NodeBB / nodebb-plugin-composer-quill

WYSIWYG composer for NodeBB based off of Quill (https://quilljs.com/)
MIT License
15 stars 11 forks source link

BUG: @textcomplete dropdown mentions and emojis not working on mouse click #341

Open cisnerosebastian opened 1 year ago

cisnerosebastian commented 1 year ago

Since nodebb update 2.6.1 (it has updates on composer default and new @textcomplete plugin) mentions and emjis dropdown item on click not working. Its working just fine if selected with keyboard and "enter" key. Its working perfect on composer default, but not on quill composer. When you click with mouse button, the composer content area scrolls up, and no autofill is done.

image

I've installed a clean new nodebb 2.6.1 , quill 3.0.2 and its not working also updated nodebb to 2.7.0 and still not working then unistalled quill, and used composer default, and its working just fine

I'm not 100% sure where to report this bug, as it can be on nodebb update, or composer-quill, or composerdefault, or maybe in the @textcomplete plugin. Let me know if I have to report this in another repo.

Thanks.

barisusakli commented 1 year ago

Looks bugged, I also get this error in the browser console sometimes

Uncaught Error: Unexpected
    at ContenteditableEditor.getRange (ContenteditableEditor.js:113:19)
    at ContenteditableEditor.getRange (ContenteditableEditor.js:117:28)
    at ContenteditableEditor.getBeforeCursor (ContenteditableEditor.js:86:28)
    at ContenteditableEditor.emitChangeEvent (Editor.js:71:36)
    at ContenteditableEditor.onInput (ContenteditableEditor.js:11:18)
Incryve commented 1 year ago

Hi there @barisusakli ! I was wondering if there has been a fix to this issue yet. My users keep drawing my attention to it and I'm hoping to address the problem asap. Thank you very much!

barisusakli commented 1 year ago

@Incryve nope, I tried to fix this but couldn't figure out the issue. Seems like textcomplete and quill don't play nice together. Selecting a option from the dropdown in textcomplete doesn't add the selected text into the quill composer.

cisnerosebastian commented 1 year ago

@barisusakli I may have some time to check on this issue. If you have any idea where the problem may be let me know.

barisusakli commented 1 year ago

Some of the related code is here https://github.com/NodeBB/nodebb-plugin-composer-quill/blob/master/static/lib/quill-nbb.js#L338-L367, it works when you press enter but mouse clicks on the dropdown doesn't work. The autocomplete module is actually in composer-default here https://github.com/NodeBB/nodebb-plugin-composer-default/blob/master/static/lib/composer/autocomplete.js#L17-L65

cisnerosebastian commented 1 year ago

@barisusakli I've been trying to understand how this works. Its like quill is intercepting keyboard and mouse events to update the quill contents and cursor. So, in this code

https://github.com/NodeBB/nodebb-plugin-composer-quill/blob/master/static/lib/quill-nbb.js#L362-L367

what is doing is like adding the tab and enter key events on the top of the list of quill events

maybe something similar is what we have to achieve with the mouse events?

On another hand, I can see that the textcomplete is actually getting the click event , and returning the right value, but that content is not been added on the quill contents.

Anyway, I will try to spend more time on this next week.

barisusakli commented 1 year ago

Yeah that's what I found out too, when you click something in the dropdown that text doesn't get inserted into the quill editor.

cisnerosebastian commented 2 months ago

Hi, it is me again. I'm still trying to fix this. So, I've made some progress, but still not 100% there yet.

This seeems more like missing functionallity than a bug.

in the default composer autocomplete.js there is a

data.element.on('textComplete:select', function () {
            preview.render(postContainer);
        });

im thinking this is the code that should print the mentions after select, but it doesn't. This is not the right event string, and preview.render does nothing on nodebb quilll plugin.

So, what I did is captured the right event, and triggered my own custom event to get the replacement done

textcomplete.on('selected', function (ev) {
            var data = ev.detail.searchResult.data;
            if (typeof data === 'string') {
                console.log('ev', ev);
                var quillElem = $(editor.el).parent();
                var quill = $(quillElem[0]).data('quill')
                var payload = {
                    quill: quill,
                    context: 'mentions',
                    original: ev.detail.searchResult.term,
                    fullreplace: slugigyFullMention(data),
                };
                $(window).trigger('action:composer.textcompleteReplace', payload);
            }
        });

        function slugigyFullMention(mention) {
            // Strip (fullname) part from mentions
            mention = mention.replace(/ \(.+\)/, '');
            mention = $('<div/>').html(mention);
            // Strip letter avatar
            mention.find('span').remove();
            let ret = '@' + slugify(mention.text(), true) + ' ';
            return ret;
        }

then on quill nodebb im trying to do the replacement, but im failing there, as I cant get the right cursor placement to replace the words. I tryied to do a full replacement in the qhole text of the quill contents, but that also not working

$(window).on('action:composer.textcompleteReplace', (evt, data) => {
        const quill = data.quill;
        const fullText = quill.getText(); // Obtenemos todo el texto del editor
        const searchText = '@' + data.original; // Texto que queremos encontrar y reemplazar

        // Función para encontrar la primera posición válida del searchText como palabra completa
        function findWholeWord(text, search) {
            let index = text.indexOf(search);
            while (index !== -1) {
                const charBefore = index > 0 ? text[index - 1] : ' ';
                const charAfter = text[index + search.length] || ' ';
                // Comprobamos si ambos caracteres antes y después no son parte de una palabra
                if (!charBefore.match(/\w/) && !charAfter.match(/\w/)) {
                    return index; // Si ambos caracteres no son alfanuméricos, es una palabra completa
                }
                // Si no, sigue buscando más adelante en el texto
                index = text.indexOf(search, index + 1);
            }
            return -1;
        }

        // Buscamos la primera ocurrencia de searchText como palabra completa en el contenido completo
        const startIndex = findWholeWord(fullText, searchText);

        if (startIndex !== -1) { // Verificamos si encontramos el texto
            const endIndex = startIndex + searchText.length;
            quill.deleteText(startIndex, searchText.length); // Borramos el texto antiguo
            quill.insertText(startIndex, data.fullreplace); // Insertamos el nuevo texto
        } else {
            console.log('Texto no encontrado para reemplazar');
        }

    });

I think I'm close, but not there yet.

maybe If I know how to do this replace properly ... not sure where the code of this replacement is on composer or quills code. I'm trying to see how you calculate the position of the old word to be replaced to then remove it and wirte the new word in its place.

any thgouhts?