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 {
}}
>
+
+