diff --git a/qortal-ui-core/font/switch-theme.css b/qortal-ui-core/font/switch-theme.css index 110700a3..3d164a7c 100644 --- a/qortal-ui-core/font/switch-theme.css +++ b/qortal-ui-core/font/switch-theme.css @@ -28,6 +28,7 @@ html { --relaynodetxt: #646464; --menuhover: #eeeeee; --menuactive: #ebebeb; + --menuactivergb: 235, 235, 235; --mainmenutext: #080808; --mainmenutexthover: #080808; --switchbackground: #666666; @@ -82,6 +83,7 @@ html[theme="dark"] { --relaynodetxt: #d4d4d4; --menuhover: #008fd5; --menuactive: #008fd5; + --menuactivergb: 0, 143, 213; --mainmenutext: #008fd5; --mainmenutexthover: #0f1a2e; --switchbackground: #eeeeee; diff --git a/qortal-ui-core/language/us.json b/qortal-ui-core/language/us.json index 73232b58..43efa61b 100644 --- a/qortal-ui-core/language/us.json +++ b/qortal-ui-core/language/us.json @@ -571,7 +571,8 @@ "cchange62": "Wrong Username and Address Inputted! Please try again!", "cchange63": "Enter Enabled", "cchange64": "Enter Disabled", - "cchange65": "Please enter a recipient" + "cchange65": "Please enter a recipient", + "cchange66": "Cannot fetch replied-to message. Message is too old." }, "welcomepage": { diff --git a/qortal-ui-plugins/plugins/core/components/ChatPage.js b/qortal-ui-plugins/plugins/core/components/ChatPage.js index a4f3a414..1274da7e 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatPage.js +++ b/qortal-ui-plugins/plugins/core/components/ChatPage.js @@ -102,7 +102,8 @@ class ChatPage extends LitElement { openTipUser: { type: Boolean }, openUserInfo: { type: Boolean }, selectedHead: { type: Object }, - userName: { type: String } + userName: { type: String }, + goToRepliedMessage: {attribute: false} } } @@ -906,7 +907,6 @@ class ChatPage extends LitElement { } setUserName(props) { - console.log({props}) this.userName = props.senderName ? props.senderName : props.sender; this.setSelectedHead(props); } @@ -925,7 +925,6 @@ class ChatPage extends LitElement { } render() { - console.log(this.userName, "username here"); return html`
{ + findElement.classList.remove('blink-bg') + }, 2000) + } + + return + } + if((message.timestamp - this.messagesRendered[0].timestamp) > 86400000){ + let errorMsg = get("chatpage.cchange66") + parentEpml.request('showSnackBar', `${errorMsg}`) + return + } + + if((message.timestamp - this.messagesRendered[0].timestamp) < 86400000){ + await this.getOldMessageDynamic(0, this.messagesRendered[0].timestamp, message.timestamp - 7200000) + const findMessage = this.shadowRoot.querySelector('chat-scroller').shadowRoot.getElementById(message.reference) + if(findMessage){ + findMessage.scrollIntoView({ behavior: 'smooth', block: 'center' }) + const findElement = findMessage.shadowRoot.querySelector('.message-parent') + if(findElement){ + findElement.classList.add('blink-bg') + setTimeout(()=> { + findElement.classList.remove('blink-bg') + }, 2000) + } + + return + } + + let errorMsg = get("chatpage.cchange66") + parentEpml.request('showSnackBar', `${errorMsg}`) + + } + + } + async userSearch() { const nameValue = this.shadowRoot.getElementById('sendTo').value; if (!nameValue) { @@ -1616,7 +1658,6 @@ class ChatPage extends LitElement { this.groupAdmin = membersAdminsWithName this.groupMembers = membersWithName this.groupInfo = getGroupInfo - console.log({membersAdminsWithName}) } catch (error) { console.error(error) } @@ -1749,6 +1790,8 @@ class ChatPage extends LitElement { .setSelectedHead=${(val) => this.setSelectedHead(val)} ?openTipUser=${this.openTipUser} .selectedHead=${this.selectedHead} + .goToRepliedMessage=${(val)=> this.goToRepliedMessage(val)} + .getOldMessageAfter=${(val)=> this.getOldMessageAfter(val)} > ` @@ -1782,6 +1825,81 @@ class ChatPage extends LitElement { }) } + async getOldMessageDynamic(limit, before, after) { + + 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=${limit}&reverse=true&before=${before}&after=${after}&haschatreference=false`, + }); + + const decodeMsgs = getInitialMessages.map((eachMessage) => { + return this.decodeMessage(eachMessage) + }) + + + const replacedMessages = await replaceMessagesEdited({ + decodedMessages: decodeMsgs, + parentEpml, + isReceipient: this.isReceipient, + decodeMessageFunc: this.decodeMessage, + _publicKey: this._publicKey + }) + this.messagesRendered = [...replacedMessages, ...this.messagesRendered].sort(function (a, b) { + return a.timestamp + - b.timestamp + }) + this.isLoadingOldMessages = false + await this.getUpdateComplete(); + const viewElement = this.shadowRoot.querySelector('chat-scroller').shadowRoot.getElementById('viewElement'); + + if(viewElement){ + viewElement.scrollTop = 200 + } + + + + + + } else { + const getInitialMessages = await parentEpml.request('apiCall', { + type: 'api', + url: `/chat/messages?txGroupId=${Number(this._chatId)}&limit=${limit}&reverse=true&before=${before}&after=${after}&haschatreference=false`, + }); + + + const decodeMsgs = getInitialMessages.map((eachMessage) => { + return this.decodeMessage(eachMessage) + }) + + const replacedMessages = await replaceMessagesEdited({ + decodedMessages: decodeMsgs, + parentEpml, + isReceipient: this.isReceipient, + decodeMessageFunc: this.decodeMessage, + _publicKey: this._publicKey + }) + + this.messagesRendered = [...replacedMessages, ...this.messagesRendered].sort(function (a, b) { + return a.timestamp + - b.timestamp + }) + this.isLoadingOldMessages = false + await this.getUpdateComplete(); + const viewElement = this.shadowRoot.querySelector('chat-scroller').shadowRoot.getElementById('viewElement'); + + if(viewElement){ + viewElement.scrollTop = 200 + } + + + + + + } + } + + async getOldMessage(scrollElement) { if (this.isReceipient) { @@ -1853,6 +1971,77 @@ class ChatPage extends LitElement { } } + async getOldMessageAfter(scrollElement) { + + 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&afer=${scrollElement.messageObj.timestamp}&haschatreference=false`, + }); + + const decodeMsgs = getInitialMessages.map((eachMessage) => { + return this.decodeMessage(eachMessage) + }) + + + const replacedMessages = await replaceMessagesEdited({ + decodedMessages: decodeMsgs, + parentEpml, + isReceipient: this.isReceipient, + decodeMessageFunc: this.decodeMessage, + _publicKey: this._publicKey + }) + this.messagesRendered = [...this.messagesRendered, ...replacedMessages].sort(function (a, b) { + return a.timestamp + - b.timestamp + }) + this.isLoadingOldMessages = false + await this.getUpdateComplete(); + const marginElements = Array.from(this.shadowRoot.querySelector('chat-scroller').shadowRoot.querySelectorAll('message-template')); + + const findElement = marginElements.find((item)=> item.messageObj.reference === scrollElement.messageObj.reference) + + if(findElement){ + findElement.scrollIntoView({ behavior: 'auto', block: 'center' }); + } + + + } else { + const getInitialMessages = await parentEpml.request('apiCall', { + type: 'api', + url: `/chat/messages?txGroupId=${Number(this._chatId)}&limit=20&reverse=true&after=${scrollElement.messageObj.timestamp}&haschatreference=false`, + }); + + + const decodeMsgs = getInitialMessages.map((eachMessage) => { + return this.decodeMessage(eachMessage) + }) + + const replacedMessages = await replaceMessagesEdited({ + decodedMessages: decodeMsgs, + parentEpml, + isReceipient: this.isReceipient, + decodeMessageFunc: this.decodeMessage, + _publicKey: this._publicKey + }) + + this.messagesRendered = [ ...this.messagesRendered, ...replacedMessages].sort(function (a, b) { + return a.timestamp + - b.timestamp + }) + this.isLoadingOldMessages = false + await this.getUpdateComplete(); + const marginElements = Array.from(this.shadowRoot.querySelector('chat-scroller').shadowRoot.querySelectorAll('message-template')); + const findElement = marginElements.find((item)=> item.messageObj.reference === scrollElement.messageObj.reference) + + if(findElement){ + findElement.scrollIntoView({ behavior: 'auto', block: 'center' }); + } + + + } + } + async processMessages(messages, isInitial) { const isReceipient = this.chatId.includes('direct') const decodedMessages = messages.map((eachMessage) => { @@ -2002,7 +2191,6 @@ class ChatPage extends LitElement { let decodedMessageObj = {}; if (isReceipientVar === true) { - console.log('encoded', encodedMessageObj.isEncrypted, _publicKeyVar.hasPubKey,encodedMessageObj.data) // direct chat if (encodedMessageObj.isEncrypted === true && _publicKeyVar.hasPubKey === true && encodedMessageObj.data) { let decodedMessage = window.parent.decryptChatMessage(encodedMessageObj.data, window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey, _publicKeyVar.key, encodedMessageObj.reference); @@ -2653,7 +2841,6 @@ class ChatPage extends LitElement { type: 'api', url: `/names/${userInput}` }); - console.log({validatedAddress, validatedUsername }) if (validatedAddress && validatedUsername.name) { userPubkey = await parentEpml.request('apiCall', { diff --git a/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js b/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js index 06f2607a..27c4a6fe 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js +++ b/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js @@ -172,6 +172,7 @@ export const chatStyles = css` border-radius: 5px; padding: 8px 5px 8px 25px; margin-bottom: 10px; + cursor: pointer; } .original-message:before { @@ -187,6 +188,7 @@ export const chatStyles = css` .original-message-sender { margin: 0 0 5px 0; color: var(--mdc-theme-primary); + cursor: pointer; } .replied-message { @@ -640,4 +642,14 @@ export const chatStyles = css` border-top: 2px solid rgba(#0D0D0D, 0.1); margin: 2rem 0; } + + .blink-bg{ + border-radius: 8px; + animation: blinkingBackground 3s; + } + @keyframes blinkingBackground{ + 0% { background-color: rgba(var(--menuactivergb), 1)} + + 100% { background-color:rgba(var(--menuactivergb), 0)} + } ` diff --git a/qortal-ui-plugins/plugins/core/components/ChatScroller.js b/qortal-ui-plugins/plugins/core/components/ChatScroller.js index e9db4e5e..cf021483 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatScroller.js +++ b/qortal-ui-plugins/plugins/core/components/ChatScroller.js @@ -50,7 +50,9 @@ class ChatScroller extends LitElement { openTipUser: { type: Boolean }, openUserInfo: { type: Boolean }, userName: { type: String }, - selectedHead: { type: Object } + selectedHead: { type: Object }, + goToRepliedMessage: { attribute: false }, + getOldMessageAfter: {attribute: false} } } @@ -101,6 +103,7 @@ class ChatScroller extends LitElement { } return messageArray; }, []) + return html` ${this.isLoadingMessages ? html` @@ -132,7 +135,10 @@ class ChatScroller extends LitElement { .setOpenPrivateMessage=${(val) => this.setOpenPrivateMessage(val)} .setOpenTipUser=${(val) => this.setOpenTipUser(val)} .setOpenUserInfo=${(val) => this.setOpenUserInfo(val)} - .setUserName=${(val) => this.setUserName(val)}> + .setUserName=${(val) => this.setUserName(val)} + id=${message.reference} + .goToRepliedMessage=${this.goToRepliedMessage} + > ` ) })} @@ -195,6 +201,10 @@ class ChatScroller extends LitElement { this.getOldMessage(_scrollElement) } + _getOldMessageAfter(_scrollElement) { + this.getOldMessageAfter(_scrollElement) + } + _upObserverhandler(entries) { if (entries[0].isIntersecting) { if(this.messages.length < 20){ @@ -208,6 +218,8 @@ class ChatScroller extends LitElement { _downObserverHandler(entries) { if (!entries[0].isIntersecting) { + let _scrollElement = entries[0].target.previousElementSibling; + // this._getOldMessageAfter(_scrollElement); this.showLastMessageRefScroller(true); } else { this.showLastMessageRefScroller(false); @@ -270,7 +282,8 @@ class MessageTemplate extends LitElement { setOpenTipUser: { attribute: false }, setOpenUserInfo: { attribute: false }, setUserName: { attribute: false }, - openTipUser:{ type: Boolean } + openTipUser:{ type: Boolean }, + goToRepliedMessage: { attribute: false }, } } @@ -511,14 +524,13 @@ class MessageTemplate extends LitElement { ) : null}
${repliedToData && html` -
+
{ + this.goToRepliedMessage(repliedToData) + }}>

{ - if (this.myAddress === repliedToData.sender) return; - this.setOpenUserInfo(true); - this.setUserName(repliedToData) - }} + + class="original-message-sender"> ${repliedToData.senderName ?? cropAddress(repliedToData.sender)}