diff --git a/install/package.json b/install/package.json index 4a21993a69..391a7f14e6 100644 --- a/install/package.json +++ b/install/package.json @@ -72,6 +72,7 @@ "graceful-fs": "4.2.11", "helmet": "7.0.0", "html-to-text": "9.0.5", + "imagesloaded": "5.0.0", "ipaddr.js": "2.1.0", "jquery": "3.7.0", "jquery-deserialize": "2.0.0", diff --git a/public/src/client/chats.js b/public/src/client/chats.js index c8743f9d80..997092b53e 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -62,8 +62,9 @@ define('forum/chats', [ } Chats.initialised = true; - messages.scrollToBottom($('[component="chat/message/content"]')); - messages.wrapImagesInLinks($('[component="chat/message/content"]')); + const changeContentEl = $('[component="chat/message/content"]'); + messages.wrapImagesInLinks(changeContentEl); + messages.scrollToBottomAfterImageLoad(changeContentEl); create.init(); hooks.fire('action:chat.loaded', $('.chats-full')); @@ -283,11 +284,12 @@ define('forum/chats', [ // https://stackoverflow.com/questions/454202/creating-a-textarea-with-auto-resize const textarea = parent.find('[component="chat/input"]'); textarea.on('input', function () { - const isAtBottom = messages.isAtBottom(parent.find('[component="chat/message/content"]')); + const chatContentEl = parent.find('[component="chat/message/content"]'); + const isAtBottom = messages.isAtBottom(chatContentEl); textarea.css({ height: 0 }); textarea.css({ height: messages.calcAutoTextAreaHeight(textarea) + 'px' }); if (isAtBottom) { - messages.scrollToBottom(parent.find('[component="chat/message/content"]')); + messages.scrollToBottom(chatContentEl); } }); }; @@ -526,7 +528,7 @@ define('forum/chats', [ Chats.setActive(roomId); Chats.addEventListeners(); hooks.fire('action:chat.loaded', $('.chats-full')); - messages.scrollToBottom(mainWrapper.find('[component="chat/message/content"]')); + messages.scrollToBottomAfterImageLoad(mainWrapper.find('[component="chat/message/content"]')); if (history.pushState) { history.pushState({ url: url, diff --git a/public/src/client/chats/messages.js b/public/src/client/chats/messages.js index fc875fea04..f8adbeae5e 100644 --- a/public/src/client/chats/messages.js +++ b/public/src/client/chats/messages.js @@ -3,9 +3,9 @@ define('forum/chats/messages', [ 'components', 'hooks', 'bootbox', 'alerts', - 'messages', 'api', 'forum/topic/images', + 'messages', 'api', 'forum/topic/images', 'imagesloaded', ], function ( - components, hooks, bootbox, alerts, messagesModule, api, images + components, hooks, bootbox, alerts, messagesModule, api, images, imagesLoaded ) { const messages = {}; @@ -95,7 +95,7 @@ define('forum/chats/messages', [ newMessage.appendTo(chatContentEl); messages.onMessagesAddedToDom(newMessage); if (isAtBottom || msgData.self) { - messages.scrollToBottom(chatContentEl); + messages.scrollToBottomAfterImageLoad(chatContentEl); // remove some message elements if there are too many const chatMsgEls = chatContentEl.find('[data-mid]'); if (chatMsgEls.length > 150) { @@ -137,6 +137,14 @@ define('forum/chats/messages', [ return distanceToBottom < (threshold || 100); } }; + messages.scrollToBottomAfterImageLoad = function (containerEl) { + if (containerEl && containerEl.length) { + const msgBodyEls = containerEl[0].querySelectorAll('[component="chat/message/body"]'); + imagesLoaded(msgBodyEls, () => { + messages.scrollToBottom(containerEl); + }); + } + }; messages.scrollToBottom = function (containerEl) { if (containerEl && containerEl.length) { diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index 31f81927a0..23e0b67f6b 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -209,7 +209,7 @@ define('chat', [ if (modal.is(':visible')) { taskbar.updateActive(modal.attr('data-uuid')); if (ChatsMessages.isAtBottom(modal.find('[component="chat/message/content"]'))) { - ChatsMessages.scrollToBottom(modal.find('[component="chat/message/content"]')); + ChatsMessages.scrollToBottomAfterImageLoad(modal.find('[component="chat/message/content"]')); } } else if (!ajaxify.data.template.chats) { module.toggleNew(modal.attr('data-uuid'), true, true); @@ -453,7 +453,7 @@ define('chat', [ const chatModal = $('.chat-modal[data-uuid="' + uuid + '"]'); chatModal.removeClass('hide'); taskbar.updateActive(uuid); - ChatsMessages.scrollToBottom(chatModal.find('.chat-content')); + ChatsMessages.scrollToBottomAfterImageLoad(chatModal.find('.chat-content')); module.focusInput(chatModal); const roomId = chatModal.attr('data-roomid'); api.del(`/chats/${roomId}/state`, {});