diff --git a/install/package.json b/install/package.json index 3de154ee38..2404f14372 100644 --- a/install/package.json +++ b/install/package.json @@ -108,7 +108,7 @@ "nodebb-theme-lavender": "7.1.8", "nodebb-theme-peace": "2.2.6", "nodebb-theme-persona": "13.3.25", - "nodebb-widget-essentials": "7.0.18", + "nodebb-widget-essentials": "7.0.19", "nodemailer": "6.9.14", "nprogress": "0.2.0", "passport": "0.7.0", diff --git a/public/language/en-GB/modules.json b/public/language/en-GB/modules.json index 36731fe37f..3e332287d4 100644 --- a/public/language/en-GB/modules.json +++ b/public/language/en-GB/modules.json @@ -1,8 +1,9 @@ { "chat.room-id": "Room %1", "chat.chatting-with": "Chat with", - "chat.placeholder": "Type chat message here, drag & drop images, press enter to send", - "chat.placeholder.mobile": "Type chat message here", + "chat.placeholder": "Type chat message here, drag & drop images", + "chat.placeholder.mobile": "Type chat message", + "chat.placeholder.message-room": "Message #%1", "chat.scroll-up-alert": "Go to most recent message", "chat.usernames-and-x-others": "%1 & %2 others", "chat.chat-with-usernames": "Chat with %1", diff --git a/public/src/client/header/unread.js b/public/src/client/header/unread.js index 0d67c22526..d7cee4f71e 100644 --- a/public/src/client/header/unread.js +++ b/public/src/client/header/unread.js @@ -97,14 +97,16 @@ define('forum/header/unread', ['hooks'], function (hooks) { .toggleClass('hidden', count <= 0) .text(count); - // persona mobile menu uses data-content - $('#mobile-menu [data-unread-url="' + url + '"]') - .attr('data-content', countText); + if (navLink.length) { + // persona mobile menu uses data-content + $('#mobile-menu [data-unread-url="' + url + '"]') + .attr('data-content', countText); - // harmony mobile unread badge, doesn't use data-content - $('[component="unread/count"][data-unread-url="' + url + '"]') - .toggleClass('hidden', count <= 0) - .text(countText); + // harmony mobile unread badge, doesn't use data-content + $('[component="unread/count"][data-unread-url="' + url + '"]') + .toggleClass('hidden', count <= 0) + .text(countText); + } hooks.fire('action:unread.updateCount', { url, count }); } diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index 0794af22a8..c48113d2f7 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -1,10 +1,9 @@ 'use strict'; define('chat', [ - 'components', 'taskbar', 'translator', 'hooks', 'bootbox', 'alerts', 'api', -], function (components, taskbar, translator, hooks, bootbox, alerts, api) { + 'components', 'taskbar', 'translator', 'hooks', 'bootbox', 'alerts', 'api', 'scrollStop', +], function (components, taskbar, translator, hooks, bootbox, alerts, api, scrollStop) { const module = {}; - let newMessage = false; module.openChat = function (roomId, uid) { if (!app.user.uid) { @@ -182,9 +181,11 @@ define('chat', [ return; } if (module.modalExists(data.roomId)) { + const modal = module.getModal(data.roomId); + const newMessage = parseInt(modal.attr('new-message'), 10) === 1; data.self = parseInt(app.user.uid, 10) === parseInt(data.fromUid, 10) ? 1 : 0; if (!newMessage) { - newMessage = data.self === 0; + modal.attr('new-message', data.self === 0 ? 1 : 0); } data.message.self = data.self; data.message.timestamp = Math.min(Date.now(), data.message.timestamp); @@ -290,11 +291,60 @@ define('chat', [ return $('#chat-modal-' + roomId).length !== 0; }; + module.initWidget = function (roomId, chatModal) { + require(['forum/chats', 'forum/chats/messages'], function (Chats, ChatsMessages) { + socket.emit('modules.chats.enter', roomId); + api.del(`/chats/${roomId}/state`, {}); + + chatModal.find('.timeago').timeago(); + chatModal.find('[data-bs-toggle="tooltip"]').tooltip({ + trigger: 'hover', container: '#content', + }); + ChatsMessages.wrapImagesInLinks(chatModal.find('[component="chat/messages"] .chat-content')); + + scrollStop.apply(chatModal.find('[component="chat/messages"] .chat-content')); + + chatModal.on('mousemove keypress click', function () { + if (parseInt(chatModal.attr('new-message'), 10) === 1) { + api.del(`/chats/${roomId}/state`, {}); + chatModal.removeAttr('new-message'); + } + }); + + Chats.addActionHandlers(chatModal.find('[component="chat/message/window"]'), roomId); + Chats.addSendHandlers(roomId, chatModal.find('.chat-input'), chatModal.find('[data-action="send"]')); + + Chats.createAutoComplete(roomId, chatModal.find('[component="chat/input"]')); + + Chats.addScrollHandler(roomId, app.user.uid, chatModal.find('[component="chat/message/content"]')); + Chats.addScrollBottomHandler(roomId, chatModal.find('[component="chat/message/content"]')); + Chats.addParentHandler(chatModal.find('[component="chat/message/content"]')); + Chats.addCharactersLeftHandler(chatModal); + Chats.addTextareaResizeHandler(chatModal); + Chats.addTypingHandler(chatModal, roomId); + Chats.addIPHandler(chatModal); + Chats.addTooltipHandler(chatModal); + Chats.addUploadHandler({ + dragDropAreaEl: chatModal.find('.modal-content'), + pasteEl: chatModal, + uploadFormEl: chatModal.find('[component="chat/upload"]'), + uploadBtnEl: chatModal.find('[component="chat/upload/button"]'), + inputEl: chatModal.find('[component="chat/input"]'), + }); + + ChatsMessages.addSocketListeners(); + + ChatsMessages.scrollToBottomAfterImageLoad(chatModal.find('.chat-content')); + + hooks.fire('action:chat.loaded', chatModal); + }); + }; + module.createModal = function (data, callback) { callback = callback || function () {}; require([ - 'scrollStop', 'forum/chats', 'forum/chats/messages', 'forum/chats/message-search', - ], function (scrollStop, Chats, ChatsMessages, messageSearch) { + 'forum/chats', 'forum/chats/messages', 'forum/chats/message-search', + ], function (Chats, ChatsMessages, messageSearch) { app.parseAndTranslate('chat', data, function (chatModal) { const roomId = data.roomId; if (module.modalExists(roomId)) { @@ -305,45 +355,19 @@ define('chat', [ chatModal.attr('id', 'chat-modal-' + roomId); chatModal.attr('data-roomid', roomId); - chatModal.attr('intervalId', 0); chatModal.attr('data-uuid', uuid); chatModal.css('position', 'fixed'); chatModal.appendTo($('body')); chatModal.find('.timeago').timeago(); chatModal.find('[data-bs-toggle="tooltip"]').tooltip({ trigger: 'hover', container: '#content' }); ChatsMessages.wrapImagesInLinks(chatModal.find('[component="chat/messages"] .chat-content')); - module.center(chatModal); - - app.loadJQueryUI(function () { - chatModal.find('.modal-content').resizable({ - handles: 'n, e, s, w, se', - minHeight: 250, - minWidth: 400, - }); - - chatModal.find('.modal-content').on('resize', function (event, ui) { - if (ui.originalSize.height === ui.size.height) { - return; - } - - chatModal.find('.modal-body').css('height', module.calculateChatListHeight(chatModal)); - }); - - chatModal.draggable({ - start: function () { - taskbar.updateActive(uuid); - chatModal.css({ bottom: 'auto', right: 'auto' }); - }, - stop: function () { - module.focusInput(chatModal); - }, - distance: 10, - handle: '.modal-header', - }); - }); scrollStop.apply(chatModal.find('[component="chat/messages"] .chat-content')); + module.center(chatModal); + + makeModalResizeableDraggable(chatModal, uuid); + chatModal.find('#chat-close-btn').on('click', function () { module.close(uuid); }); @@ -380,9 +404,9 @@ define('chat', [ }); chatModal.on('mousemove keypress click', function () { - if (newMessage) { + if (parseInt(chatModal.attr('new-message'), 10) === 1) { api.del(`/chats/${roomId}/state`, {}); - newMessage = false; + chatModal.removeAttr('new-message'); } }); @@ -433,6 +457,36 @@ define('chat', [ }); }; + function makeModalResizeableDraggable(chatModal, uuid) { + app.loadJQueryUI(function () { + chatModal.find('.modal-content').resizable({ + handles: 'n, e, s, w, se', + minHeight: 250, + minWidth: 400, + }); + + chatModal.find('.modal-content').on('resize', function (event, ui) { + if (ui.originalSize.height === ui.size.height) { + return; + } + + chatModal.find('.modal-body').css('height', module.calculateChatListHeight(chatModal)); + }); + + chatModal.draggable({ + start: function () { + taskbar.updateActive(uuid); + chatModal.css({ bottom: 'auto', right: 'auto' }); + }, + stop: function () { + module.focusInput(chatModal); + }, + distance: 10, + handle: '.modal-header', + }); + }); + } + module.focusInput = function (chatModal) { setTimeout(function () { chatModal.find('[component="chat/input"]').focus(); @@ -441,8 +495,6 @@ define('chat', [ module.close = function (uuid) { const chatModal = $('.chat-modal[data-uuid="' + uuid + '"]'); - clearInterval(chatModal.attr('intervalId')); - chatModal.attr('intervalId', 0); chatModal.remove(); chatModal.data('modal', null); taskbar.discard('chat', uuid); @@ -529,8 +581,6 @@ define('chat', [ const chatModal = $('.chat-modal[data-uuid="' + uuid + '"]'); chatModal.addClass('hide'); taskbar.minimize('chat', uuid); - clearInterval(chatModal.attr('intervalId')); - chatModal.attr('intervalId', 0); hooks.fire('action:chat.minimized', { uuid: uuid, modal: chatModal, diff --git a/src/views/partials/chats/composer.tpl b/src/views/partials/chats/composer.tpl index cae9634f9a..d80c9337d5 100644 --- a/src/views/partials/chats/composer.tpl +++ b/src/views/partials/chats/composer.tpl @@ -5,7 +5,7 @@