4
1
mirror of https://github.com/Qortal/qortal-ui.git synced 2025-02-11 17:55:51 +00:00

fetch updates in bg

This commit is contained in:
PhilReact 2023-09-02 22:02:31 -07:00
parent 9705febe65
commit 950817b877
6 changed files with 330 additions and 73 deletions

View File

@ -43,6 +43,7 @@ import '@material/mwc-dialog'
import '@material/mwc-icon'
import '@polymer/paper-dialog/paper-dialog.js'
import '@polymer/paper-spinner/paper-spinner-lite.js'
import { RequestQueue } from '../../utils/queue.js'
const chatLastSeen = localForage.createInstance({
name: "chat-last-seen",
@ -50,6 +51,9 @@ const chatLastSeen = localForage.createInstance({
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
export const queue = new RequestQueue();
class ChatPage extends LitElement {
static get properties() {
return {
@ -113,7 +117,8 @@ class ChatPage extends LitElement {
openGifModal: { type: Boolean },
gifsLoading: { type: Boolean },
goToRepliedMessage: { attribute: false },
isLoadingGoToRepliedMessage: { type: Object }
isLoadingGoToRepliedMessage: { type: Object },
updateMessageHash: { type: Object}
}
}
@ -1348,6 +1353,8 @@ class ChatPage extends LitElement {
offsetHeight: 0
}
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
this.updateMessageHash = {}
this.addToUpdateMessageHashmap = this.addToUpdateMessageHashmap.bind(this)
}
setOpenGifModal(value) {
@ -2502,6 +2509,7 @@ class ChatPage extends LitElement {
.selectedHead=${this.selectedHead}
.goToRepliedMessage=${(val, val2) => this.goToRepliedMessage(val, val2)}
.getOldMessageAfter=${(val) => this.getOldMessageAfter(val)}
.updateMessageHash=${this.updateMessageHash}
>
</chat-scroller>
`
@ -2548,13 +2556,15 @@ class ChatPage extends LitElement {
return this.decodeMessage(eachMessage)
})
// const replacedMessages = await replaceMessagesEdited({
// decodedMessages: decodeMsgs,
// parentEpml,
// isReceipient: this.isReceipient,
// decodeMessageFunc: this.decodeMessage,
// _publicKey: this._publicKey
// })
queue.push(() => replaceMessagesEdited({
decodedMessages: decodeMsgs,
parentEpml,
isReceipient: this.isReceipient,
decodeMessageFunc: this.decodeMessage,
_publicKey: this._publicKey,
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
}));
this.messagesRendered = [...decodeMsgs, ...this.messagesRendered].sort(function (a, b) {
return a.timestamp
@ -2578,13 +2588,15 @@ class ChatPage extends LitElement {
return this.decodeMessage(eachMessage)
})
// const replacedMessages = await replaceMessagesEdited({
// decodedMessages: decodeMsgs,
// parentEpml,
// isReceipient: this.isReceipient,
// decodeMessageFunc: this.decodeMessage,
// _publicKey: this._publicKey
// })
queue.push(() => replaceMessagesEdited({
decodedMessages: decodeMsgs,
parentEpml,
isReceipient: this.isReceipient,
decodeMessageFunc: this.decodeMessage,
_publicKey: this._publicKey,
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
}));
this.messagesRendered = [...decodeMsgs, ...this.messagesRendered].sort(function (a, b) {
return a.timestamp
@ -2612,13 +2624,15 @@ class ChatPage extends LitElement {
return this.decodeMessage(eachMessage)
})
// const replacedMessages = await replaceMessagesEdited({
// decodedMessages: decodeMsgs,
// parentEpml,
// isReceipient: this.isReceipient,
// decodeMessageFunc: this.decodeMessage,
// _publicKey: this._publicKey
// })
queue.push(() => replaceMessagesEdited({
decodedMessages: decodeMsgs,
parentEpml,
isReceipient: this.isReceipient,
decodeMessageFunc: this.decodeMessage,
_publicKey: this._publicKey,
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
}));
this.messagesRendered = [...decodeMsgs, ...this.messagesRendered].sort(function (a, b) {
return a.timestamp
@ -2644,13 +2658,15 @@ class ChatPage extends LitElement {
return this.decodeMessage(eachMessage)
})
// const replacedMessages = await replaceMessagesEdited({
// decodedMessages: decodeMsgs,
// parentEpml,
// isReceipient: this.isReceipient,
// decodeMessageFunc: this.decodeMessage,
// _publicKey: this._publicKey
// })
queue.push(() => replaceMessagesEdited({
decodedMessages: decodeMsgs,
parentEpml,
isReceipient: this.isReceipient,
decodeMessageFunc: this.decodeMessage,
_publicKey: this._publicKey,
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
}));
this.messagesRendered = [...decodeMsgs, ...this.messagesRendered].sort(function (a, b) {
return a.timestamp
@ -2668,6 +2684,27 @@ class ChatPage extends LitElement {
}
}
async addToUpdateMessageHashmap(array){
console.log({array})
const viewElement = this.shadowRoot.querySelector('chat-scroller').shadowRoot.getElementById('viewElement')
const originalScrollTop = viewElement.scrollTop;
const originalScrollHeight = viewElement.scrollHeight;
const newObj = {}
array.forEach((item)=> {
const signature = item.originalSignature || item.signature
newObj[signature] = item
})
this.updateMessageHash = {
...this.updateMessageHash,
...newObj
}
await this.getUpdateComplete()
const heightDifference = viewElement.scrollHeight - originalScrollHeight;
viewElement.scrollTop = originalScrollTop + heightDifference;
}
async getOldMessageAfter(scrollElement) {
if (this.isReceipient) {
const getInitialMessages = await parentEpml.request('apiCall', {
@ -2679,13 +2716,15 @@ class ChatPage extends LitElement {
return this.decodeMessage(eachMessage)
})
// const replacedMessages = await replaceMessagesEdited({
// decodedMessages: decodeMsgs,
// parentEpml,
// isReceipient: this.isReceipient,
// decodeMessageFunc: this.decodeMessage,
// _publicKey: this._publicKey
// })
queue.push(() => replaceMessagesEdited({
decodedMessages: decodeMsgs,
parentEpml,
isReceipient: this.isReceipient,
decodeMessageFunc: this.decodeMessage,
_publicKey: this._publicKey,
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
}));
this.messagesRendered = [...this.messagesRendered, ...decodeMsgs].sort(function (a, b) {
return a.timestamp
@ -2711,13 +2750,15 @@ class ChatPage extends LitElement {
return this.decodeMessage(eachMessage)
})
// const replacedMessages = await replaceMessagesEdited({
// decodedMessages: decodeMsgs,
// parentEpml,
// isReceipient: this.isReceipient,
// decodeMessageFunc: this.decodeMessage,
// _publicKey: this._publicKey
// })
queue.push(() => replaceMessagesEdited({
decodedMessages: decodeMsgs,
parentEpml,
isReceipient: this.isReceipient,
decodeMessageFunc: this.decodeMessage,
_publicKey: this._publicKey,
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
}));
this.messagesRendered = [...this.messagesRendered, ...decodeMsgs].sort(function (a, b) {
return a.timestamp
@ -2751,13 +2792,21 @@ class ChatPage extends LitElement {
})
if (isInitial) {
this.chatEditorPlaceholder = await this.renderPlaceholder()
// const replacedMessages = await replaceMessagesEdited({
// decodedMessages: decodedMessages,
// parentEpml,
// isReceipient: isReceipient,
// decodeMessageFunc: this.decodeMessage,
// _publicKey: this._publicKey
// })
try {
queue.push(() => replaceMessagesEdited({
decodedMessages: decodedMessages,
parentEpml,
isReceipient: isReceipient,
decodeMessageFunc: this.decodeMessage,
_publicKey: this._publicKey,
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
}));
} catch (error) {
console.log({error})
}
this._messages = decodedMessages.sort(function (a, b) {
return a.timestamp
@ -2771,14 +2820,17 @@ class ChatPage extends LitElement {
setTimeout(() => this.downElementObserver(), 500)
} else {
// const replacedMessages = await replaceMessagesEdited({
// decodedMessages: decodedMessages,
// parentEpml,
// isReceipient: isReceipient,
// decodeMessageFunc: this.decodeMessage,
// _publicKey: this._publicKey,
// isNotInitial: true
// })
queue.push(() => replaceMessagesEdited({
decodedMessages: decodedMessages,
parentEpml,
isReceipient: isReceipient,
decodeMessageFunc: this.decodeMessage,
_publicKey: this._publicKey,
isNotInitial: true,
addToUpdateMessageHashmap: this.addToUpdateMessageHashmap
}));
const renderEachMessage = decodedMessages.map(async (msg) => {
await this.renderNewMessage(msg)

View File

@ -196,7 +196,8 @@ class ChatScroller extends LitElement {
selectedHead: { type: Object },
goToRepliedMessage: { attribute: false },
getOldMessageAfter: { attribute: false },
listSeenMessages: { type: Array }
listSeenMessages: { type: Array },
updateMessageHash: {type: Object}
}
}
@ -223,6 +224,10 @@ class ChatScroller extends LitElement {
render() {
let formattedMessages = this.messages.reduce((messageArray, message, index) => {
if(this.updateMessageHash[message.signature]){
message = this.updateMessageHash[message.signature]
}
const lastGroupedMessage = messageArray[messageArray.length - 1]
let timestamp
let sender
@ -319,6 +324,9 @@ class ChatScroller extends LitElement {
if (changedProperties.has('userName')) {
return true
}
if (changedProperties.has('updateMessageHash')) {
return true
}
// Only update element if prop1 changed.
return changedProperties.has('messages')
}

View File

@ -101,7 +101,6 @@ class LevelFounder extends LitElement {
}
firstUpdated() {
console.log('levelFounder')
parentEpml.ready().then(() => {
parentEpml.subscribe('selected_address', async selectedAddress => {

View File

@ -465,6 +465,7 @@ class Chat extends LitElement {
url: `/addresses/balance/${window.parent.reduxStore.getState().app.selectedAddress.address}`
}).then(res => {
this.balance = res
this.requestUpdate()
})
})
parentEpml.imReady()
@ -834,6 +835,7 @@ class Chat extends LitElement {
chatId=${this.activeChatHeadUrl}
.setOpenPrivateMessage=${(val) => this.setOpenPrivateMessage(val)}
.setActiveChatHeadUrl=${(val)=> this.setActiveChatHeadUrl(val)}
balance=${this.balance}
>
</chat-page>
`

View File

@ -0,0 +1,34 @@
export class RequestQueue {
constructor(maxConcurrent = 5) {
this.queue = [];
this.maxConcurrent = maxConcurrent;
this.currentConcurrent = 0;
}
push(request) {
return new Promise((resolve, reject) => {
this.queue.push({
request,
resolve,
reject,
});
this.checkQueue();
});
}
checkQueue() {
if (this.queue.length === 0 || this.currentConcurrent >= this.maxConcurrent) return;
const { request, resolve, reject } = this.queue.shift();
this.currentConcurrent++;
request()
.then(resolve)
.catch(reject)
.finally(() => {
this.currentConcurrent--;
this.checkQueue();
});
}
}

View File

@ -1,11 +1,161 @@
// export const replaceMessagesEdited = async ({
// decodedMessages,
// parentEpml,
// isReceipient,
// decodeMessageFunc,
// _publicKey,
// addToUpdateMessageHashmap
// }) => {
// const findNewMessages = decodedMessages.map(async (msg) => {
// let msgItem = null
// try {
// let msgQuery = `&involving=${msg.recipient}&involving=${msg.sender}`
// if (!isReceipient) {
// msgQuery = `&txGroupId=${msg.txGroupId}`
// }
// const response = await parentEpml.request("apiCall", {
// type: "api",
// url: `/chat/messages?chatreference=${msg.signature}&reverse=true${msgQuery}&limit=1&sender=${msg.sender}&encoding=BASE64`,
// })
// if (response && Array.isArray(response) && response.length !== 0) {
// let responseItem = { ...response[0] }
// const decodeResponseItem = decodeMessageFunc(responseItem, isReceipient, _publicKey)
// delete decodeResponseItem.timestamp
// msgItem = {
// ...msg,
// ...decodeResponseItem,
// senderName: msg.senderName,
// sender: msg.sender,
// editedTimestamp: response[0].timestamp,
// originalSignature: msg.signature
// }
// }
// } catch (error) {
// }
// return msgItem
// })
// const updateMessages = await Promise.all(findNewMessages)
// const filterOutNull = updateMessages.filter((item)=> item !== 'null' && item !== null)
// const findNewMessages2 = filterOutNull.map(async (msg) => {
// let parsedMessageObj = msg
// try {
// parsedMessageObj = JSON.parse(msg.decodedMessage)
// } catch (error) {
// return msg
// }
// let msgItem = msg
// try {
// let msgQuery = `&involving=${msg.recipient}&involving=${msg.sender}`
// if (!isReceipient) {
// msgQuery = `&txGroupId=${msg.txGroupId}`
// }
// if (parsedMessageObj.repliedTo) {
// let originalReply
// if(+parsedMessageObj.version > 2){
// originalReply = await parentEpml.request("apiCall", {
// type: "api",
// url: `/chat/message/${parsedMessageObj.repliedTo}?encoding=BASE64`,
// })
// }
// if(+parsedMessageObj.version < 3){
// originalReply = await parentEpml.request("apiCall", {
// type: "api",
// url: `/chat/messages?reference=${parsedMessageObj.repliedTo}&reverse=true${msgQuery}&encoding=BASE64`,
// })
// }
// const originalReplyMessage = originalReply.timestamp ? originalReply : originalReply.length !== 0 ? originalReply[0] : null
// const response = await parentEpml.request("apiCall", {
// type: "api",
// url: `/chat/messages?chatreference=${parsedMessageObj.repliedTo}&reverse=true${msgQuery}&limit=1&sender=${originalReplyMessage.sender}&encoding=BASE64`,
// })
// if (
// originalReplyMessage &&
// response &&
// Array.isArray(response) &&
// response.length !== 0
// ) {
// const decodeOriginalReply = decodeMessageFunc(originalReplyMessage, isReceipient, _publicKey)
// const decodeUpdatedReply = decodeMessageFunc(response[0], isReceipient, _publicKey)
// const formattedRepliedToData = {
// ...decodeUpdatedReply,
// senderName: decodeOriginalReply.senderName,
// sender: decodeOriginalReply.sender,
// }
// msgItem = {
// ...msg,
// repliedToData: formattedRepliedToData,
// }
// } else {
// if (
// originalReplyMessage
// ) {
// msgItem = {
// ...msg,
// repliedToData: decodeMessageFunc(originalReplyMessage, isReceipient, _publicKey),
// }
// }
// }
// }
// } catch (error) {
// }
// return msgItem
// })
// const updateMessages2 = await Promise.all(findNewMessages2)
// console.log({updateMessages2})
// updateMessages2.forEach((item)=> {
// addToUpdateMessageHashmap(item.originalSignature, item)
// })
// return updateMessages2
// }
export const replaceMessagesEdited = async ({
decodedMessages,
parentEpml,
decodedMessages,
parentEpml,
isReceipient,
decodeMessageFunc,
_publicKey
_publicKey,
addToUpdateMessageHashmap
}) => {
const findNewMessages = decodedMessages.map(async (msg) => {
const MAX_CONCURRENT_REQUESTS = 5; // Maximum number of concurrent requests
const executeWithConcurrencyLimit = async (array, asyncFn) => {
const results = [];
const concurrencyPool = [];
for (const item of array) {
const promise = asyncFn(item);
concurrencyPool.push(promise);
if (concurrencyPool.length >= MAX_CONCURRENT_REQUESTS) {
results.push(...await Promise.all(concurrencyPool));
concurrencyPool.length = 0; // Clear the concurrency pool
}
}
if (concurrencyPool.length > 0) {
results.push(...await Promise.all(concurrencyPool));
}
return results;
};
const findNewMessages = async (msg) => {
let msgItem = msg
try {
let msgQuery = `&involving=${msg.recipient}&involving=${msg.sender}`
@ -28,15 +178,16 @@ export const replaceMessagesEdited = async ({
senderName: msg.senderName,
sender: msg.sender,
editedTimestamp: response[0].timestamp,
originalSignature: msg.signature
}
}
} catch (error) {
}
return msgItem
})
const updateMessages = await Promise.all(findNewMessages)
const findNewMessages2 = updateMessages.map(async (msg) => {
};
const findNewMessages2 = async (msg) => {
let parsedMessageObj = msg
try {
parsedMessageObj = JSON.parse(msg.decodedMessage)
@ -74,6 +225,7 @@ export const replaceMessagesEdited = async ({
url: `/chat/messages?chatreference=${parsedMessageObj.repliedTo}&reverse=true${msgQuery}&limit=1&sender=${originalReplyMessage.sender}&encoding=BASE64`,
})
if (
originalReplyMessage &&
response &&
@ -98,7 +250,6 @@ export const replaceMessagesEdited = async ({
if (
originalReplyMessage
) {
msgItem = {
...msg,
repliedToData: decodeMessageFunc(originalReplyMessage, isReceipient, _publicKey),
@ -109,9 +260,20 @@ export const replaceMessagesEdited = async ({
} catch (error) {
}
return msgItem
})
const updateMessages2 = await Promise.all(findNewMessages2)
return updateMessages2
}
return msgItem
};
const sortedMessages = decodedMessages.sort((a, b) => b.timestamp - a.timestamp);
// Execute the functions with concurrency limit
const updateMessages = await executeWithConcurrencyLimit(sortedMessages, findNewMessages);
const updateMessages2 = await executeWithConcurrencyLimit(updateMessages.filter(item => item !== 'null' && item !== null), findNewMessages2);
addToUpdateMessageHashmap(updateMessages2)
return updateMessages2;
};