From 20fd75bf76b2d31b75fabd8e15de093b08a1c37f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Fri, 13 Sep 2024 12:43:40 -0400 Subject: [PATCH] refactor: move textcomplete to core --- install/package.json | 3 +++ public/src/client/chats.js | 2 +- public/src/modules/autocomplete.js | 36 +++++++++++++++++++++++++++++- public/src/modules/quickreply.js | 14 +++++++----- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/install/package.json b/install/package.json index 259c483d32..76831b33b9 100644 --- a/install/package.json +++ b/install/package.json @@ -35,6 +35,9 @@ "@isaacs/ttlcache": "1.4.1", "@nodebb/spider-detector": "2.0.3", "@popperjs/core": "2.11.8", + "@textcomplete/contenteditable": "0.1.13", + "@textcomplete/core": "0.1.13", + "@textcomplete/textarea": "0.1.13", "ace-builds": "1.36.2", "archiver": "7.0.1", "async": "3.2.6", diff --git a/public/src/client/chats.js b/public/src/client/chats.js index 1570872d62..4181bd79cb 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -11,7 +11,7 @@ define('forum/chats', [ 'forum/chats/user-list', 'forum/chats/message-search', 'forum/chats/pinned-messages', - 'composer/autocomplete', + 'autocomplete', 'hooks', 'bootbox', 'alerts', diff --git a/public/src/modules/autocomplete.js b/public/src/modules/autocomplete.js index 277859ce3d..13e4e56427 100644 --- a/public/src/modules/autocomplete.js +++ b/public/src/modules/autocomplete.js @@ -1,6 +1,8 @@ 'use strict'; -define('autocomplete', ['api', 'alerts'], function (api, alerts) { +define('autocomplete', [ + 'api', 'alerts', '@textcomplete/core', '@textcomplete/textarea', '@textcomplete/contenteditable', +], function (api, alerts, { Textcomplete }, { TextareaEditor }, { ContenteditableEditor }) { const autocomplete = {}; const _default = { delay: 200, @@ -129,5 +131,37 @@ define('autocomplete', ['api', 'alerts'], function (api, alerts) { onselect(event, ui); } + // This is a generic method that is also used by the chat + autocomplete.setup = function ({ element, strategies, options }) { + const targetEl = element.get(0); + if (!targetEl) { + return; + } + var editor; + if (targetEl.nodeName === 'TEXTAREA' || targetEl.nodeName === 'INPUT') { + editor = new TextareaEditor(targetEl); + } else if (targetEl.nodeName === 'DIV' && targetEl.getAttribute('contenteditable') === 'true') { + editor = new ContenteditableEditor(targetEl); + } + if (!editor) { + throw new Error('unknown target element type'); + } + // yuku-t/textcomplete inherits directionality from target element itself + targetEl.setAttribute('dir', document.querySelector('html').getAttribute('data-dir')); + + var textcomplete = new Textcomplete(editor, strategies, { + dropdown: options, + }); + textcomplete.on('rendered', function () { + if (textcomplete.dropdown.items.length) { + // Activate the first item by default. + textcomplete.dropdown.items[0].activate(); + } + }); + + return textcomplete; + }; + + return autocomplete; }); diff --git a/public/src/modules/quickreply.js b/public/src/modules/quickreply.js index 45ac9d5265..563ee486f8 100644 --- a/public/src/modules/quickreply.js +++ b/public/src/modules/quickreply.js @@ -1,13 +1,15 @@ 'use strict'; define('quickreply', [ - 'components', 'composer/autocomplete', 'api', + 'components', 'autocomplete', 'api', 'alerts', 'uploadHelpers', 'mousetrap', 'storage', 'hooks', ], function ( components, autocomplete, api, alerts, uploadHelpers, mousetrap, storage, hooks ) { - const QuickReply = {}; + const QuickReply = { + _active: {}, + }; QuickReply.init = function () { const element = components.get('topic/quickreply/text'); @@ -27,7 +29,7 @@ define('quickreply', [ destroyAutoComplete(); }); $(window).trigger('composer:autocomplete:init', data); - autocomplete._active.core_qr = autocomplete.setup(data); + QuickReply._active.core_qr = autocomplete.setup(data); mousetrap.bind('ctrl+return', (e) => { if (e.target === element.get(0)) { @@ -123,9 +125,9 @@ define('quickreply', [ }; function destroyAutoComplete() { - if (autocomplete._active.core_qr) { - autocomplete._active.core_qr.destroy(); - autocomplete._active.core_qr = null; + if (QuickReply._active.core_qr) { + QuickReply._active.core_qr.destroy(); + QuickReply._active.core_qr = null; } }