From 74cf2d13a5787c3ef4b89dc2b5037708be15941b Mon Sep 17 00:00:00 2001 From: Justin Ferrari <‘justinwesleyferrari@gmail.com’> Date: Fri, 9 Dec 2022 20:55:28 +0100 Subject: [PATCH 01/15] Started private message refactor --- .../plugins/core/components/ChatPage.js | 13 ----- .../plugins/core/components/ChatTextEditor.js | 3 +- .../core/messaging/q-chat/q-chat.src.js | 55 +++++++++++++++---- 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/qortal-ui-plugins/plugins/core/components/ChatPage.js b/qortal-ui-plugins/plugins/core/components/ChatPage.js index ad197b91..4f92363b 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatPage.js +++ b/qortal-ui-plugins/plugins/core/components/ChatPage.js @@ -510,7 +510,6 @@ class ChatPage extends LitElement { constructor() { super() - this.changeMsgInput = this.changeMsgInput.bind(this) this.getOldMessage = this.getOldMessage.bind(this) this._sendMessage = this._sendMessage.bind(this) this.insertImage = this.insertImage.bind(this) @@ -629,9 +628,7 @@ class ChatPage extends LitElement { .chatEditor=${this.chatEditor} .imageFile=${this.imageFile} .insertImage=${this.insertImage} - .chatMessageInput=${this.chatMessageInput} .editedMessageObj=${this.editedMessageObj} - .mirrorChatInput=${this.mirrorChatInput} ?isLoading=${this.isLoading} ?isLoadingMessages=${this.isLoadingMessages} ?isEditMessageOpen=${this.isEditMessageOpen}> @@ -726,9 +723,6 @@ class ChatPage extends LitElement { if (file.type.includes('image')) { this.imageFile = file; this.chatEditor.disable(); - // this.changeMsgInput('newChat') - // this.initChatEditor(); - // this.chatEditor.disable(); return; } parentEpml.request('showSnackBar', get("chatpage.cchange28")); @@ -739,13 +733,6 @@ class ChatPage extends LitElement { this.chatEditor.enable(); } - changeMsgInput(id) { - - this.chatEditor.remove() - this.chatMessageInput = this.shadowRoot.getElementById(id); - this.initChatEditor(); - } - async firstUpdated() { window.addEventListener('storage', () => { const checkLanguage = localStorage.getItem('qortalLanguage'); diff --git a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js index b2a16f89..77719560 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js +++ b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js @@ -172,7 +172,7 @@ class ChatTextEditor extends LitElement { } return html`
{ this.preventUserSendingImage(e) @@ -300,7 +300,6 @@ class ChatTextEditor extends LitElement { } }) - this.emojiPickerHandler = this.shadowRoot.querySelector('.emoji-button'); this.mirrorChatInput = this.shadowRoot.getElementById('messageBox'); this.chatMessageInput = this.shadowRoot.getElementById(this.iframeId); diff --git a/qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js b/qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js index 5de97d52..49d5c148 100644 --- a/qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js +++ b/qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js @@ -34,7 +34,10 @@ class Chat extends LitElement { balance: { type: Number }, theme: { type: String, reflect: true }, blockedUsers: { type: Array }, - blockedUserList: { type: Array } + blockedUserList: { type: Array }, + privateMessagePlaceholder: { type: String}, + chatEditor: { type: Object }, + imageFile: { type: Object } } } @@ -321,9 +324,12 @@ class Chat extends LitElement { this.isLoading = false this.showNewMesssageBar = this.showNewMesssageBar.bind(this) this.hideNewMesssageBar = this.hideNewMesssageBar.bind(this) + this.insertImage = this.insertImage.bind(this) this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' this.blockedUsers = [] this.blockedUserList = [] + this.privateMessagePlaceholder = "" + this.imageFile = null } render() { @@ -362,17 +368,33 @@ class Chat extends LitElement {

${translate("chatpage.cchange6")}

- -

- -

- + + + this.setChatEditor(editor)} + .chatEditor=${this.chatEditor} + .imageFile=${this.imageFile} + .insertImage=${this.insertImage} + ?isLoading=${this.isLoading}> + + - ${this.isLoading === false ? this.renderSendText() : html``} + ${this.isLoading === false ? this.renderSendText() : html``} - ${translate("general.close")} + ${translate("general.close")} @@ -416,7 +438,6 @@ class Chat extends LitElement { } firstUpdated() { - this.changeLanguage() this.changeTheme() this.getChatBlockedList() @@ -523,6 +544,7 @@ class Chat extends LitElement { this.config = JSON.parse(c) }) parentEpml.subscribe('chat_heads', chatHeads => { + console.log("here51"); chatHeads = JSON.parse(chatHeads) this.getChatHeadFromState(chatHeads) }) @@ -542,6 +564,19 @@ class Chat extends LitElement { parentEpml.imReady() } + setChatEditor(editor) { + this.chatEditor = editor; + } + + insertImage(file) { + if (file.type.includes('image')) { + this.imageFile = file; + this.chatEditor.disable(); + return; + } + parentEpml.request('showSnackBar', get("chatpage.cchange28")); + } + renderLoadingText() { return html`${translate("chatpage.cchange2")}` } @@ -712,7 +747,7 @@ class Chat extends LitElement { const compareArgs = (a, b) => { return b.timestamp - a.timestamp } - + console.log({chatHeadMasterList}); this.chatHeads = chatHeadMasterList.sort(compareArgs) } From c34cf0fda8cb9615a322af988994f337d8255fed Mon Sep 17 00:00:00 2001 From: Justin Ferrari <‘justinwesleyferrari@gmail.com’> Date: Mon, 12 Dec 2022 21:50:55 -0500 Subject: [PATCH 02/15] Started private message with chat-text-editor --- .../plugins/core/components/ChatPage.js | 16 +- .../plugins/core/components/ChatTextEditor.js | 12 +- .../core/messaging/q-chat/q-chat.src.js | 323 +++++++++--------- 3 files changed, 176 insertions(+), 175 deletions(-) diff --git a/qortal-ui-plugins/plugins/core/components/ChatPage.js b/qortal-ui-plugins/plugins/core/components/ChatPage.js index 4f92363b..158d24eb 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatPage.js +++ b/qortal-ui-plugins/plugins/core/components/ChatPage.js @@ -1554,35 +1554,31 @@ class ChatPage extends LitElement { users: [this.selectedAddress.address] }] } - const messageObject = { ...message, reactions - } const stringifyMessageObject = JSON.stringify(messageObject) this.sendMessage(stringifyMessageObject, typeMessage, chatReference); - } else if (/^\s*$/.test(trimmedMessage)) { this.isLoading = false; this.chatEditor.enable(); - this.chatEditorNewChat.enable() + this.chatEditorNewChat.enable(); } else if (this.repliedToMessageObj) { - let chatReference = this.repliedToMessageObj.reference - + let chatReference = this.repliedToMessageObj.reference; if(this.repliedToMessageObj.chatReference){ - chatReference = this.repliedToMessageObj.chatReference + chatReference = this.repliedToMessageObj.chatReference; } - typeMessage = 'reply' + typeMessage = 'reply'; const messageObject = { messageText: trimmedMessage, images: [''], repliedTo: chatReference, version: 1 } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage ); + const stringifyMessageObject = JSON.stringify(messageObject); + this.sendMessage(stringifyMessageObject, typeMessage); } else if (this.editedMessageObj) { typeMessage = 'edit' let chatReference = this.editedMessageObj.reference diff --git a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js index 8809cba0..76b9d39d 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js +++ b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js @@ -223,7 +223,13 @@ class ChatTextEditor extends LitElement { ` ) : html` -
+
${this.isLoading === false ? html` 1000 ) { parentEpml.request('showSnackBar', get("chatpage.cchange29")); return; }; this.chatMessageSize = 0; - this._sendMessage(props); + this._sendMessage(); } getMessageSize(message){ diff --git a/qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js b/qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js index 49d5c148..7a17b6a7 100644 --- a/qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js +++ b/qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js @@ -2,6 +2,7 @@ import { LitElement, html, css } from 'lit' import { render } from 'lit/html.js' import { Epml } from '../../../../epml.js' import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate' +import WebWorker from 'web-worker:../../components/computePowWorker.js'; registerTranslateConfig({ loader: lang => fetch(`/language/${lang}.json`).then(res => res.json()) @@ -324,6 +325,7 @@ class Chat extends LitElement { this.isLoading = false this.showNewMesssageBar = this.showNewMesssageBar.bind(this) this.hideNewMesssageBar = this.hideNewMesssageBar.bind(this) + this._sendMessage = this._sendMessage.bind(this) this.insertImage = this.insertImage.bind(this) this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' this.blockedUsers = [] @@ -381,10 +383,10 @@ class Chat extends LitElement { iframeId="privateMessage" ?hasGlobalEvents=${true} placeholder="${translate("chatpage.cchange8")}" - _sendMessage=${this._sendMessage} .setChatEditor=${(editor)=> this.setChatEditor(editor)} .chatEditor=${this.chatEditor} - .imageFile=${this.imageFile} + .imageFile=${this.imageFile}. + ._sendMessage=${this._sendMessage} .insertImage=${this.insertImage} ?isLoading=${this.isLoading}> @@ -392,7 +394,7 @@ class Chat extends LitElement { ${this.isLoading === false ? this.renderSendText() : html``} @@ -544,7 +546,6 @@ class Chat extends LitElement { this.config = JSON.parse(c) }) parentEpml.subscribe('chat_heads', chatHeads => { - console.log("here51"); chatHeads = JSON.parse(chatHeads) this.getChatHeadFromState(chatHeads) }) @@ -568,6 +569,162 @@ class Chat extends LitElement { this.chatEditor = editor; } + async _sendMessage() { + console.log("here1"); + this.isLoading = true; + this.chatEditor.disable(); + const messageText = this.chatEditor.mirror.value; + // Format and Sanitize Message + const sanitizedMessage = messageText.replace(/ /gi, ' ').replace(//gi, '\n'); + const trimmedMessage = sanitizedMessage.trim(); + + if (/^\s*$/.test(trimmedMessage)) { + this.isLoading = false; + this.chatEditor.enable(); + } else { + const messageObject = { + messageText: trimmedMessage, + images: [''], + repliedTo: '', + version: 1 + } + const stringifyMessageObject = JSON.stringify(messageObject) + this.sendMessage(stringifyMessageObject); + } + console.log("here2"); + } + + async sendMessage(messageText) { + console.log("here3"); + this.isLoading = true; + + const _recipient = this.shadowRoot.getElementById('sendTo').value; + + let recipient; + + const validateName = async (receiverName) => { + let myRes; + try { + let myNameRes = await parentEpml.request('apiCall', { + type: 'api', + url: `/names/${receiverName}` + }); + if (myNameRes.error === 401) { + myRes = false; + } else { + myRes = myNameRes; + } + return myRes; + } catch (error) { + return ""; + } + }; + + const myNameRes = await validateName(_recipient); + if (!myNameRes) { + recipient = _recipient; + } else { + recipient = myNameRes.owner; + }; + + const getAddressPublicKey = async () => { + let isEncrypted; + let _publicKey; + + let addressPublicKey = await parentEpml.request('apiCall', { + type: 'api', + url: `/addresses/publickey/${recipient}` + }) + + if (addressPublicKey.error === 102) { + _publicKey = false; + let err4string = get("chatpage.cchange19"); + parentEpml.request('showSnackBar', `${err4string}`); + this.isLoading = false; + } else if (addressPublicKey !== false) { + isEncrypted = 1; + _publicKey = addressPublicKey; + sendMessageRequest(isEncrypted, _publicKey); + } else { + isEncrypted = 0; + _publicKey = this.selectedAddress.address; + sendMessageRequest(isEncrypted, _publicKey); + } + }; + let _reference = new Uint8Array(64); + window.crypto.getRandomValues(_reference); + let reference = window.parent.Base58.encode(_reference); + const sendMessageRequest = async (isEncrypted, _publicKey) => { + let chatResponse = await parentEpml.request('chat', { + type: 18, + nonce: this.selectedAddress.nonce, + params: { + timestamp: Date.now(), + recipient: recipient, + recipientPublicKey: _publicKey, + hasChatReference: 0, + message: messageText, + lastReference: reference, + proofOfWorkNonce: 0, + isEncrypted: isEncrypted, + isText: 1 + } + }); + console.log({chatResponse}); + + _computePow(chatResponse); + }; + + const _computePow = async (chatBytes) => { + const difficulty = this.balance === 0 ? 12 : 8; + const path = window.parent.location.origin + '/memory-pow/memory-pow.wasm.full'; + console.log("here4"); + const worker = new WebWorker(); + console.log("here5"); + let nonce = null; + let chatBytesArray = null; + await new Promise((res, rej) => { + console.log(chatBytes, "chatBytes"); + console.log(path, "path"); + console.log(difficulty, "difficulty"); + worker.postMessage({chatBytes, path, difficulty}); + + worker.onmessage = e => { + worker.terminate(); + chatBytesArray = e.data.chatBytesArray; + nonce = e.data.nonce; + res(); + } + }); + + let _response = await parentEpml.request('sign_chat', { + nonce: this.selectedAddress.nonce, + chatBytesArray: chatBytesArray, + chatNonce: nonce + }); + + getSendChatResponse(_response); + }; + + const getSendChatResponse = (response) => { + if (response === true) { + this.chatEditor.resetValue(); + } else if (response.error) { + parentEpml.request('showSnackBar', response.message); + } else { + let err2string = get("chatpage.cchange21"); + parentEpml.request('showSnackBar', `${err2string}`); + } + + this.isLoading = false; + this.chatEditor.enable(); + }; + + // Exec.. + getAddressPublicKey(); + + } + insertImage(file) { if (file.type.includes('image')) { this.imageFile = file; @@ -747,7 +904,6 @@ class Chat extends LitElement { const compareArgs = (a, b) => { return b.timestamp - a.timestamp } - console.log({chatHeadMasterList}); this.chatHeads = chatHeadMasterList.sort(compareArgs) } @@ -762,163 +918,6 @@ class Chat extends LitElement { } } - _sendMessage() { - - this.isLoading = true - - const recipient = this.shadowRoot.getElementById('sendTo').value - const messageBox = this.shadowRoot.getElementById('messageBox') - const messageText = messageBox.value - - if (recipient.length === 0) { - this.isLoading = false - } else if (messageText.length === 0) { - this.isLoading = false - } else { - this.sendMessage() - } - } - - async sendMessage(e) { - - this.isLoading = true - - const _recipient = this.shadowRoot.getElementById('sendTo').value - const messageBox = this.shadowRoot.getElementById('messageBox') - const messageText = messageBox.value - let recipient - - const validateName = async (receiverName) => { - - let myRes - let myNameRes = await parentEpml.request('apiCall', { - type: 'api', - url: `/names/${receiverName}` - }) - - if (myNameRes.error === 401) { - myRes = false - } else { - myRes = myNameRes - } - return myRes - } - - const myNameRes = await validateName(_recipient) - if (!myNameRes) { - - recipient = _recipient - } else { - - recipient = myNameRes.owner - } - - let _reference = new Uint8Array(64); - window.crypto.getRandomValues(_reference); - - let sendTimestamp = Date.now() - - let reference = window.parent.Base58.encode(_reference) - - const getAddressPublicKey = async () => { - let isEncrypted - let _publicKey - - let addressPublicKey = await parentEpml.request('apiCall', { - type: 'api', - url: `/addresses/publickey/${recipient}` - }) - - if (addressPublicKey.error === 102) { - _publicKey = false - let err4string = get("chatpage.cchange19") - parentEpml.request('showSnackBar', `${err4string}`) - this.isLoading = false - } else if (addressPublicKey !== false) { - isEncrypted = 1 - _publicKey = addressPublicKey - sendMessageRequest(isEncrypted, _publicKey) - } else { - isEncrypted = 0 - _publicKey = this.selectedAddress.address - sendMessageRequest(isEncrypted, _publicKey) - } - }; - - const sendMessageRequest = async (isEncrypted, _publicKey) => { - const messageObject = { - messageText, - images: [''], - repliedTo: '', - version: 1 - } - const stringifyMessageObject = JSON.stringify(messageObject) - let chatResponse = await parentEpml.request('chat', { - type: 18, - nonce: this.selectedAddress.nonce, - params: { - timestamp: sendTimestamp, - recipient: recipient, - recipientPublicKey: _publicKey, - hasChatReference: 0, - message: stringifyMessageObject, - lastReference: reference, - proofOfWorkNonce: 0, - isEncrypted: isEncrypted, - isText: 1 - } - }) - - _computePow(chatResponse) - } - - const _computePow = async (chatBytes) => { - - const _chatBytesArray = Object.keys(chatBytes).map(function (key) { return chatBytes[key]; }); - const chatBytesArray = new Uint8Array(_chatBytesArray) - const chatBytesHash = new window.parent.Sha256().process(chatBytesArray).finish().result - const hashPtr = window.parent.sbrk(32, window.parent.heap); - const hashAry = new Uint8Array(window.parent.memory.buffer, hashPtr, 32) - - hashAry.set(chatBytesHash); - - const difficulty = this.balance === 0 ? 12 : 8 - - const workBufferLength = 8 * 1024 * 1024; - const workBufferPtr = window.parent.sbrk(workBufferLength, window.parent.heap) - - let nonce = window.parent.computePow(hashPtr, workBufferPtr, workBufferLength, difficulty) - - let _response = await parentEpml.request('sign_chat', { - nonce: this.selectedAddress.nonce, - chatBytesArray: chatBytesArray, - chatNonce: nonce - }) - - getSendChatResponse(_response) - } - - const getSendChatResponse = (response) => { - - if (response === true) { - messageBox.value = "" - let err5string = get("chatpage.cchange20") - parentEpml.request('showSnackBar', `${err5string}`) - this.isLoading = false - } else if (response.error) { - parentEpml.request('showSnackBar', response.message) - this.isLoading = false - } else { - let err6string = get("chatpage.cchange21") - parentEpml.request('showSnackBar', `${err6string}`) - this.isLoading = false - } - } - - // Exec.. - getAddressPublicKey() - } - _textMenu(event) { const getSelectedText = () => { From 0dc1f5ec79940cc4c6e76b49cabffd79e28e38a8 Mon Sep 17 00:00:00 2001 From: Justin Ferrari <‘justinwesleyferrari@gmail.com’> Date: Fri, 16 Dec 2022 11:41:51 -0500 Subject: [PATCH 03/15] Fixed private message bugs --- .../plugins/core/components/ChatPage.js | 8 +- .../plugins/core/components/ChatTextEditor.js | 18 +- .../plugins/core/components/WrapperModal.js | 5 +- .../core/messaging/q-chat/q-chat.src.js | 207 ++++++++++++------ 4 files changed, 153 insertions(+), 85 deletions(-) diff --git a/qortal-ui-plugins/plugins/core/components/ChatPage.js b/qortal-ui-plugins/plugins/core/components/ChatPage.js index 48edbb1f..8cdf5510 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatPage.js +++ b/qortal-ui-plugins/plugins/core/components/ChatPage.js @@ -673,9 +673,9 @@ class ChatPage extends LitElement {
`: ''} { - this.chatEditorNewChat.resetValue() - this.removeImage() + .onClickFunc=${() => { + this.chatEditorNewChat.resetValue(); + this.removeImage(); } } style=${(this.imageFile && !this.isUploadingImage) ? "display: block" : "display: none"}>
@@ -724,7 +724,7 @@ class ChatPage extends LitElement {
{ + .onClickFunc=${() => { this.openForwardOpen = false this.forwardActiveChatHeadUrl = "" } } diff --git a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js index 76b9d39d..7db0986c 100644 --- a/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js +++ b/qortal-ui-plugins/plugins/core/components/ChatTextEditor.js @@ -174,9 +174,12 @@ class ChatTextEditor extends LitElement {
-
{ - this.preventUserSendingImage(e) - }}> +
{ + this.preventUserSendingImage(e) + }}> this.emojiPicker.togglePicker(this.emojiPickerHandler)); + this.emojiPickerHandler.addEventListener('click', () => { + console.log("yo what's up?") + this.emojiPicker.togglePicker(this.emojiPickerHandler) + }); await this.updateComplete; this.initChatEditor(); @@ -366,6 +372,7 @@ class ChatTextEditor extends LitElement { return; }; this.chatMessageSize = 0; + this.chatEditor.updateMirror(); this._sendMessage(); } @@ -693,11 +700,10 @@ class ChatTextEditor extends LitElement { }, 0); res(); }) + // Handle Enter if (e.keyCode === 13 && !e.shiftKey) { - // Update Mirror - editor.updateMirror(); if (editor.state() === 'false') return false; if (editorConfig.iframeId === 'newChat') { diff --git a/qortal-ui-plugins/plugins/core/components/WrapperModal.js b/qortal-ui-plugins/plugins/core/components/WrapperModal.js index 23b6c040..96b22142 100644 --- a/qortal-ui-plugins/plugins/core/components/WrapperModal.js +++ b/qortal-ui-plugins/plugins/core/components/WrapperModal.js @@ -5,7 +5,8 @@ import { wrapperModalStyles } from './WrapperModal-css.js' export class WrapperModal extends LitElement { static get properties() { return { - removeImage: { type: Function }, + onClickFunc: { attribute: false }, + closePrivateMessage: { attribute: false }, } } @@ -15,7 +16,7 @@ export class WrapperModal extends LitElement { return html`
{ - this.removeImage() + this.onClickFunc(); }}>