fix immutable issues

This commit is contained in:
PhilReact 2023-09-08 02:00:56 -05:00
parent 63d65c6773
commit 9f0e482183
2 changed files with 187 additions and 63 deletions

View File

@ -55,7 +55,7 @@ const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
export const queue = new RequestQueue(); export const queue = new RequestQueue();
export const chatLimit = 10 export const chatLimit = 40
class ChatPage extends LitElement { class ChatPage extends LitElement {
static get properties() { static get properties() {
return { return {
@ -1282,6 +1282,7 @@ class ChatPage extends LitElement {
constructor() { constructor() {
super() super()
this.getOldMessage = this.getOldMessage.bind(this) this.getOldMessage = this.getOldMessage.bind(this)
this.clearUpdateMessageHashmap = this.clearUpdateMessageHashmap.bind(this)
this._sendMessage = this._sendMessage.bind(this) this._sendMessage = this._sendMessage.bind(this)
this.insertFile = this.insertFile.bind(this) this.insertFile = this.insertFile.bind(this)
this.pasteImage = this.pasteImage.bind(this) this.pasteImage = this.pasteImage.bind(this)
@ -2138,6 +2139,7 @@ class ChatPage extends LitElement {
} }
async goToRepliedMessage(message, clickedOnMessage) { async goToRepliedMessage(message, clickedOnMessage) {
console.log({message})
const findMessage = this.shadowRoot.querySelector('chat-scroller').shadowRoot.getElementById(message.signature) const findMessage = this.shadowRoot.querySelector('chat-scroller').shadowRoot.getElementById(message.signature)
if (findMessage) { if (findMessage) {
@ -2165,24 +2167,21 @@ class ChatPage extends LitElement {
} }
await this.getOldMessageDynamic(0, clickedOnMessage.timestamp, message) await this.getOldMessageDynamic(0, clickedOnMessage.timestamp, message)
await new Promise((res)=> { await this.getUpdateComplete()
setTimeout(()=> {
res()
},1000)
})
await this.getUpdateCompleteMessages()
const marginElements = Array.from(this.shadowRoot.querySelector('chat-scroller').shadowRoot.querySelectorAll('message-template')) const marginElements = Array.from(this.shadowRoot.querySelector('chat-scroller').shadowRoot.querySelectorAll('message-template'))
const findMessage = marginElements.find((item) => item.messageObj.signature === message.signature) console.log({marginElements})
if (findMessage) { 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)
findMessage.scrollIntoView({ behavior: 'auto', block: 'center' }) console.log({findMessage2}, message.signature)
if (findMessage2) {
findMessage2.scrollIntoView({ block: 'center' })
} }
if (findMessage) { if (findMessage2) {
this.isLoadingGoToRepliedMessage = { this.isLoadingGoToRepliedMessage = {
...this.isLoadingGoToRepliedMessage, ...this.isLoadingGoToRepliedMessage,
loading: false loading: false
} }
const findElement = findMessage.shadowRoot.querySelector('.message-parent') const findElement = findMessage2.shadowRoot.querySelector('.message-parent')
if (findElement) { if (findElement) {
findElement.classList.add('blink-bg') findElement.classList.add('blink-bg')
setTimeout(() => { setTimeout(() => {
@ -2515,6 +2514,7 @@ class ChatPage extends LitElement {
} }
renderChatScroller() { renderChatScroller() {
console.log('clearUpdateMessageHashmap', Object.keys(this.updateMessageHash).length)
return html` return html`
<chat-scroller <chat-scroller
chatId=${this.chatId} chatId=${this.chatId}
@ -2541,6 +2541,7 @@ class ChatPage extends LitElement {
.selectedHead=${this.selectedHead} .selectedHead=${this.selectedHead}
.goToRepliedMessage=${(val, val2) => this.goToRepliedMessage(val, val2)} .goToRepliedMessage=${(val, val2) => this.goToRepliedMessage(val, val2)}
.updateMessageHash=${this.updateMessageHash} .updateMessageHash=${this.updateMessageHash}
.clearUpdateMessageHashmap=${this.clearUpdateMessageHashmap}
> >
</chat-scroller> </chat-scroller>
` `
@ -2585,7 +2586,7 @@ class ChatPage extends LitElement {
async getOldMessageDynamic(limit, timestampClickedOnMessage, messageToGoTo) { async getOldMessageDynamic(limit, timestampClickedOnMessage, messageToGoTo) {
const findMsg = await parentEpml.request("apiCall", { const findMsg = await parentEpml.request("apiCall", {
type: "api", type: "api",
url: `/chat/message/${messageToGoTo.signature}?encoding=BASE64`, url: `/chat/message/${messageToGoTo.originalSignature || messageToGoTo.signature}?encoding=BASE64`,
}) })
if(!findMsg) return null if(!findMsg) return null
if (this.isReceipient) { if (this.isReceipient) {
@ -2595,7 +2596,7 @@ class ChatPage extends LitElement {
}) })
const getInitialMessagesAfter = await parentEpml.request('apiCall', { const getInitialMessagesAfter = await parentEpml.request('apiCall', {
type: 'api', 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] const getInitialMessages = [...getInitialMessagesBefore, ...getInitialMessagesAfter]
let decodeMsgs = [] let decodeMsgs = []
@ -2624,7 +2625,8 @@ class ChatPage extends LitElement {
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
})); }));
console.log({decodeMsgs})
let list = [...decodeMsgs] let list = [...decodeMsgs]
await new Promise((res, rej) => { await new Promise((res, rej) => {
@ -2643,6 +2645,7 @@ class ChatPage extends LitElement {
this.messagesRendered = { this.messagesRendered = {
messages: list, messages: list,
type: 'inBetween', type: 'inBetween',
message: messageToGoTo
} }
this.isLoadingOldMessages = false this.isLoadingOldMessages = false
@ -2654,7 +2657,7 @@ class ChatPage extends LitElement {
}) })
const getInitialMessagesAfter = await parentEpml.request('apiCall', { const getInitialMessagesAfter = await parentEpml.request('apiCall', {
type: 'api', 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] const getInitialMessages = [...getInitialMessagesBefore, ...getInitialMessagesAfter]
@ -2683,7 +2686,7 @@ class ChatPage extends LitElement {
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
})); }));
console.log({decodeMsgs})
let list = [...decodeMsgs] let list = [...decodeMsgs]
@ -2842,7 +2845,7 @@ class ChatPage extends LitElement {
if (this.isReceipient) { if (this.isReceipient) {
const getInitialMessages = await parentEpml.request('apiCall', { const getInitialMessages = await parentEpml.request('apiCall', {
type: 'api', 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 = [] let decodeMsgs = []
@ -2904,7 +2907,7 @@ class ChatPage extends LitElement {
} else { } else {
const getInitialMessages = await parentEpml.request('apiCall', { const getInitialMessages = await parentEpml.request('apiCall', {
type: 'api', 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 = [] let decodeMsgs = []
await new Promise((res, rej) => { await new Promise((res, rej) => {
@ -2959,7 +2962,6 @@ class ChatPage extends LitElement {
await this.getUpdateComplete() await this.getUpdateComplete()
const marginElements = Array.from(this.shadowRoot.querySelector('chat-scroller').shadowRoot.querySelectorAll('message-template')) const marginElements = Array.from(this.shadowRoot.querySelector('chat-scroller').shadowRoot.querySelectorAll('message-template'))
const findElement = marginElements.find((item) => item.messageObj.signature === scrollElement.messageObj.signature) const findElement = marginElements.find((item) => item.messageObj.signature === scrollElement.messageObj.signature)
if (findElement) { if (findElement) {
findElement.scrollIntoView({ behavior: 'auto', block: 'center' }) findElement.scrollIntoView({ behavior: 'auto', block: 'center' })
} }
@ -2984,8 +2986,14 @@ const originalScrollHeight = viewElement.scrollHeight;
...newObj ...newObj
} }
await this.getUpdateComplete() await this.getUpdateComplete()
const heightDifference = viewElement.scrollHeight - originalScrollHeight; // const heightDifference = viewElement.scrollHeight - originalScrollHeight;
viewElement.scrollTop = originalScrollTop + heightDifference; // viewElement.scrollTop = originalScrollTop + heightDifference;
}
async clearUpdateMessageHashmap(){
console.log('hello clear')
this.updateMessageHash = {}
this.requestUpdate()
} }

View File

@ -237,7 +237,8 @@ class ChatScroller extends LitElement {
listSeenMessages: { type: Array }, listSeenMessages: { type: Array },
updateMessageHash: { type: Object }, updateMessageHash: { type: Object },
messagesToRender: { type: Array }, messagesToRender: { type: Array },
oldMessages: { type: Array } oldMessages: { type: Array },
clearUpdateMessageHashmap: { attribute: false}
} }
} }
@ -263,11 +264,16 @@ class ChatScroller extends LitElement {
this.listSeenMessages = [] this.listSeenMessages = []
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
this.messagesToRender = [] this.messagesToRender = []
this.disableFetching = false
} }
addSeenMessage(val) { addSeenMessage(val) {
this.listSeenMessages.push(val) this.listSeenMessages.push(val)
} }
goToRepliedMessageFunc(val, val2){
this.disableFetching = true
this.goToRepliedMessage(val, val2)
}
shouldGroupWithLastMessage(newMessage, lastGroupedMessage) { shouldGroupWithLastMessage(newMessage, lastGroupedMessage) {
if (!lastGroupedMessage) return false; if (!lastGroupedMessage) return false;
@ -289,12 +295,15 @@ class ChatScroller extends LitElement {
} }
this.requestUpdate(); this.requestUpdate();
this.disableFetching = false
} }
async newListMessages(newMessages, signature) { async newListMessages(newMessages, message) {
this.disableFetching = true
console.log('sup') console.log('sup')
let data = [] let data = []
newMessages.forEach(newMessage => { const copy = [...newMessages]
copy.forEach(newMessage => {
const lastGroupedMessage = data[data.length - 1]; const lastGroupedMessage = data[data.length - 1];
if (this.shouldGroupWithLastMessage(newMessage, lastGroupedMessage)) { if (this.shouldGroupWithLastMessage(newMessage, lastGroupedMessage)) {
@ -307,49 +316,95 @@ class ChatScroller extends LitElement {
} }
}); });
console.log({data})
this.messagesToRender = data this.messagesToRender = data
this.disableFetching = false
this.requestUpdate() 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)) { if (this.shouldGroupWithLastMessage(newMessage, lastGroupedMessage)) {
lastGroupedMessage.messages.push(newMessage); lastGroupedMessage.messages.push(newMessage);
} else { } else {
this.messagesToRender.push({ copy.push({
messages: [newMessage], messages: [newMessage],
...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) { async prependOldMessages(oldMessages) {
console.log('2', { oldMessages });
console.log('2', { oldMessages }) this.disableFetching = true
if (!this.messagesToRender) this.messagesToRender = []; // Ensure it's initialized if (!this.messagesToRender) this.messagesToRender = []; // Ensure it's initialized
let currentMessageGroup = null; let currentMessageGroup = null;
let previousMessage = null; let previousMessage = null;
for (const message of oldMessages) { for (const message of oldMessages) {
if (!previousMessage || !this.shouldGroupWithLastMessage(message, previousMessage)) { if (!previousMessage || !this.shouldGroupWithLastMessage(message, previousMessage)) {
// If no previous message, or if the current message shouldn't be grouped with the previous, // 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; previousMessage = message;
} }
// After processing all old messages, add the last group // After processing all old messages, add the last group
if (currentMessageGroup) { if (currentMessageGroup) {
this.messagesToRender.unshift(currentMessageGroup); this.messagesToRender.unshift(currentMessageGroup);
} }
this.requestUpdate(); // Ensure that the total number of individual messages doesn't exceed 80
this.setIsLoadingMessages(false) 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];
async replaceMessagesWithUpdate(updatedMessages) { if (lastGroup.messages.length <= (totalMessagesCount - 80)) {
for (let group of this.messagesToRender) { // If removing the whole last group achieves the goal, remove it
for (let i = 0; i < group.messages.length; i++) { totalMessagesCount -= lastGroup.messages.length;
if (updatedMessages[group.messages[i].signature]) { this.messagesToRender.pop();
Object.assign(group.messages[i], updatedMessages[group.messages[i].signature]); } else {
} // Otherwise, trim individual messages from the last group
const messagesToRemove = totalMessagesCount - 80;
lastGroup.messages.splice(-messagesToRemove, messagesToRemove);
totalMessagesCount = 80;
} }
} }
this.requestUpdate(); 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) { async replaceMessagesWithUpdateByArray(updatedMessagesArray) {
let previousScrollTop;
let previousScrollHeight;
const viewElement = this.shadowRoot.querySelector("#viewElement");
previousScrollTop = viewElement.scrollTop;
previousScrollHeight = viewElement.scrollHeight;
console.log({updatedMessagesArray}, this.messagesToRender) console.log({updatedMessagesArray}, this.messagesToRender)
for (let group of this.messagesToRender) { for (let group of this.messagesToRender) {
for (let i = 0; i < group.messages.length; i++) { for (let i = 0; i < group.messages.length; i++) {
@ -400,6 +502,10 @@ class ChatScroller extends LitElement {
} }
} }
this.requestUpdate(); 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) this.replaceMessagesWithUpdate(this.updateMessageHash)
} }
@ -499,7 +605,7 @@ class ChatScroller extends LitElement {
.setOpenUserInfo=${(val) => this.setOpenUserInfo(val)} .setOpenUserInfo=${(val) => this.setOpenUserInfo(val)}
.setUserName=${(val) => this.setUserName(val)} .setUserName=${(val) => this.setUserName(val)}
id=${message.signature} id=${message.signature}
.goToRepliedMessage=${this.goToRepliedMessage} .goToRepliedMessage=${(val, val2)=> this.goToRepliedMessageFunc(val, val2)}
.addSeenMessage=${(val) => this.addSeenMessage(val)} .addSeenMessage=${(val) => this.addSeenMessage(val)}
.listSeenMessages=${this.listSeenMessages} .listSeenMessages=${this.listSeenMessages}
chatId=${this.chatId} chatId=${this.chatId}
@ -510,12 +616,17 @@ class ChatScroller extends LitElement {
<div style=${"height: 1px; margin-top: -100px"} id='bottomObserverForFetchingMessages'></div> <div style=${"height: 1px; margin-top: -100px"} id='bottomObserverForFetchingMessages'></div>
<div style=${"height: 1px;"} id='downObserver'></div> <div style=${"height: 1px;"} id='downObserver'></div>
${this.isLoadingMessages ? html`
<div class="spinnerContainer">
<paper-spinner-lite active></paper-spinner-lite>
</div>
` : ''}
</ul> </ul>
` `
} }
shouldUpdate(changedProperties) { shouldUpdate(changedProperties) {
console.log({changedProperties})
if (changedProperties.has('isLoadingMessages')) { if (changedProperties.has('isLoadingMessages')) {
return true return true
} }
@ -534,6 +645,10 @@ class ChatScroller extends LitElement {
if (changedProperties.has('updateMessageHash')) { if (changedProperties.has('updateMessageHash')) {
return true return true
} }
if(changedProperties.has('messagesToRender')){
console.log('true', this.messagesToRender)
return true
}
// Only update element if prop1 changed. // Only update element if prop1 changed.
return changedProperties.has('messages') return changedProperties.has('messages')
} }
@ -617,7 +732,7 @@ class ChatScroller extends LitElement {
_upObserverhandler(entries) { _upObserverhandler(entries) {
if (entries[0].isIntersecting) { if (entries[0].isIntersecting) {
if (this.isLoadingMessages) { if (this.isLoadingMessages || this.disableFetching) {
return return
} }
this.setIsLoadingMessages(true) this.setIsLoadingMessages(true)
@ -635,11 +750,12 @@ class ChatScroller extends LitElement {
} }
__bottomObserverForFetchingMessagesHandler(entries) { __bottomObserverForFetchingMessagesHandler(entries) {
if (this.messagesToRender.length === 0) { if (this.messagesToRender.length === 0 || this.disableFetching) {
return return
} }
if (!entries[0].isIntersecting) { if (!entries[0].isIntersecting) {
} else { } else {
this.setIsLoadingMessages(true)
let _scrollElement = entries[0].target.previousElementSibling let _scrollElement = entries[0].target.previousElementSibling
this._getAfterMessages(_scrollElement) this._getAfterMessages(_scrollElement)
} }