diff --git a/qortal-ui-core/language/us.json b/qortal-ui-core/language/us.json index 2aa00796..c2bc9565 100644 --- a/qortal-ui-core/language/us.json +++ b/qortal-ui-core/language/us.json @@ -518,7 +518,11 @@ "bcchange10": "More", "bcchange11": "Reply", "bcchange12": "Edit", - "bcchange13": "Reaction" + "bcchange13": "Reaction", + "bcchange14": "Forward", + "bcchange15": "Message Forwarded", + "bcchange16": "Choose recipient", + "bcchange17": "FORWARDED" }, "grouppage": { "gchange1": "Qortal Groups", diff --git a/qortal-ui-plugins/plugins/core/components/ChatPage.js b/qortal-ui-plugins/plugins/core/components/ChatPage.js index 07b6c9ea..7fc5d3b0 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatPage.js +++ b/qortal-ui-plugins/plugins/core/components/ChatPage.js @@ -16,6 +16,7 @@ import './NameMenu.js'; import './TimeAgo.js'; import './ChatTextEditor'; import './WrapperModal'; +import './ChatSelect.js' import '@polymer/paper-spinner/paper-spinner-lite.js'; import '@material/mwc-button'; import '@material/mwc-dialog'; @@ -68,7 +69,10 @@ class ChatPage extends LitElement { lastMessageRefVisible: { type: Boolean }, isLoadingOldMessages: {type: Boolean}, isEditMessageOpen: { type: Boolean }, - webSocket: {attribute: false} + webSocket: {attribute: false}, + chatHeads: {type: Array}, + forwardActiveChatHeadUrl: {type: String}, + openForwardOpen: {type: Boolean} } } @@ -78,6 +82,15 @@ class ChatPage extends LitElement { scroll-behavior: smooth; } + .chat-head-container { + display: flex; + justify-content: flex-start; + flex-direction: column; + height: 50vh; + overflow-y: auto; + width: 100%; + } + .chat-container { display: grid; grid-template-rows: minmax(6%, 92vh) minmax(40px, auto); @@ -429,6 +442,11 @@ class ChatPage extends LitElement { height: 100%; } + .dialog-container-title { + color: var(--black); + font-size: 18px; + } + .dialog-container-loader { position: relative; display: flex; @@ -551,6 +569,7 @@ class ChatPage extends LitElement { position: 'top-start', boxShadow: 'rgba(4, 4, 5, 0.15) 0px 0px 0px 1px, rgba(0, 0, 0, 0.24) 0px 8px 16px 0px' }); + this.openForwardOpen = false } render() { @@ -705,11 +724,104 @@ class ChatPage extends LitElement { + { + this.openForwardOpen = false + this.forwardActiveChatHeadUrl = "" + } } + style=${this.openForwardOpen ? "display: block" : "display: none"}> +
+
+
+

${translate("blockpage.bcchange16")}

+
+
+ ${this.chatHeads.map((item)=> { + return html` { + this.forwardActiveChatHeadUrl = val + }} chatInfo=${JSON.stringify(item)}>` + })} +
+ + +
+
+
` } - + setForwardProperties(forwardedMessage){ + this.openForwardOpen = true + this.forwardedMessage = forwardedMessage + } + + async sendForwardMessage(){ + let parsedMessageObj = {} + let publicKey = { + hasPubKey: false, + key: '' + } + try { + parsedMessageObj = JSON.parse(this.forwardedMessage); + + } catch (error) { + parsedMessageObj = {} + } + + try { + const res = await parentEpml.request('apiCall', { + type: 'api', + url: `/addresses/publickey/${this.forwardChatId}` + }) + if (res.error === 102) { + publicKey.key = '' + publicKey.hasPubKey = false + } else if (res !== false) { + publicKey.key = res + publicKey.hasPubKey = true + } else { + publicKey.key = '' + publicKey.hasPubKey = false + } + } catch (error) { + + } + + try { + const message = { + ...parsedMessageObj, + type: 'forward' + } + const stringifyMessageObject = JSON.stringify(message) + this.sendMessage(stringifyMessageObject, undefined, '', true, { + isReceipient: true, + chatId: 'Qdxha59Cm1Ty4QkKMBWPnKrNigcDCDk6eq', + publicKey: { + hasPubKey: false, + key: '' + } + }) + } catch (error) { + console.log({error}) + } + } showLastMessageRefScroller(props) { this.lastMessageRefVisible = props; @@ -884,10 +996,12 @@ class ChatPage extends LitElement { .setEditedMessageObj=${(val) => this.setEditedMessageObj(val)} .focusChatEditor=${() => this.focusChatEditor()} .sendMessage=${(val) => this._sendMessage(val)} + .sendMessageForward=${(messageText, typeMessage, chatReference, isForward, forwardParams)=> this.sendMessage(messageText, typeMessage, chatReference, isForward, forwardParams)} .showLastMessageRefScroller=${(val) => this.showLastMessageRefScroller(val)} .emojiPicker=${this.emojiPicker} ?isLoadingMessages=${this.isLoadingOldMessages} .setIsLoadingMessages=${(val) => this.setIsLoadingMessages(val)} + .setForwardProperties=${(forwardedMessage)=> this.setForwardProperties(forwardedMessage)} > ` @@ -1147,7 +1261,6 @@ class ChatPage extends LitElement { async fetchChatMessages(chatId) { const initDirect = async (cid) => { - let initial = 0 let directSocketTimeout @@ -1646,8 +1759,7 @@ class ChatPage extends LitElement { } } - async sendMessage(messageText, typeMessage, chatReference) { - + async sendMessage(messageText, typeMessage, chatReference, isForward, forwardParams) { this.isLoading = true; let _reference = new Uint8Array(64); @@ -1695,7 +1807,55 @@ class ChatPage extends LitElement { } }; - const _computePow = async (chatBytes) => { + const sendForwardRequest = async () => { + const { publicKey } = forwardParams + + const isRecipient = this.forwardActiveChatHeadUrl.includes('direct') === true ? true : false; + + const chatId = this.forwardActiveChatHeadUrl.split('/')[1]; + this.openForwardOpen = false + if (isRecipient === true) { + let chatResponse = await parentEpml.request('chat', { + type: 18, + nonce: this.selectedAddress.nonce, + params: { + timestamp: Date.now(), + recipient: chatId, + recipientPublicKey: publicKey.key, + hasChatReference: 0, + chatReference: "", + message: messageText, + lastReference: reference, + proofOfWorkNonce: 0, + isEncrypted: publicKey.hasPubKey === false ? 0 : 1, + isText: 1 + } + }); + + _computePow(chatResponse, true) + } else { + let groupResponse = await parentEpml.request('chat', { + type: 181, + nonce: this.selectedAddress.nonce, + params: { + timestamp: Date.now(), + groupID: Number(chatId), + hasReceipient: 0, + hasChatReference: 0, + chatReference: chatReference, + message: messageText, + lastReference: reference, + proofOfWorkNonce: 0, + isEncrypted: 0, // Set default to not encrypted for groups + isText: 1 + } + }); + + _computePow(groupResponse, true) + } + }; + + const _computePow = async (chatBytes, isForward) => { const difficulty = this.balance === 0 ? 12 : 8; const path = window.parent.location.origin + '/memory-pow/memory-pow.wasm.full' const worker = new WebWorker(); @@ -1720,13 +1880,17 @@ class ChatPage extends LitElement { }); - getSendChatResponse(_response); + getSendChatResponse(_response, isForward); }; - const getSendChatResponse = (response) => { + const getSendChatResponse = (response, isForward) => { if (response === true) { this.chatEditor.resetValue(); this.chatEditorNewChat.resetValue() + if(isForward){ + let successString = get("blockpage.bcchange15"); + parentEpml.request('showSnackBar', `${successString}`); + } } else if (response.error) { parentEpml.request('showSnackBar', response.message); } else { @@ -1739,9 +1903,14 @@ class ChatPage extends LitElement { this.chatEditorNewChat.enable() this.closeEditMessageContainer() this.closeRepliedToContainer() + this.openForwardOpen = false + this.forwardActiveChatHeadUrl = "" }; - // Exec.. + if(isForward){ + sendForwardRequest(); + return + } sendMessageRequest(); } diff --git a/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js b/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js index d37a2d92..4b644c79 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js +++ b/qortal-ui-plugins/plugins/core/components/ChatScroller-css.js @@ -63,6 +63,12 @@ export const chatStyles = css` margin-bottom: 5px; } + .message-data-forward { + user-select: none; + color: var(--mainmenutext); + margin-bottom: 5px; + font-size: 12px; + } .message-data-my-name { color: #cf21e8; text-shadow: 0 0 3px #cf21e8; diff --git a/qortal-ui-plugins/plugins/core/components/ChatScroller.js b/qortal-ui-plugins/plugins/core/components/ChatScroller.js index 2893b3a5..204b302d 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatScroller.js +++ b/qortal-ui-plugins/plugins/core/components/ChatScroller.js @@ -30,11 +30,13 @@ class ChatScroller extends LitElement { setEditedMessageObj: {attribute: false}, focusChatEditor: {attribute: false}, sendMessage: {attribute: false}, + sendMessageForward: {attribute: false}, showLastMessageRefScroller: { type: Function }, emojiPicker: { attribute: false }, isLoadingMessages: { type: Boolean}, setIsLoadingMessages: {attribute: false}, - chatId: { type: String } + chatId: { type: String }, + setForwardProperties: {attribute: false}, } } @@ -51,6 +53,7 @@ class ChatScroller extends LitElement { render() { + console.log({messages: this.messages}) let formattedMessages = this.messages.reduce((messageArray, message) => { const lastGroupedMessage = messageArray[messageArray.length - 1]; let timestamp; @@ -96,10 +99,12 @@ class ChatScroller extends LitElement { .setEditedMessageObj=${this.setEditedMessageObj} .focusChatEditor=${this.focusChatEditor} .sendMessage=${this.sendMessage} + .sendMessageForward=${this.sendMessageForward} ?isFirstMessage=${indexMessage === 0} ?isSingleMessageInGroup=${formattedMessage.messages.length > 1} ?isLastMessageInGroup=${indexMessage === formattedMessage.messages.length - 1} .setToggledMessage=${this.setToggledMessage} + .setForwardProperties=${this.setForwardProperties} > ` ) @@ -219,12 +224,14 @@ class MessageTemplate extends LitElement { setEditedMessageObj: {attribute: false}, focusChatEditor: {attribute: false}, sendMessage: {attribute: false}, + sendMessageForward: {attribute: false}, openDialogImage: {attribute: false}, isImageLoaded: { type: Boolean }, isFirstMessage: { type: Boolean }, isSingleMessageInGroup: { type: Boolean }, isLastMessageInGroup: { type: Boolean }, - setToggledMessage: {attribute: false} + setToggledMessage: {attribute: false}, + setForwardProperties: {attribute: false}, } } @@ -279,6 +286,7 @@ class MessageTemplate extends LitElement { let image = null; let isImageDeleted = false; let version = 0; + let isForwarded = false try { const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage); message = parsedMessageObj.messageText; @@ -286,6 +294,7 @@ class MessageTemplate extends LitElement { isImageDeleted = parsedMessageObj.isImageDeleted; reactions = parsedMessageObj.reactions || []; version = parsedMessageObj.version + isForwarded = parsedMessageObj.type === 'forward' if (parsedMessageObj.images && Array.isArray(parsedMessageObj.images) && parsedMessageObj.images.length > 0) { image = parsedMessageObj.images[0]; } @@ -299,6 +308,7 @@ class MessageTemplate extends LitElement { let nameMenu = ''; let levelFounder = ''; let hideit = hidemsg.includes(this.messageObj.sender); + let forwarded = '' levelFounder = html``; if (this.messageObj.senderName) { @@ -352,6 +362,11 @@ class MessageTemplate extends LitElement { ${this.messageObj.senderName ? this.messageObj.senderName : cropAddress(this.messageObj.sender)} `; + forwarded = html` + + ${translate("blockpage.bcchange17")} + + `; if (repliedToData) { try { @@ -414,6 +429,14 @@ class MessageTemplate extends LitElement { ` : null } + ${isForwarded ? + html` + + ${forwarded} + + ` + : null + } ${this.isFirstMessage ? ( html` ${levelFounder} @@ -480,9 +503,11 @@ class MessageTemplate extends LitElement { .myAddress=${this.myAddress} @blur=${() => this.showBlockIconFunc(false)} .sendMessage=${this.sendMessage} + .sendMessageForward=${this.sendMessageForward} version=${version} .emojiPicker=${this.emojiPicker} .setToggledMessage=${this.setToggledMessage} + .setForwardProperties=${this.setForwardProperties} > @@ -559,7 +584,9 @@ class ChatMenu extends LitElement { emojiPicker: { attribute: false }, sendMessage: {attribute: false}, version: {type: String}, - setToggledMessage: {attribute: false} + setToggledMessage: {attribute: false}, + sendMessageForward: {attribute: false}, + setForwardProperties: {attribute: false} } } @@ -589,6 +616,51 @@ class ChatMenu extends LitElement { parentEpml.request('showSnackBar', `${errorMsg}`) } + async messageForwardFunc(){ + let parsedMessageObj = {} + let publicKey = { + hasPubKey: false, + key: '' + } + try { + parsedMessageObj = JSON.parse(this.originalMessage.decodedMessage); + + } catch (error) { + parsedMessageObj = {} + } + + try { + const res = await parentEpml.request('apiCall', { + type: 'api', + url: `/addresses/publickey/${this._chatId}` + }) + if (res.error === 102) { + publicKey.key = '' + publicKey.hasPubKey = false + } else if (res !== false) { + publicKey.key = res + publicKey.hasPubKey = true + } else { + publicKey.key = '' + publicKey.hasPubKey = false + } + } catch (error) { + + } + + try { + const message = { + ...parsedMessageObj, + type: 'forward' + } + const stringifyMessageObject = JSON.stringify(message) + this.setForwardProperties(stringifyMessageObject) + + } catch (error) { + console.log({error}) + } + } + render() { return html`
@@ -610,6 +682,14 @@ class ChatMenu extends LitElement { }} > +
+