diff --git a/plugins/plugins/core/components/ChatPage.js b/plugins/plugins/core/components/ChatPage.js index dbd11b11..1d256e69 100644 --- a/plugins/plugins/core/components/ChatPage.js +++ b/plugins/plugins/core/components/ChatPage.js @@ -55,7 +55,7 @@ const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) export const queue = new RequestQueue(); -export const chatLimit = 10 +export const chatLimit = 40 class ChatPage extends LitElement { static get properties() { return { @@ -1282,6 +1282,7 @@ class ChatPage extends LitElement { constructor() { super() this.getOldMessage = this.getOldMessage.bind(this) + this.clearUpdateMessageHashmap = this.clearUpdateMessageHashmap.bind(this) this._sendMessage = this._sendMessage.bind(this) this.insertFile = this.insertFile.bind(this) this.pasteImage = this.pasteImage.bind(this) @@ -2138,6 +2139,7 @@ class ChatPage extends LitElement { } async goToRepliedMessage(message, clickedOnMessage) { + console.log({message}) const findMessage = this.shadowRoot.querySelector('chat-scroller').shadowRoot.getElementById(message.signature) if (findMessage) { @@ -2165,24 +2167,21 @@ class ChatPage extends LitElement { } await this.getOldMessageDynamic(0, clickedOnMessage.timestamp, message) - await new Promise((res)=> { - setTimeout(()=> { - res() - },1000) - }) - await this.getUpdateCompleteMessages() + await this.getUpdateComplete() const marginElements = Array.from(this.shadowRoot.querySelector('chat-scroller').shadowRoot.querySelectorAll('message-template')) - const findMessage = marginElements.find((item) => item.messageObj.signature === message.signature) - if (findMessage) { - findMessage.scrollIntoView({ behavior: 'auto', block: 'center' }) + console.log({marginElements}) + const findMessage2 = marginElements.find((item) => item.messageObj.signature === message.signature) || marginElements.find((item) => item.messageObj.originalSignature === message.signature) || marginElements.find((item) => item.messageObj.signature === message.originalSignature) || marginElements.find((item) => item.messageObj.originalSignature === message.originalSignature) + console.log({findMessage2}, message.signature) + if (findMessage2) { + findMessage2.scrollIntoView({ block: 'center' }) } - if (findMessage) { + if (findMessage2) { this.isLoadingGoToRepliedMessage = { ...this.isLoadingGoToRepliedMessage, loading: false } - const findElement = findMessage.shadowRoot.querySelector('.message-parent') + const findElement = findMessage2.shadowRoot.querySelector('.message-parent') if (findElement) { findElement.classList.add('blink-bg') setTimeout(() => { @@ -2515,6 +2514,7 @@ class ChatPage extends LitElement { } renderChatScroller() { + console.log('clearUpdateMessageHashmap', Object.keys(this.updateMessageHash).length) return html` this.goToRepliedMessage(val, val2)} .updateMessageHash=${this.updateMessageHash} + .clearUpdateMessageHashmap=${this.clearUpdateMessageHashmap} > ` @@ -2585,7 +2586,7 @@ class ChatPage extends LitElement { async getOldMessageDynamic(limit, timestampClickedOnMessage, messageToGoTo) { const findMsg = await parentEpml.request("apiCall", { type: "api", - url: `/chat/message/${messageToGoTo.signature}?encoding=BASE64`, + url: `/chat/message/${messageToGoTo.originalSignature || messageToGoTo.signature}?encoding=BASE64`, }) if(!findMsg) return null if (this.isReceipient) { @@ -2595,7 +2596,7 @@ class ChatPage extends LitElement { }) const getInitialMessagesAfter = await parentEpml.request('apiCall', { type: 'api', - url: `/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${this._chatId}&limit=${20}&reverse=true&after=${findMsg.timestamp - 100}&haschatreference=false&encoding=BASE64` + url: `/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${this._chatId}&limit=${20}&reverse=false&after=${findMsg.timestamp - 1000}&haschatreference=false&encoding=BASE64` }) const getInitialMessages = [...getInitialMessagesBefore, ...getInitialMessagesAfter] let decodeMsgs = [] @@ -2624,7 +2625,8 @@ class ChatPage extends LitElement { addToUpdateMessageHashmap: this.addToUpdateMessageHashmap })); - + console.log({decodeMsgs}) + let list = [...decodeMsgs] await new Promise((res, rej) => { @@ -2643,6 +2645,7 @@ class ChatPage extends LitElement { this.messagesRendered = { messages: list, type: 'inBetween', + message: messageToGoTo } this.isLoadingOldMessages = false @@ -2654,7 +2657,7 @@ class ChatPage extends LitElement { }) const getInitialMessagesAfter = await parentEpml.request('apiCall', { type: 'api', - url: `/chat/messages?txGroupId=${Number(this._chatId)}&limit=${20}&reverse=true&after=${findMsg.timestamp - 100}&haschatreference=false&encoding=BASE64` + url: `/chat/messages?txGroupId=${Number(this._chatId)}&limit=${20}&reverse=false&after=${findMsg.timestamp - 1000}&haschatreference=false&encoding=BASE64` }) const getInitialMessages = [...getInitialMessagesBefore, ...getInitialMessagesAfter] @@ -2683,7 +2686,7 @@ class ChatPage extends LitElement { addToUpdateMessageHashmap: this.addToUpdateMessageHashmap })); - + console.log({decodeMsgs}) let list = [...decodeMsgs] @@ -2842,7 +2845,7 @@ class ChatPage extends LitElement { if (this.isReceipient) { const getInitialMessages = await parentEpml.request('apiCall', { type: 'api', - url: `/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${this._chatId}&limit=20&reverse=true&after=${timestamp}&haschatreference=false&encoding=BASE64` + url: `/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${this._chatId}&limit=${chatLimit}&reverse=false&after=${timestamp}&haschatreference=false&encoding=BASE64` }) let decodeMsgs = [] @@ -2904,7 +2907,7 @@ class ChatPage extends LitElement { } else { const getInitialMessages = await parentEpml.request('apiCall', { type: 'api', - url: `/chat/messages?txGroupId=${Number(this._chatId)}&limit=20&reverse=true&after=${timestamp}&haschatreference=false&encoding=BASE64` + url: `/chat/messages?txGroupId=${Number(this._chatId)}&limit=${chatLimit}&reverse=false&after=${timestamp}&haschatreference=false&encoding=BASE64` }) let decodeMsgs = [] await new Promise((res, rej) => { @@ -2959,7 +2962,6 @@ class ChatPage extends LitElement { await this.getUpdateComplete() const marginElements = Array.from(this.shadowRoot.querySelector('chat-scroller').shadowRoot.querySelectorAll('message-template')) const findElement = marginElements.find((item) => item.messageObj.signature === scrollElement.messageObj.signature) - if (findElement) { findElement.scrollIntoView({ behavior: 'auto', block: 'center' }) } @@ -2984,8 +2986,14 @@ const originalScrollHeight = viewElement.scrollHeight; ...newObj } await this.getUpdateComplete() - const heightDifference = viewElement.scrollHeight - originalScrollHeight; -viewElement.scrollTop = originalScrollTop + heightDifference; +// const heightDifference = viewElement.scrollHeight - originalScrollHeight; +// viewElement.scrollTop = originalScrollTop + heightDifference; + } + + async clearUpdateMessageHashmap(){ + console.log('hello clear') + this.updateMessageHash = {} + this.requestUpdate() } diff --git a/plugins/plugins/core/components/ChatScroller.js b/plugins/plugins/core/components/ChatScroller.js index 6239db60..8ea34681 100644 --- a/plugins/plugins/core/components/ChatScroller.js +++ b/plugins/plugins/core/components/ChatScroller.js @@ -237,7 +237,8 @@ class ChatScroller extends LitElement { listSeenMessages: { type: Array }, updateMessageHash: { type: Object }, messagesToRender: { type: Array }, - oldMessages: { type: Array } + oldMessages: { type: Array }, + clearUpdateMessageHashmap: { attribute: false} } } @@ -263,11 +264,16 @@ class ChatScroller extends LitElement { this.listSeenMessages = [] this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' this.messagesToRender = [] + this.disableFetching = false } addSeenMessage(val) { this.listSeenMessages.push(val) } + goToRepliedMessageFunc(val, val2){ + this.disableFetching = true + this.goToRepliedMessage(val, val2) + } shouldGroupWithLastMessage(newMessage, lastGroupedMessage) { if (!lastGroupedMessage) return false; @@ -289,12 +295,15 @@ class ChatScroller extends LitElement { } this.requestUpdate(); + this.disableFetching = false } - async newListMessages(newMessages, signature) { + async newListMessages(newMessages, message) { + this.disableFetching = true console.log('sup') let data = [] - newMessages.forEach(newMessage => { + const copy = [...newMessages] + copy.forEach(newMessage => { const lastGroupedMessage = data[data.length - 1]; if (this.shouldGroupWithLastMessage(newMessage, lastGroupedMessage)) { @@ -307,49 +316,95 @@ class ChatScroller extends LitElement { } }); - + console.log({data}) this.messagesToRender = data + this.disableFetching = false this.requestUpdate() - + await this.updateComplete() + + this.setIsLoadingMessages(false); + + + + + } - async addNewMessages(newMessages, type) { - console.log('sup') - newMessages.forEach(newMessage => { - const lastGroupedMessage = this.messagesToRender[this.messagesToRender.length - 1]; + + + async addNewMessages(newMessages, type) { + let previousScrollTop; + let previousScrollHeight; + + const viewElement = this.shadowRoot.querySelector("#viewElement"); + previousScrollTop = viewElement.scrollTop; + previousScrollHeight = viewElement.scrollHeight; + this.disableFetching = true + + console.log('sup', type); + const copy = [...this.messagesToRender] + + for (const newMessage of newMessages) { + const lastGroupedMessage = copy[copy.length - 1]; + if (this.shouldGroupWithLastMessage(newMessage, lastGroupedMessage)) { lastGroupedMessage.messages.push(newMessage); } else { - this.messagesToRender.push({ + copy.push({ messages: [newMessage], ...newMessage }); } - }); - - this.requestUpdate(); - if(type === 'initial'){ - await this.getUpdateComplete(); - setTimeout(() => { - this.viewElement.scrollTop = this.viewElement.scrollHeight + 50; - this.setIsLoadingMessages(false) - }, 50) } - + + + // Ensure that the total number of individual messages doesn't exceed 80 + let totalMessagesCount = copy.reduce((acc, group) => acc + group.messages.length, 0); + while (totalMessagesCount > 80 && copy.length) { + const firstGroup = copy[0]; + if (firstGroup.messages.length <= (totalMessagesCount - 80)) { + // If removing the whole first group achieves the goal, remove it + totalMessagesCount -= firstGroup.messages.length; + copy.shift(); + } else { + // Otherwise, trim individual messages from the first group + const messagesToRemove = totalMessagesCount - 80; + firstGroup.messages.splice(0, messagesToRemove); + totalMessagesCount = 80; + } + } + this.messagesToRender = copy + this.requestUpdate(); + console.log("Before waiting for updateComplete"); + await this.updateComplete; + console.log("After waiting for updateComplete"); + + if (type === 'initial') { + + this.viewElement.scrollTop = this.viewElement.scrollHeight + this.setIsLoadingMessages(false); + + + } else { + this.setIsLoadingMessages(false); + + } + this.disableFetching = false } + async prependOldMessages(oldMessages) { - - console.log('2', { oldMessages }) + console.log('2', { oldMessages }); + this.disableFetching = true if (!this.messagesToRender) this.messagesToRender = []; // Ensure it's initialized - + let currentMessageGroup = null; let previousMessage = null; - + for (const message of oldMessages) { if (!previousMessage || !this.shouldGroupWithLastMessage(message, previousMessage)) { // If no previous message, or if the current message shouldn't be grouped with the previous, @@ -368,28 +423,75 @@ class ChatScroller extends LitElement { } previousMessage = message; } - + // After processing all old messages, add the last group if (currentMessageGroup) { this.messagesToRender.unshift(currentMessageGroup); } - - this.requestUpdate(); - this.setIsLoadingMessages(false) - } - - async replaceMessagesWithUpdate(updatedMessages) { - for (let group of this.messagesToRender) { - for (let i = 0; i < group.messages.length; i++) { - if (updatedMessages[group.messages[i].signature]) { - Object.assign(group.messages[i], updatedMessages[group.messages[i].signature]); - } + + // Ensure that the total number of individual messages doesn't exceed 80 + let totalMessagesCount = this.messagesToRender.reduce((acc, group) => acc + group.messages.length, 0); + while (totalMessagesCount > 80 && this.messagesToRender.length) { + const lastGroup = this.messagesToRender[this.messagesToRender.length - 1]; + if (lastGroup.messages.length <= (totalMessagesCount - 80)) { + // If removing the whole last group achieves the goal, remove it + totalMessagesCount -= lastGroup.messages.length; + this.messagesToRender.pop(); + } else { + // Otherwise, trim individual messages from the last group + const messagesToRemove = totalMessagesCount - 80; + lastGroup.messages.splice(-messagesToRemove, messagesToRemove); + totalMessagesCount = 80; } } + this.requestUpdate(); + this.setIsLoadingMessages(false); + this.disableFetching = false } + + + async replaceMessagesWithUpdate(updatedMessages) { + const viewElement = this.shadowRoot.querySelector("#viewElement"); + if (!viewElement) return; // Ensure the element exists + + const previousScrollTop = viewElement.scrollTop; + const previousScrollHeight = viewElement.scrollHeight; + + // Using map to return a new array, rather than mutating the old one + const newMessagesToRender = this.messagesToRender.map(group => { + // For each message, return the updated message if it exists, otherwise return the original message + const updatedGroupMessages = group.messages.map(message => { + return updatedMessages[message.signature] ? {...message, ...updatedMessages[message.signature]} : message; + }); + + // Return a new group object with updated messages + return { + ...group, + messages: updatedGroupMessages + }; + }); + + this.messagesToRender = newMessagesToRender; + + await this.updateComplete; + + // Adjust scroll position based on the difference in scroll heights + const newScrollHeight = viewElement.scrollHeight; + viewElement.scrollTop = previousScrollTop + (newScrollHeight - previousScrollHeight); + + this.clearUpdateMessageHashmap(); + this.disableFetching = false; + } + async replaceMessagesWithUpdateByArray(updatedMessagesArray) { + let previousScrollTop; + let previousScrollHeight; + + const viewElement = this.shadowRoot.querySelector("#viewElement"); + previousScrollTop = viewElement.scrollTop; + previousScrollHeight = viewElement.scrollHeight; console.log({updatedMessagesArray}, this.messagesToRender) for (let group of this.messagesToRender) { for (let i = 0; i < group.messages.length; i++) { @@ -400,6 +502,10 @@ class ChatScroller extends LitElement { } } this.requestUpdate(); + const newScrollHeight = viewElement.scrollHeight; + viewElement.scrollTop = previousScrollTop + (newScrollHeight - previousScrollHeight); + this.clearUpdateMessageHashmap() + this.disableFetching = false } @@ -420,7 +526,7 @@ class ChatScroller extends LitElement { } - if (changedProperties && changedProperties.has('updateMessageHash')) { + if (changedProperties && changedProperties.has('updateMessageHash') && Object.keys(this.updateMessageHash).length > 0) { this.replaceMessagesWithUpdate(this.updateMessageHash) } @@ -499,7 +605,7 @@ class ChatScroller extends LitElement { .setOpenUserInfo=${(val) => this.setOpenUserInfo(val)} .setUserName=${(val) => this.setUserName(val)} id=${message.signature} - .goToRepliedMessage=${this.goToRepliedMessage} + .goToRepliedMessage=${(val, val2)=> this.goToRepliedMessageFunc(val, val2)} .addSeenMessage=${(val) => this.addSeenMessage(val)} .listSeenMessages=${this.listSeenMessages} chatId=${this.chatId} @@ -510,12 +616,17 @@ class ChatScroller extends LitElement {
- + ${this.isLoadingMessages ? html` +
+ +
+ ` : ''} ` } shouldUpdate(changedProperties) { + console.log({changedProperties}) if (changedProperties.has('isLoadingMessages')) { return true } @@ -534,6 +645,10 @@ class ChatScroller extends LitElement { if (changedProperties.has('updateMessageHash')) { return true } + if(changedProperties.has('messagesToRender')){ + console.log('true', this.messagesToRender) + return true + } // Only update element if prop1 changed. return changedProperties.has('messages') } @@ -617,7 +732,7 @@ class ChatScroller extends LitElement { _upObserverhandler(entries) { if (entries[0].isIntersecting) { - if (this.isLoadingMessages) { + if (this.isLoadingMessages || this.disableFetching) { return } this.setIsLoadingMessages(true) @@ -635,11 +750,12 @@ class ChatScroller extends LitElement { } __bottomObserverForFetchingMessagesHandler(entries) { - if (this.messagesToRender.length === 0) { + if (this.messagesToRender.length === 0 || this.disableFetching) { return } if (!entries[0].isIntersecting) { } else { + this.setIsLoadingMessages(true) let _scrollElement = entries[0].target.previousElementSibling this._getAfterMessages(_scrollElement) }