From 79fa08a099074fa1c375bec5d72daa7d3f978f5b Mon Sep 17 00:00:00 2001 From: PhilReact Date: Tue, 12 Sep 2023 21:49:01 -0500 Subject: [PATCH] added pending messages --- plugins/plugins/core/components/ChatPage.js | 174 ++++++++++++++---- .../core/components/ChatScroller-css.js | 4 + .../plugins/core/components/ChatScroller.js | 88 +++++++-- .../core/components/ChatTextEditor copy.js | 1 + .../plugins/core/components/ChatTextEditor.js | 16 +- 5 files changed, 235 insertions(+), 48 deletions(-) diff --git a/plugins/plugins/core/components/ChatPage.js b/plugins/plugins/core/components/ChatPage.js index 85948ccd..66f1ada6 100644 --- a/plugins/plugins/core/components/ChatPage.js +++ b/plugins/plugins/core/components/ChatPage.js @@ -124,7 +124,9 @@ class ChatPage extends LitElement { goToRepliedMessage: { attribute: false }, isLoadingGoToRepliedMessage: { type: Object }, updateMessageHash: { type: Object}, - oldMessages: {type: Array} + oldMessages: {type: Array}, + messageQueue: {type: Array}, + isInProcessQueue: {type: Boolean} } } @@ -1371,6 +1373,10 @@ class ChatPage extends LitElement { this.oldMessages = [] this.lastReadMessageTimestamp = 0 this.initUpdate = this.initUpdate.bind(this) + this.messageQueue = [] + this.addToQueue = this.addToQueue.bind(this) + this.processQueue = this.processQueue.bind(this) + this.isInProcessQueue = false } setOpenGifModal(value) { @@ -1416,7 +1422,84 @@ class ChatPage extends LitElement { this.gifsLoading = props } + addToQueue(outSideMsg, messageQueue) { + console.log('added to queue', messageQueue, this.messageQueue) + // Push the new message object to the queue + + this.messageQueue = [...messageQueue, { ...outSideMsg, timestamp: Date.now()}]; + console.log('Current Queue after adding:', [...this.messageQueue]); + + // Start processing the queue only if the message we just added is the only one in the queue + // This ensures that the queue processing starts only once, even if this method is called multiple times + if (this.messageQueue.length === 1) { + this.processQueue(); + } + + // Notify Lit to update/render due to the property change + this.requestUpdate(); + } + + async processQueue() { + if (this.messageQueue.length === 0) return; + const currentMessage = this.messageQueue[0]; + console.log({currentMessage}) + try { + const res = await this.sendMessage(currentMessage); + console.log({res}) + if(res === true) { + this.messageQueue = this.messageQueue.slice(1); + } else { + throw new Error('failed') + } + + if (this.messageQueue.length > 0) { + setTimeout(() => this.processQueue(), 2000); // Wait for 10 seconds before retrying + // setTimeout(() => this.processQueue(), 0); // Process the next message immediately + } + } catch (error) { + console.error("Failed to send message:", error); + setTimeout(() => this.processQueue(), 10000); // Wait for 10 seconds before retrying + } + } + // async processQueue() { + // let inProcess = false; // to indicate if we're currently sending a message + + // while (true) { // Infinite loop + // const currentMessage = this.messageQueue[0]; + + // // If there's no current message, you could wait a while (e.g., a second) before the next iteration. + // // This prevents the loop from consuming resources unnecessarily when the queue is empty. + // if (!currentMessage) { + // await new Promise(res => setTimeout(res, 1000)); // Wait for 1 second + // continue; // go to the next iteration of the loop + // } + + // // If not currently processing another message, attempt to send the current one + // if (!inProcess) { + // inProcess = true; // indicate that we're starting to process a message + + // try { + // await this._sendMessage(currentMessage.outSideMsg, currentMessage.msg, true, currentMessage.chatId, currentMessage.isReceipient, currentMessage._publicKey, currentMessage.attachment); + + // // If successful, remove the processed message from the queue + // this.messageQueue = this.messageQueue.slice(1); + // inProcess = false; // set inProcess back to false since we're done with this message + // } catch (error) { + // console.error("Failed to send message:", error); + // inProcess = false; // set inProcess back to false since an error occurred + // await new Promise(res => setTimeout(res, 10000)); // Wait for 10 seconds before retrying + // } + // } else { + // await new Promise(res => setTimeout(res, 1000)); // Wait for 1 second before checking again if inProcess is false + // } + // } + // } + + + render() { + console.log('this.messageQueue', this.messageQueue.length) + return html`
this.setOpenGifModal(val)} chatId=${this.chatId} + .messageQueue=${this.messageQueue} >
@@ -2394,7 +2478,9 @@ class ChatPage extends LitElement { async firstUpdated() { this.changeTheme() - + + // this.processQueue(); + window.addEventListener('storage', () => { const checkLanguage = localStorage.getItem('qortalLanguage') const checkTheme = localStorage.getItem('qortalTheme') @@ -2453,6 +2539,7 @@ class ChatPage extends LitElement { shouldUpdate(changedProperties) { + console.log({changedProperties}) if (changedProperties.has('setActiveChatHeadUrl')) { return false } @@ -2537,6 +2624,7 @@ class ChatPage extends LitElement { .goToRepliedMessage=${(val, val2) => this.goToRepliedMessage(val, val2)} .updateMessageHash=${this.updateMessageHash} .clearUpdateMessageHashmap=${this.clearUpdateMessageHashmap} + .messageQueue=${this.messageQueue} > ` @@ -3484,11 +3572,25 @@ class ChatPage extends LitElement { } } - async _sendMessage(outSideMsg, msg) { + async _sendMessage(outSideMsg, msg, messageQueue) { + const _chatId= this._chatId + const isReceipient= this.isReceipient + const _publicKey= this._publicKey + const attachment= this.attachment + console.log({ + _chatId, isReceipient, _publicKey, attachment + }) + // if(messageQueue){ + // console.log('is queueCurrent Queue after before:', [...this.messageQueue]); + // this.addToQueue(outSideMsg, msg, messageQueue); + + // return + // } + try { if (this.isReceipient) { let hasPublicKey = true - if (!this._publicKey.hasPubKey) { + if (!publicKey.hasPubKey) { hasPublicKey = false try { const res = await parentEpml.request('apiCall', { @@ -3496,20 +3598,20 @@ class ChatPage extends LitElement { url: `/addresses/publickey/${this.selectedAddress.address}` }) if (res.error === 102) { - this._publicKey.key = '' - this._publicKey.hasPubKey = false + publicKey.key = '' + publicKey.hasPubKey = false } else if (res !== false) { - this._publicKey.key = res - this._publicKey.hasPubKey = true + publicKey.key = res + publicKey.hasPubKey = true hasPublicKey = true } else { - this._publicKey.key = '' - this._publicKey.hasPubKey = false + publicKey.key = '' + publicKey.hasPubKey = false } } catch (error) { } - if (!hasPublicKey || !this._publicKey.hasPubKey) { + if (!hasPublicKey || !publicKey.hasPubKey) { let err4string = get("chatpage.cchange39") parentEpml.request('showSnackBar', `${err4string}`) return @@ -3524,7 +3626,7 @@ class ChatPage extends LitElement { // create new var called repliedToData and use that to modify the UI // find specific object property in local let typeMessage = 'regular' - this.isLoading = true + // this.isLoading = true const trimmedMessage = msg const getName = async (recipient) => { @@ -3640,7 +3742,7 @@ class ChatPage extends LitElement { isImageDeleted: true } const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage, chatReference) + return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}) } else if (outSideMsg && outSideMsg.type === 'deleteAttachment') { this.isDeletingAttachment = true let compressedFile = '' @@ -3738,7 +3840,7 @@ class ChatPage extends LitElement { isAttachmentDeleted: true } const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage, chatReference) + return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}) } else if (outSideMsg && outSideMsg.type === 'image') { this.isUploadingImage = true const userName = await getName(this.selectedAddress.address) @@ -3826,7 +3928,7 @@ class ChatPage extends LitElement { version: 3 } const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage) + return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference: undefined, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}) } else if (outSideMsg && outSideMsg.type === 'gif') { const userName = await getName(this.selectedAddress.address) if (!userName) { @@ -3847,7 +3949,7 @@ class ChatPage extends LitElement { version: 3 } const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage) + return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference: undefined, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}) } else if (outSideMsg && outSideMsg.type === 'attachment') { this.isUploadingAttachment = true const userName = await getName(this.selectedAddress.address) @@ -3864,7 +3966,7 @@ class ChatPage extends LitElement { this.webWorkerFile = new WebWorkerFile() - const attachment = this.attachment + // const attachment = attachment const id = this.uid() const identifier = `qchat_${id}` const fileSize = attachment.size @@ -3916,7 +4018,7 @@ class ChatPage extends LitElement { version: 3 } const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage) + return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference: undefined, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}) } else if (outSideMsg && outSideMsg.type === 'reaction') { const userName = await getName(this.selectedAddress.address) typeMessage = 'edit' @@ -3971,7 +4073,7 @@ class ChatPage extends LitElement { reactions } const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage, chatReference) + return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}) } else if (/^\s*$/.test(trimmedMessage)) { this.isLoading = false } else if (this.repliedToMessageObj) { @@ -3987,7 +4089,7 @@ class ChatPage extends LitElement { version: 3 } const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage) + return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference: undefined, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}) } else if (this.editedMessageObj) { typeMessage = 'edit' let chatReference = this.editedMessageObj.signature @@ -4010,7 +4112,7 @@ class ChatPage extends LitElement { isEdited: true } const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage, chatReference) + return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}) } else { const messageObject = { messageText: trimmedMessage, @@ -4025,7 +4127,7 @@ class ChatPage extends LitElement { this.myTrimmedMeassage = stringifyMessageObject this.shadowRoot.getElementById('confirmDialog').open() } else { - this.sendMessage(stringifyMessageObject, typeMessage) + return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference: undefined, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}) } } } catch (error) { @@ -4036,20 +4138,27 @@ class ChatPage extends LitElement { } - async sendMessage(messageText, typeMessage, chatReference, isForward) { - this.isLoading = true + async sendMessage({messageText, typeMessage, chatReference, isForward,isReceipient, _chatId, _publicKey, messageQueue}) { + console.log('2', {messageText, typeMessage, chatReference, isForward,isReceipient, _chatId, _publicKey}) + if(messageQueue){ + console.log('is queueCurrent Queue after before:', [...this.messageQueue]); + this.addToQueue({messageText, typeMessage, chatReference, isForward, isReceipient, _chatId, _publicKey}, messageQueue); + this.resetChatEditor() + return + } + // this.isLoading = true let _reference = new Uint8Array(64) window.crypto.getRandomValues(_reference) let reference = window.parent.Base58.encode(_reference) const sendMessageRequest = async () => { - if (this.isReceipient === true) { + if (isReceipient === true) { let chatResponse = await parentEpml.request('chat', { type: 18, nonce: this.selectedAddress.nonce, params: { timestamp: Date.now(), - recipient: this._chatId, - recipientPublicKey: this._publicKey.key, + recipient: _chatId, + recipientPublicKey: _publicKey.key, hasChatReference: typeMessage === 'edit' ? 1 : 0, chatReference: chatReference, message: messageText, @@ -4059,14 +4168,14 @@ class ChatPage extends LitElement { isText: 1 } }) - _computePow(chatResponse) + return _computePow(chatResponse) } else { let groupResponse = await parentEpml.request('chat', { type: 181, nonce: this.selectedAddress.nonce, params: { timestamp: Date.now(), - groupID: Number(this._chatId), + groupID: Number(_chatId), hasReceipient: 0, hasChatReference: typeMessage === 'edit' ? 1 : 0, chatReference: chatReference, @@ -4077,7 +4186,7 @@ class ChatPage extends LitElement { isText: 1 } }) - _computePow(groupResponse) + return _computePow(groupResponse) } } @@ -4266,11 +4375,12 @@ class ChatPage extends LitElement { }) getSendChatResponse(_response, isForward) + return _response } const getSendChatResponse = (response, isForward, customErrorMessage) => { if (response === true) { - this.resetChatEditor() + // this.resetChatEditor() if (isForward) { let successString = get("blockpage.bcchange15") parentEpml.request('showSnackBar', `${successString}`) @@ -4302,7 +4412,7 @@ class ChatPage extends LitElement { sendForwardRequest() return } - sendMessageRequest() + return sendMessageRequest() } /** diff --git a/plugins/plugins/core/components/ChatScroller-css.js b/plugins/plugins/core/components/ChatScroller-css.js index d2ac074a..378ccac8 100644 --- a/plugins/plugins/core/components/ChatScroller-css.js +++ b/plugins/plugins/core/components/ChatScroller-css.js @@ -43,6 +43,10 @@ export const chatStyles = css` margin: 0; padding: 20px 17px; } + .message-sending { + opacity: 0.5; + cursor: progress; +} .chat-list { overflow-y: auto; diff --git a/plugins/plugins/core/components/ChatScroller.js b/plugins/plugins/core/components/ChatScroller.js index d5a78398..a206d633 100644 --- a/plugins/plugins/core/components/ChatScroller.js +++ b/plugins/plugins/core/components/ChatScroller.js @@ -245,7 +245,8 @@ class ChatScroller extends LitElement { clearUpdateMessageHashmap: { attribute: false}, disableFetching: {type: Boolean}, isLoadingBefore: {type: Boolean}, - isLoadingAfter: {type: Boolean} + isLoadingAfter: {type: Boolean}, + messageQueue: {type: Array} } } @@ -279,6 +280,7 @@ class ChatScroller extends LitElement { this.isLoadingAfter = false this.disableAddingNewMessages = false this.lastReadMessageTimestamp = null + this.messageQueue = [] } addSeenMessage(val) { @@ -614,6 +616,7 @@ class ChatScroller extends LitElement { render() { + console.log('this.chatId', this.chatId) // let formattedMessages = this.messages.reduce((messageArray, message) => { // const currentMessage = this.updateMessageHash[message.signature] || message; // const lastGroupedMessage = messageArray[messageArray.length - 1]; @@ -698,17 +701,67 @@ class ChatScroller extends LitElement { ` )} + ` )} + + ${this.messageQueue.filter((item )=> this.chatId.includes(item._chatId)).length > 0 ? html` +
+ ` : html`
+ `} +
+ ${this.isLoadingAfter ? html`
` : ''} + ${repeat( + this.messageQueue.filter((item )=> this.chatId.includes(item._chatId)), + (message) => message.messageText, + (message, indexMessage) => html` + + this.setOpenPrivateMessage(val)} + .setOpenTipUser=${(val) => this.setOpenTipUser(val)} + .setOpenUserInfo=${(val) => this.setOpenUserInfo(val)} + .setUserName=${(val) => this.setUserName(val)} + id=${message.signature} + .goToRepliedMessage=${(val, val2)=> this.goToRepliedMessageFunc(val, val2)} + .addSeenMessage=${(val) => this.addSeenMessage(val)} + .listSeenMessages=${this.listSeenMessages} + chatId=${this.chatId} + ?isInProgress=${true} + > + + ` + + )} ` } @@ -741,6 +794,9 @@ class ChatScroller extends LitElement { if(changedProperties.has('isLoadingAfter')){ return true } + if(changedProperties.has('messageQueue')){ + return true + } // Only update element if prop1 changed. return changedProperties.has('messages') } @@ -820,7 +876,7 @@ class ChatScroller extends LitElement { _upObserverhandler(entries) { - + if(!entries[0].target || !entries[0].target.nextElementSibling) return if (entries[0].isIntersecting) { if (this.disableFetching) { return @@ -844,7 +900,7 @@ class ChatScroller extends LitElement { if (this.messagesToRender.length === 0 || this.disableFetching) { return } - if (!entries[0].isIntersecting) { + if (!entries[0].isIntersecting || !entries[0].target || !entries[0].target.previousElementSibling) { } else { this.disableFetching = true this.isLoadingAfter = true @@ -926,7 +982,8 @@ class MessageTemplate extends LitElement { goToRepliedMessage: { attribute: false }, listSeenMessages: { type: Array }, addSeenMessage: { attribute: false }, - chatId: { type: String } + chatId: { type: String }, + isInProgress: {type: Boolean} } } @@ -947,6 +1004,7 @@ class MessageTemplate extends LitElement { this.isSingleMessageInGroup = false this.isLastMessageInGroup = false this.viewImage = false + this.isInProgress = false } static get styles() { @@ -1059,6 +1117,7 @@ class MessageTemplate extends LitElement { let isEdited = false let attachment = null try { + console.log('this.messageOb', this.messageObj ) const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage) if (+parsedMessageObj.version > 1 && parsedMessageObj.messageText) { messageVersion2 = generateHTML(parsedMessageObj.messageText, [ @@ -1250,7 +1309,7 @@ class MessageTemplate extends LitElement {
-
+
${(this.isSingleMessageInGroup === false || (this.isSingleMessageInGroup === true && this.isLastMessageInGroup === true)) ? ( @@ -1476,7 +1535,12 @@ class MessageTemplate extends LitElement { ` : '' } + ${this.isInProgress ? html` +

Sending...

+ ` : html` + `} +
@@ -1518,7 +1582,7 @@ class MessageTemplate extends LitElement { editedMessageObj: this.messageObj, reaction: reaction.type, })} - id=${`reactions-${index}`} + id=${`reactions-${indexMessageTemplate}`} class="reactions-bg"> ${reaction.type} ${reaction.qty} @@ -1530,7 +1594,7 @@ class MessageTemplate extends LitElement { text=${reaction.users.length > 3 ? ( `${reaction.users[0].name - ? reaction.users[0].name + ? reaction.users[0].nameMessageTemplate : cropAddress(reaction.users[0].address)}, ${reaction.users[1].name ? reaction.users[1].name @@ -1558,7 +1622,7 @@ class MessageTemplate extends LitElement { : cropAddress(reaction.users[0].address)} ${get("chatpage.cchange71")} ${reaction.users[1].name - ? reaction.users[1].name + ? reaction.users[1].namMessageTemplatee : cropAddress(reaction.users[1].address)} ${get("chatpage.cchange74")} ${reaction.type}` ) : reaction.users.length === 1 ? ( @@ -1585,7 +1649,7 @@ class MessageTemplate extends LitElement { toblockaddress=${this.messageObj.sender} > - { @@ -1600,7 +1664,7 @@ class MessageTemplate extends LitElement { dialogAction="cancel" class="red" @click=${() => { - +MessageTemplate this.openDialogImage = false }} > @@ -1612,7 +1676,7 @@ class MessageTemplate extends LitElement { ?open=${this.openDialogGif} @closed=${() => { this.openDialogGif = false - }}> + }}>MessageTemplate
${gifHTMLDialog} @@ -1627,7 +1691,7 @@ class MessageTemplate extends LitElement { }} > ${translate("general.close")} - + MessageTemplate 60 && this.shadowRoot.querySelector(".chat-editor").contentDocument.body.querySelector("#chatbarId").innerHTML.trim() !== "") { diff --git a/plugins/plugins/core/components/ChatTextEditor.js b/plugins/plugins/core/components/ChatTextEditor.js index b13dc72f..ba2b4c67 100644 --- a/plugins/plugins/core/components/ChatTextEditor.js +++ b/plugins/plugins/core/components/ChatTextEditor.js @@ -36,7 +36,8 @@ class ChatTextEditor extends LitElement { isEnabledChatEnter: {type: Boolean}, openGifModal: { type: Boolean }, setOpenGifModal: { attribute: false }, - chatId: {type: String} + chatId: {type: String}, + messageQueue: {type: Array} } } @@ -376,9 +377,12 @@ mwc-checkbox::shadow .mdc-checkbox::after, mwc-checkbox::shadow .mdc-checkbox::b this.userName = window.parent.reduxStore.getState().app.accountInfo.names[0] this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' this.editor = null + this.messageQueue = [] + } render() { + console.log('at render', this.messageQueue) return html`
{ - this.sendMessageFunc(); + console.log('onclick', this.messageQueue) + this.sendMessageFunc(this.messageQueue); }} > @@ -538,7 +543,8 @@ mwc-checkbox::shadow .mdc-checkbox::after, mwc-checkbox::shadow .mdc-checkbox::b alt="send-icon" class="send-icon" @click=${() => { - this.sendMessageFunc(); + console.log('onclick', this.messageQueue) + this.sendMessageFunc(this.messageQueue); }} /> ` : @@ -641,6 +647,7 @@ mwc-checkbox::shadow .mdc-checkbox::after, mwc-checkbox::shadow .mdc-checkbox::b } sendMessageFunc(props) { + console.log({props}) if(this.editor.isEmpty && (this.iframeId !== 'newChat' && this.iframeId !== 'newAttachmentChat')) return this.getMessageSize(this.editor.getJSON()) if (this.chatMessageSize > 4000 ) { @@ -648,7 +655,8 @@ mwc-checkbox::shadow .mdc-checkbox::after, mwc-checkbox::shadow .mdc-checkbox::b return; } this.chatMessageSize = 0; - this._sendMessage(props, this.editor.getJSON()); + console.log('messageQueue', this.messageQueue) + this._sendMessage(props, this.editor.getJSON(), this.messageQueue); } getMessageSize(message){