nodebb-shoutbox-plugin: how to add @mention completion and emoji completion in the plugin
-
Hello,
I am modifying for my personal use the nodebb-plugin-shoutbox plugin : https://github.com/NodeBB-Community/nodebb-plugin-shoutbox
I finished the French translation and I proposed it on the github.
On the other hand, the translation of the admin.json & shoutbox.json files on language directory is not enough.
You have to modify the text of other files for a complete translation.I managed to modify the default commands and add new ones (text and sound) but there are 2 things I can't do for now, hence the creation of this topic :
-
- Add @mention user completion :
-
- add emojis completion :
--> If anyone could help me on these 2 topics or direct me to the right approach, I would be grateful.
Have a nice day
-
-
thought about using the nodebb-plugin-mention plugin but I'm not sure how to integrate it.
for the completion of the emoji I don't really know.
-
Anyone ?
-
Take a look at how it is done for chats.
NodeBB/public/src/client/chats.js at master · NodeBB/NodeBB
Node.js based forum software built for the modern web - NodeBB/public/src/client/chats.js at master · NodeBB/NodeBB
GitHub (github.com)
You can probably use this same code but pass in the text input element of the shoutbox.
-
Thanks @baris
Hmm I will test things with that.
Maybe here it's a good start ?nodebb-plugin-shoutbox/public/js/lib/actions/default.js at master · NodeBB-Community/nodebb-plugin-shoutbox
NodeBB Shoutbox plugin. Contribute to NodeBB-Community/nodebb-plugin-shoutbox development by creating an account on GitHub.
GitHub (github.com)
-
I Test this but doesn't work @baris :
'use strict'; (function (Shoutbox) { var Instance = function (container, options) { var self = this; this.options = options || {}; setupDom.apply(this, [container]); setupVars.apply(this); setupDependencies.apply(this); this.settings.load(); getShouts(); window.sb = this; function getShouts() { self.sockets.getShouts(function (err, shouts) { if (err) { return app.alertError(err); } shouts = shouts.filter(function (el) { return el !== null; }); if (shouts.length === 0) { self.utils.showOverlay(self.vars.messages.empty); } else { self.addShouts(shouts); } }); } Chats.createAutoComplete = function (element) { if (!element.length) { return; } const data = { element: element, strategies: [], options: { style: { 'z-index': 20000, flex: 0, top: 'inherit', }, placement: 'top', }, }; $(window).trigger('chat:autocomplete:init', data); if (data.strategies.length) { autocomplete.setup(data); } }; }; function setupDependencies() { this.utils = Shoutbox.utils.init(this); this.sockets = Shoutbox.sockets.init(this); this.settings = Shoutbox.settings.init(this); this.actions = Shoutbox.actions.init(this); this.commands = Shoutbox.commands.init(this); } Instance.prototype.addShouts = function (shouts) { if (!shouts.length) { return; } var self = this; var lastUid = this.vars.lastUid; var lastSid = this.vars.lastSid; var uid; var sid; for (let i = shouts.length - 1; i > 0; i -= 1) { var s = shouts[i]; var prev = shouts[i - 1]; if (parseInt(s.fromuid, 10) === parseInt(prev.fromuid, 10)) { prev.timestamp = s.timestamp; } } shouts = shouts.map(function (el) { uid = parseInt(el.fromuid, 10); sid = parseInt(el.sid, 10); // Own shout el.isOwn = parseInt(app.user.uid, 10) === uid; // Permissions el.user.isMod = el.isOwn || app.user.isAdmin || app.user.isGlobalMod; // Add shout chain information to shout el.isChained = lastUid === uid; // Add timeString to shout // jQuery.timeago only works properly with ISO timestamps el.timeString = (new Date(parseInt(el.timestamp, 10)).toISOString()); // Extra classes el.typeClasses = el.isOwn ? 'shoutbox-shout-self ' : ''; el.typeClasses += el.user.isAdmin ? 'shoutbox-shout-admin ' : ''; lastUid = uid; lastSid = sid; return el; }); this.vars.lastUid = lastUid; this.vars.lastSid = lastSid; app.parseAndTranslate('shoutbox/shouts', { shouts: shouts, }, function (html) { self.dom.shoutsContainer.append(html); html.find('.timeago').timeago(); self.utils.scrollToBottom(shouts.length > 1); }); }; Instance.prototype.updateUserStatus = function (uid, status) { var self = this; var setStatus = function (uid, status) { self.dom.shoutsContainer.find('[data-uid="' + uid + '"].shoutbox-avatar').removeClass().addClass('shoutbox-avatar ' + status); }; var getStatus = function (uid) { self.sockets.getUserStatus(uid, function (err, data) { if (err) { return app.alertError(err); } setStatus(uid, data.status); }); }; if (!uid) { uid = []; self.dom.shoutsContainer.find('[data-uid].shoutbox-avatar').each(function (index, el) { uid.push($(el).data('uid')); }); uid = uid.filter(function (el, index) { return uid.indexOf(el) === index; }); } if (!status) { if (typeof uid === 'number') { getStatus(uid); } else if (Array.isArray(uid)) { for (let i = 0, l = uid.length; i < l; i++) { getStatus(uid[i]); } } } else if (typeof uid === 'number') { setStatus(uid, status); } else if (Array.isArray(uid)) { for (let i = 0, l = uid.length; i < l; i++) { setStatus(uid[i], status); } } }; Instance.prototype.showUserPanel = function () { this.dom.onlineUsers.parent().removeClass('hidden'); }; Instance.prototype.hideUserPanel = function () { this.dom.onlineUsers.parent().addClass('hidden'); }; Instance.prototype.startUserPanelUpdater = function () { var self = this; update(); function update() { this.sockets.getUsers({ set: 'users:online', after: 0 }, function (err, data) { if (err) { return app.alertError(err); } var userCount = data.users.length; var usernames = data.users.map(function (i) { return (i.username === null ? 'Anonymous' : i.username); }); var userString = usernames.join('; '); self.dom.onlineUsers.find('.panel-body').text(userString); self.dom.onlineUsers.find('.panel-title').text('Users (' + userCount + ')'); }); setInterval(update, 10000); } }; function setupDom(container) { this.dom = {}; this.dom.container = container; this.dom.overlay = container.find('.shoutbox-content-overlay'); this.dom.overlayMessage = this.dom.overlay.find('.shoutbox-content-overlay-message'); this.dom.shoutsContainer = container.find('.shoutbox-content'); this.dom.settingsMenu = container.find('.shoutbox-settings-menu'); this.dom.textInput = container.find('.shoutbox-message-input'); this.dom.sendButton = container.find('.shoutbox-message-send-btn'); this.dom.onlineUsers = container.parents('.shoutbox-row').find('.shoutbox-users'); if (this.options.showUserPanel) { this.showUserPanel(); this.startUserPanelUpdater(); } } function setupVars() { this.vars = { lastUid: -1, lastSid: -1, scrollBreakpoint: 50, messages: { alert: '[%u] - New Msg !', empty: 'La shoutbox est vide, commencez à discuter !', scrolled: '<a href="#" id="shoutbox-content-overlay-scrolldown">Défiler vers le bas</a>', }, userCheck: 0, }; } Shoutbox.base = { init: function (container, options) { return new Instance(container, options); }, }; }(window.Shoutbox));
Continue to search
-
-
Ok my lord
-
Hello @baris
Thanks again.
For information, it seems 9.2.5 version is not proposed by default when I use an npm upgrade command :
npm update nodebb-plugin-composer-default
I must use install command specifying the version number :
npm install [email protected]
Otherwise, I have just modified the placement of auto-complete on top rather than bottom.
I find it more elegant. Like this, it does not protrude from the shoutbox. Maybe include it in the github repo ?require(['composer/autocomplete'], function (autocomplete) { const data = { element: element, strategies: [], options: { style: { 'z-index': 20000, flex: 0, top: 'inherit', }, placement: 'top', }, };
--> Other things : do you think it's easy for me to integrate a hook for another plugin?
-
-
Hello @baris
We have upgrade nodebb 2.8.6 to 2.8.9 and it seems that functionnality is broken now.
Any suggestion for resolve that ?- nodebb 2.8.9
- nodebb-plugin-composer-default 9.2.5
- nodebb-plugin-shoutbox 1.0.8
thanks in advance my friend