From ec34b0137a8f29c21c783c933d3529822d498a3b Mon Sep 17 00:00:00 2001 From: Phillip Date: Thu, 17 Aug 2023 22:14:58 -0500 Subject: [PATCH] publish with only fee, removed gif --- core/src/components/app-view.js | 3 +- plugins/plugins/core/components/ChatPage.js | 1027 +++++++++-------- .../plugins/core/components/ChatTextEditor.js | 15 - .../core/messaging/q-chat/q-chat.src.js | 5 +- .../plugins/core/qdn/browser/browser.src.js | 13 +- .../plugins/core/qdn/publish/publish.src.js | 29 +- plugins/plugins/utils/publish-modal.css | 147 +++ plugins/plugins/utils/publish-modal.js | 263 +++++ 8 files changed, 977 insertions(+), 525 deletions(-) create mode 100644 plugins/plugins/utils/publish-modal.css create mode 100644 plugins/plugins/utils/publish-modal.js diff --git a/core/src/components/app-view.js b/core/src/components/app-view.js index 3c433c11..08b9c019 100644 --- a/core/src/components/app-view.js +++ b/core/src/components/app-view.js @@ -3047,4 +3047,5 @@ class AppView extends connect(store)(LitElement) { } } -window.customElements.define('app-view', AppView) \ No newline at end of file +window.customElements.define('app-view', AppView) + diff --git a/plugins/plugins/core/components/ChatPage.js b/plugins/plugins/core/components/ChatPage.js index c11f2aa8..d354e719 100644 --- a/plugins/plugins/core/components/ChatPage.js +++ b/plugins/plugins/core/components/ChatPage.js @@ -1443,14 +1443,14 @@ class ChatPage extends LitElement { ` : ''}
- this.setGifsLoading(val)} .sendMessage=${(val) => this._sendMessage(val)} .setOpenGifModal=${(val) => this.setOpenGifModal(val)}> - + -->
@@ -3135,511 +3135,552 @@ class ChatPage extends LitElement { } async _sendMessage(outSideMsg, msg) { - if (this.isReceipient) { - let hasPublicKey = true - if (!this._publicKey.hasPubKey) { - hasPublicKey = false - try { - const res = await parentEpml.request('apiCall', { - type: 'api', - url: `/addresses/publickey/${this.selectedAddress.address}` - }) - if (res.error === 102) { - this._publicKey.key = '' - this._publicKey.hasPubKey = false - } else if (res !== false) { - this._publicKey.key = res - this._publicKey.hasPubKey = true - hasPublicKey = true - } else { - this._publicKey.key = '' - this._publicKey.hasPubKey = false + console.log({outSideMsg, msg}) + try { + if (this.isReceipient) { + let hasPublicKey = true + if (!this._publicKey.hasPubKey) { + hasPublicKey = false + try { + const res = await parentEpml.request('apiCall', { + type: 'api', + url: `/addresses/publickey/${this.selectedAddress.address}` + }) + if (res.error === 102) { + this._publicKey.key = '' + this._publicKey.hasPubKey = false + } else if (res !== false) { + this._publicKey.key = res + this._publicKey.hasPubKey = true + hasPublicKey = true + } else { + this._publicKey.key = '' + this._publicKey.hasPubKey = false + } + } catch (error) { } - } catch (error) { + + if (!hasPublicKey || !this._publicKey.hasPubKey) { + let err4string = get("chatpage.cchange39") + parentEpml.request('showSnackBar', `${err4string}`) + return + } + } - - if (!hasPublicKey || !this._publicKey.hasPubKey) { - let err4string = get("chatpage.cchange39") - parentEpml.request('showSnackBar', `${err4string}`) + } + // have params to determine if it's a reply or not + // have variable to determine if it's a response, holds signature in constructor + // need original message signature + // need whole original message object, transform the data and put it in local storage + // create new var called repliedToData and use that to modify the UI + // find specific object property in local + let typeMessage = 'regular' + this.isLoading = true + const trimmedMessage = msg + + const getName = async (recipient) => { + try { + const getNames = await parentEpml.request("apiCall", { + type: "api", + url: `/names/address/${recipient}` + }) + + if (Array.isArray(getNames) && getNames.length > 0) { + return getNames[0].name + } else { + return '' + } + + } catch (error) { + return "" + } + } + + if (outSideMsg && outSideMsg.type === 'delete') { + this.isDeletingImage = true + const userName = outSideMsg.name + const identifier = outSideMsg.identifier + let compressedFile = '' + var str = "iVBORw0KGgoAAAANSUhEUgAAAsAAAAGMAQMAAADuk4YmAAAAA1BMVEX///+nxBvIAAAAAXRSTlMAQObYZgAAADlJREFUeF7twDEBAAAAwiD7p7bGDlgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAGJrAABgPqdWQAAAABJRU5ErkJggg==" + + if (this.webWorkerFile) { + this.webWorkerFile.terminate() + this.webWorkerFile = null + } + + this.webWorkerFile = new WebWorkerFile() + + const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => { + const byteCharacters = atob(b64Data) + const byteArrays = [] + + for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { + const slice = byteCharacters.slice(offset, offset + sliceSize) + + const byteNumbers = new Array(slice.length) + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i) + } + + const byteArray = new Uint8Array(byteNumbers) + byteArrays.push(byteArray) + } + + const blob = new Blob(byteArrays, { type: contentType }) + return blob + } + const blob = b64toBlob(str, 'image/png') + await new Promise(resolve => { + new Compressor(blob, { + quality: 0.6, + maxWidth: 500, + success(result) { + const file = new File([result], "name", { + type: 'image/png' + }) + + compressedFile = file + resolve() + }, + error(err) { + }, + }) + }) + const arbitraryFeeData = await modalHelper.getArbitraryFee() + const res = await modalHelper.showModalAndWaitPublish( + { + feeAmount: arbitraryFeeData.feeToShow + } + ); + if (res.action !== 'accept') throw new Error('User declined publish') + try { + await publishData({ + registeredName: userName, + file: compressedFile, + service: 'QCHAT_IMAGE', + identifier: identifier, + parentEpml, + metaData: undefined, + uploadType: 'file', + selectedAddress: this.selectedAddress, + worker: this.webWorkerFile + }) + this.isDeletingImage = false + } catch (error) { + this.isLoading = false return } - - } - } - // have params to determine if it's a reply or not - // have variable to determine if it's a response, holds signature in constructor - // need original message signature - // need whole original message object, transform the data and put it in local storage - // create new var called repliedToData and use that to modify the UI - // find specific object property in local - let typeMessage = 'regular' - this.isLoading = true - const trimmedMessage = msg - - const getName = async (recipient) => { - try { - const getNames = await parentEpml.request("apiCall", { - type: "api", - url: `/names/address/${recipient}` - }) - - if (Array.isArray(getNames) && getNames.length > 0) { - return getNames[0].name - } else { - return '' + typeMessage = 'edit' + let chatReference = outSideMsg.editedMessageObj.signature + + if (outSideMsg.editedMessageObj.chatReference) { + chatReference = outSideMsg.editedMessageObj.chatReference } - - } catch (error) { - return "" - } - } - - if (outSideMsg && outSideMsg.type === 'delete') { - this.isDeletingImage = true - const userName = outSideMsg.name - const identifier = outSideMsg.identifier - let compressedFile = '' - var str = "iVBORw0KGgoAAAANSUhEUgAAAsAAAAGMAQMAAADuk4YmAAAAA1BMVEX///+nxBvIAAAAAXRSTlMAQObYZgAAADlJREFUeF7twDEBAAAAwiD7p7bGDlgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAGJrAABgPqdWQAAAABJRU5ErkJggg==" - - if (this.webWorkerFile) { - this.webWorkerFile.terminate() - this.webWorkerFile = null - } - - this.webWorkerFile = new WebWorkerFile() - - const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => { - const byteCharacters = atob(b64Data) - const byteArrays = [] - - for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { - const slice = byteCharacters.slice(offset, offset + sliceSize) - - const byteNumbers = new Array(slice.length) - for (let i = 0; i < slice.length; i++) { - byteNumbers[i] = slice.charCodeAt(i) + + let message = "" + try { + const parsedMessageObj = JSON.parse(outSideMsg.editedMessageObj.decodedMessage) + message = parsedMessageObj + } catch (error) { + message = outSideMsg.editedMessageObj.decodedMessage + } + const messageObject = { + ...message, + isImageDeleted: true + } + const stringifyMessageObject = JSON.stringify(messageObject) + this.sendMessage(stringifyMessageObject, typeMessage, chatReference) + } else if (outSideMsg && outSideMsg.type === 'deleteAttachment') { + this.isDeletingAttachment = true + let compressedFile = '' + var str = "iVBORw0KGgoAAAANSUhEUgAAAsAAAAGMAQMAAADuk4YmAAAAA1BMVEX///+nxBvIAAAAAXRSTlMAQObYZgAAADlJREFUeF7twDEBAAAAwiD7p7bGDlgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAGJrAABgPqdWQAAAABJRU5ErkJggg==" + const userName = outSideMsg.name + const identifier = outSideMsg.identifier + + if (this.webWorkerFile) { + this.webWorkerFile.terminate() + this.webWorkerFile = null + } + + this.webWorkerFile = new WebWorkerFile() + + const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => { + const byteCharacters = atob(b64Data) + const byteArrays = [] + + for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { + const slice = byteCharacters.slice(offset, offset + sliceSize) + + const byteNumbers = new Array(slice.length) + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i) + } + + const byteArray = new Uint8Array(byteNumbers) + byteArrays.push(byteArray) } - - const byteArray = new Uint8Array(byteNumbers) - byteArrays.push(byteArray) + + const blob = new Blob(byteArrays, { type: contentType }) + return blob } - - const blob = new Blob(byteArrays, { type: contentType }) - return blob - } - const blob = b64toBlob(str, 'image/png') - await new Promise(resolve => { - new Compressor(blob, { - quality: 0.6, - maxWidth: 500, - success(result) { - const file = new File([result], "name", { - type: 'image/png' - }) - - compressedFile = file - resolve() - }, - error(err) { - }, - }) - }) - try { - await publishData({ - registeredName: userName, - file: compressedFile, - service: 'QCHAT_IMAGE', - identifier: identifier, - parentEpml, - metaData: undefined, - uploadType: 'file', - selectedAddress: this.selectedAddress, - worker: this.webWorkerFile - }) - this.isDeletingImage = false - } catch (error) { - this.isLoading = false - return - } - typeMessage = 'edit' - let chatReference = outSideMsg.editedMessageObj.signature - - if (outSideMsg.editedMessageObj.chatReference) { - chatReference = outSideMsg.editedMessageObj.chatReference - } - - let message = "" - try { - const parsedMessageObj = JSON.parse(outSideMsg.editedMessageObj.decodedMessage) - message = parsedMessageObj - } catch (error) { - message = outSideMsg.editedMessageObj.decodedMessage - } - const messageObject = { - ...message, - isImageDeleted: true - } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage, chatReference) - } else if (outSideMsg && outSideMsg.type === 'deleteAttachment') { - this.isDeletingAttachment = true - let compressedFile = '' - var str = "iVBORw0KGgoAAAANSUhEUgAAAsAAAAGMAQMAAADuk4YmAAAAA1BMVEX///+nxBvIAAAAAXRSTlMAQObYZgAAADlJREFUeF7twDEBAAAAwiD7p7bGDlgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAGJrAABgPqdWQAAAABJRU5ErkJggg==" - const userName = outSideMsg.name - const identifier = outSideMsg.identifier - - if (this.webWorkerFile) { - this.webWorkerFile.terminate() - this.webWorkerFile = null - } - - this.webWorkerFile = new WebWorkerFile() - - const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => { - const byteCharacters = atob(b64Data) - const byteArrays = [] - - for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { - const slice = byteCharacters.slice(offset, offset + sliceSize) - - const byteNumbers = new Array(slice.length) - for (let i = 0; i < slice.length; i++) { - byteNumbers[i] = slice.charCodeAt(i) - } - - const byteArray = new Uint8Array(byteNumbers) - byteArrays.push(byteArray) - } - - const blob = new Blob(byteArrays, { type: contentType }) - return blob - } - - const blob = b64toBlob(str, 'image/png') - await new Promise(resolve => { - new Compressor(blob, { - quality: 0.6, - maxWidth: 500, - success(result) { - const file = new File([result], "name", { - type: 'image/png' - }) - - compressedFile = file - resolve() - }, - error(err) { - }, - }) - }) - - try { - await publishData({ - registeredName: userName, - file: compressedFile, - service: 'QCHAT_ATTACHMENT', - identifier: identifier, - parentEpml, - metaData: undefined, - uploadType: 'file', - selectedAddress: this.selectedAddress, - worker: this.webWorkerFile - }) - this.isDeletingAttachment = false - } catch (error) { - this.isLoading = false - return - } - typeMessage = 'edit' - let chatReference = outSideMsg.editedMessageObj.signature - - if (outSideMsg.editedMessageObj.chatReference) { - chatReference = outSideMsg.editedMessageObj.chatReference - } - - let message = "" - try { - const parsedMessageObj = JSON.parse(outSideMsg.editedMessageObj.decodedMessage) - message = parsedMessageObj - - } catch (error) { - message = outSideMsg.editedMessageObj.decodedMessage - } - const messageObject = { - ...message, - isAttachmentDeleted: true - } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage, chatReference) - } else if (outSideMsg && outSideMsg.type === 'image') { - this.isUploadingImage = true - const userName = await getName(this.selectedAddress.address) - if (!userName) { - parentEpml.request('showSnackBar', get("chatpage.cchange27")) - this.isLoading = false - this.isUploadingImage = false - this.imageFile = null - return - } - - if (this.webWorkerFile) { - this.webWorkerFile.terminate() - this.webWorkerFile = null - } - - this.webWorkerFile = new WebWorkerFile() - - const image = this.imageFile - const id = this.uid() - const identifier = `qchat_${id}` - let compressedFile = '' - await new Promise(resolve => { - new Compressor(image, { - quality: .6, - maxWidth: 1200, - success(result) { - const file = new File([result], "name", { - type: image.type - }) - compressedFile = file - resolve() - }, - error(err) { - }, - }) - }) - const fileSize = compressedFile.size - if (fileSize > 500000) { - parentEpml.request('showSnackBar', get("chatpage.cchange26")) - this.isLoading = false - this.isUploadingImage = false - return - } - try { - await publishData({ - registeredName: userName, - file: compressedFile, - service: 'QCHAT_IMAGE', - identifier: identifier, - parentEpml, - metaData: undefined, - uploadType: 'file', - selectedAddress: this.selectedAddress, - worker: this.webWorkerFile - }) - this.isUploadingImage = false - this.removeImage() - } catch (error) { - this.isLoading = false - this.isUploadingImage = false - return - } - - const messageObject = { - messageText: trimmedMessage, - images: [{ - service: "QCHAT_IMAGE", - name: userName, - identifier: identifier - }], - isImageDeleted: false, - repliedTo: '', - version: 3 - } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage) - } else if (outSideMsg && outSideMsg.type === 'gif') { - const userName = await getName(this.selectedAddress.address) - if (!userName) { - parentEpml.request('showSnackBar', get("chatpage.cchange27")) - this.isLoading = false - return - } - - const messageObject = { - messageText: '', - gifs: [{ - service: outSideMsg.service, - name: outSideMsg.name, - identifier: outSideMsg.identifier, - filePath: outSideMsg.filePath - }], - repliedTo: '', - version: 3 - } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage) - } else if (outSideMsg && outSideMsg.type === 'attachment') { - this.isUploadingAttachment = true - const userName = await getName(this.selectedAddress.address) - if (!userName) { - parentEpml.request('showSnackBar', get("chatpage.cchange27")) - this.isLoading = false - return - } - - if (this.webWorkerFile) { - this.webWorkerFile.terminate() - this.webWorkerFile = null - } - - this.webWorkerFile = new WebWorkerFile() - - const attachment = this.attachment - const id = this.uid() - const identifier = `qchat_${id}` - const fileSize = attachment.size - if (fileSize > 1000000) { - parentEpml.request('showSnackBar', get("chatpage.cchange77")) - this.isLoading = false - this.isUploadingAttachment = false - return - } - try { - await publishData({ - registeredName: userName, - file: attachment, - service: 'QCHAT_ATTACHMENT', - identifier: identifier, - parentEpml, - metaData: undefined, - uploadType: 'file', - selectedAddress: this.selectedAddress, - worker: this.webWorkerFile - }) - this.isUploadingAttachment = false - this.removeAttachment() - } catch (error) { - this.isLoading = false - this.isUploadingAttachment = false - return - } - const messageObject = { - messageText: trimmedMessage, - attachments: [{ - service: 'QCHAT_ATTACHMENT', - name: userName, - identifier: identifier, - attachmentName: attachment.name, - attachmentSize: attachment.size - }], - isAttachmentDeleted: false, - repliedTo: '', - version: 3 - } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage) - } else if (outSideMsg && outSideMsg.type === 'reaction') { - const userName = await getName(this.selectedAddress.address) - typeMessage = 'edit' - let chatReference = outSideMsg.editedMessageObj.signature - - if (outSideMsg.editedMessageObj.chatReference) { - chatReference = outSideMsg.editedMessageObj.chatReference - } - - let message = "" - - try { - const parsedMessageObj = JSON.parse(outSideMsg.editedMessageObj.decodedMessage) - message = parsedMessageObj - } catch (error) { - message = outSideMsg.editedMessageObj.decodedMessage - } - - let reactions = message.reactions || [] - const findEmojiIndex = reactions.findIndex((reaction) => reaction.type === outSideMsg.reaction) - if (findEmojiIndex !== -1) { - let users = reactions[findEmojiIndex].users || [] - const findUserIndex = users.findIndex((user) => user.address === this.selectedAddress.address) - if (findUserIndex !== -1) { - users.splice(findUserIndex, 1) - } else { - users.push({ - address: this.selectedAddress.address, - name: userName + + const blob = b64toBlob(str, 'image/png') + await new Promise(resolve => { + new Compressor(blob, { + quality: 0.6, + maxWidth: 500, + success(result) { + const file = new File([result], "name", { + type: 'image/png' + }) + + compressedFile = file + resolve() + }, + error(err) { + }, }) + }) + const arbitraryFeeData = await modalHelper.getArbitraryFee() + const res = await modalHelper.showModalAndWaitPublish( + { + feeAmount: arbitraryFeeData.feeToShow + } + ); + if (res.action !== 'accept') throw new Error('User declined publish') + try { + await publishData({ + registeredName: userName, + file: compressedFile, + service: 'QCHAT_ATTACHMENT', + identifier: identifier, + parentEpml, + metaData: undefined, + uploadType: 'file', + selectedAddress: this.selectedAddress, + worker: this.webWorkerFile + }) + this.isDeletingAttachment = false + } catch (error) { + this.isLoading = false + return } - reactions[findEmojiIndex] = { - ...reactions[findEmojiIndex], - qty: users.length, - users + typeMessage = 'edit' + let chatReference = outSideMsg.editedMessageObj.signature + + if (outSideMsg.editedMessageObj.chatReference) { + chatReference = outSideMsg.editedMessageObj.chatReference } - if (users.length === 0) { - reactions.splice(findEmojiIndex, 1) + + let message = "" + try { + const parsedMessageObj = JSON.parse(outSideMsg.editedMessageObj.decodedMessage) + message = parsedMessageObj + + } catch (error) { + message = outSideMsg.editedMessageObj.decodedMessage } - } else { - reactions = [...reactions, { - type: outSideMsg.reaction, - qty: 1, - users: [{ - address: this.selectedAddress.address, - name: userName - }] - }] - } - const messageObject = { - ...message, - reactions - } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage, chatReference) - } else if (/^\s*$/.test(trimmedMessage)) { - this.isLoading = false - } else if (this.repliedToMessageObj) { - let chatReference = this.repliedToMessageObj.signature - if (this.repliedToMessageObj.chatReference) { - chatReference = this.repliedToMessageObj.chatReference - } - typeMessage = 'reply' - const messageObject = { - messageText: trimmedMessage, - images: [''], - repliedTo: chatReference, - version: 3 - } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage) - } else if (this.editedMessageObj) { - typeMessage = 'edit' - let chatReference = this.editedMessageObj.signature - - if (this.editedMessageObj.chatReference) { - chatReference = this.editedMessageObj.chatReference - } - - let message = "" - try { - const parsedMessageObj = JSON.parse(this.editedMessageObj.decodedMessage) - message = parsedMessageObj - - } catch (error) { - message = this.editedMessageObj.decodedMessage - } - const messageObject = { - ...message, - messageText: trimmedMessage, - isEdited: true - } - const stringifyMessageObject = JSON.stringify(messageObject) - this.sendMessage(stringifyMessageObject, typeMessage, chatReference) - } else { - const messageObject = { - messageText: trimmedMessage, - images: [''], - repliedTo: '', - version: 3 - } - const stringifyMessageObject = JSON.stringify(messageObject) - - if (this.balance < 4) { - this.myTrimmedMeassage = '' - this.myTrimmedMeassage = stringifyMessageObject - this.shadowRoot.getElementById('confirmDialog').open() - } else { + const messageObject = { + ...message, + isAttachmentDeleted: true + } + const stringifyMessageObject = JSON.stringify(messageObject) + this.sendMessage(stringifyMessageObject, typeMessage, chatReference) + } else if (outSideMsg && outSideMsg.type === 'image') { + this.isUploadingImage = true + const userName = await getName(this.selectedAddress.address) + if (!userName) { + parentEpml.request('showSnackBar', get("chatpage.cchange27")) + this.isLoading = false + this.isUploadingImage = false + this.imageFile = null + return + } + const arbitraryFeeData = await modalHelper.getArbitraryFee() + console.log('updated') + const res = await modalHelper.showModalAndWaitPublish( + { + feeAmount: arbitraryFeeData.feeToShow + } + ); + console.log({res}) + if (res.action !== 'accept') throw new Error('User declined publish') + + if (this.webWorkerFile) { + this.webWorkerFile.terminate() + this.webWorkerFile = null + } + + this.webWorkerFile = new WebWorkerFile() + + const image = this.imageFile + const id = this.uid() + const identifier = `qchat_${id}` + let compressedFile = '' + await new Promise(resolve => { + new Compressor(image, { + quality: .6, + maxWidth: 1200, + success(result) { + const file = new File([result], "name", { + type: image.type + }) + compressedFile = file + resolve() + }, + error(err) { + }, + }) + }) + const fileSize = compressedFile.size + if (fileSize > 500000) { + parentEpml.request('showSnackBar', get("chatpage.cchange26")) + this.isLoading = false + this.isUploadingImage = false + return + } + + try { + + await publishData({ + registeredName: userName, + file: compressedFile, + service: 'QCHAT_IMAGE', + identifier: identifier, + parentEpml, + metaData: undefined, + uploadType: 'file', + selectedAddress: this.selectedAddress, + worker: this.webWorkerFile, + withFee: true, + feeAmount: arbitraryFeeData.fee + }) + this.isUploadingImage = false + this.removeImage() + } catch (error) { + this.isLoading = false + this.isUploadingImage = false + return + } + + const messageObject = { + messageText: trimmedMessage, + images: [{ + service: "QCHAT_IMAGE", + name: userName, + identifier: identifier + }], + isImageDeleted: false, + repliedTo: '', + version: 3 + } + const stringifyMessageObject = JSON.stringify(messageObject) this.sendMessage(stringifyMessageObject, typeMessage) + } else if (outSideMsg && outSideMsg.type === 'gif') { + const userName = await getName(this.selectedAddress.address) + if (!userName) { + parentEpml.request('showSnackBar', get("chatpage.cchange27")) + this.isLoading = false + return + } + + const messageObject = { + messageText: '', + gifs: [{ + service: outSideMsg.service, + name: outSideMsg.name, + identifier: outSideMsg.identifier, + filePath: outSideMsg.filePath + }], + repliedTo: '', + version: 3 + } + const stringifyMessageObject = JSON.stringify(messageObject) + this.sendMessage(stringifyMessageObject, typeMessage) + } else if (outSideMsg && outSideMsg.type === 'attachment') { + this.isUploadingAttachment = true + const userName = await getName(this.selectedAddress.address) + if (!userName) { + parentEpml.request('showSnackBar', get("chatpage.cchange27")) + this.isLoading = false + return + } + + if (this.webWorkerFile) { + this.webWorkerFile.terminate() + this.webWorkerFile = null + } + + this.webWorkerFile = new WebWorkerFile() + + const attachment = this.attachment + const id = this.uid() + const identifier = `qchat_${id}` + const fileSize = attachment.size + if (fileSize > 1000000) { + parentEpml.request('showSnackBar', get("chatpage.cchange77")) + this.isLoading = false + this.isUploadingAttachment = false + return + } + const arbitraryFeeData = await modalHelper.getArbitraryFee() + const res = await modalHelper.showModalAndWaitPublish( + { + feeAmount: arbitraryFeeData.feeToShow + } + ); + if (res.action !== 'accept') throw new Error('User declined publish') + try { + await publishData({ + registeredName: userName, + file: attachment, + service: 'QCHAT_ATTACHMENT', + identifier: identifier, + parentEpml, + metaData: undefined, + uploadType: 'file', + selectedAddress: this.selectedAddress, + worker: this.webWorkerFile + }) + this.isUploadingAttachment = false + this.removeAttachment() + } catch (error) { + this.isLoading = false + this.isUploadingAttachment = false + return + } + const messageObject = { + messageText: trimmedMessage, + attachments: [{ + service: 'QCHAT_ATTACHMENT', + name: userName, + identifier: identifier, + attachmentName: attachment.name, + attachmentSize: attachment.size + }], + isAttachmentDeleted: false, + repliedTo: '', + version: 3 + } + const stringifyMessageObject = JSON.stringify(messageObject) + this.sendMessage(stringifyMessageObject, typeMessage) + } else if (outSideMsg && outSideMsg.type === 'reaction') { + const userName = await getName(this.selectedAddress.address) + typeMessage = 'edit' + let chatReference = outSideMsg.editedMessageObj.signature + + if (outSideMsg.editedMessageObj.chatReference) { + chatReference = outSideMsg.editedMessageObj.chatReference + } + + let message = "" + + try { + const parsedMessageObj = JSON.parse(outSideMsg.editedMessageObj.decodedMessage) + message = parsedMessageObj + } catch (error) { + message = outSideMsg.editedMessageObj.decodedMessage + } + + let reactions = message.reactions || [] + const findEmojiIndex = reactions.findIndex((reaction) => reaction.type === outSideMsg.reaction) + if (findEmojiIndex !== -1) { + let users = reactions[findEmojiIndex].users || [] + const findUserIndex = users.findIndex((user) => user.address === this.selectedAddress.address) + if (findUserIndex !== -1) { + users.splice(findUserIndex, 1) + } else { + users.push({ + address: this.selectedAddress.address, + name: userName + }) + } + reactions[findEmojiIndex] = { + ...reactions[findEmojiIndex], + qty: users.length, + users + } + if (users.length === 0) { + reactions.splice(findEmojiIndex, 1) + } + } else { + reactions = [...reactions, { + type: outSideMsg.reaction, + qty: 1, + users: [{ + address: this.selectedAddress.address, + name: userName + }] + }] + } + const messageObject = { + ...message, + reactions + } + const stringifyMessageObject = JSON.stringify(messageObject) + this.sendMessage(stringifyMessageObject, typeMessage, chatReference) + } else if (/^\s*$/.test(trimmedMessage)) { + this.isLoading = false + } else if (this.repliedToMessageObj) { + let chatReference = this.repliedToMessageObj.signature + if (this.repliedToMessageObj.chatReference) { + chatReference = this.repliedToMessageObj.chatReference + } + typeMessage = 'reply' + const messageObject = { + messageText: trimmedMessage, + images: [''], + repliedTo: chatReference, + version: 3 + } + const stringifyMessageObject = JSON.stringify(messageObject) + this.sendMessage(stringifyMessageObject, typeMessage) + } else if (this.editedMessageObj) { + typeMessage = 'edit' + let chatReference = this.editedMessageObj.signature + + if (this.editedMessageObj.chatReference) { + chatReference = this.editedMessageObj.chatReference + } + + let message = "" + try { + const parsedMessageObj = JSON.parse(this.editedMessageObj.decodedMessage) + message = parsedMessageObj + + } catch (error) { + message = this.editedMessageObj.decodedMessage + } + const messageObject = { + ...message, + messageText: trimmedMessage, + isEdited: true + } + const stringifyMessageObject = JSON.stringify(messageObject) + this.sendMessage(stringifyMessageObject, typeMessage, chatReference) + } else { + const messageObject = { + messageText: trimmedMessage, + images: [''], + repliedTo: '', + version: 3 + } + const stringifyMessageObject = JSON.stringify(messageObject) + + if (this.balance < 4) { + this.myTrimmedMeassage = '' + this.myTrimmedMeassage = stringifyMessageObject + this.shadowRoot.getElementById('confirmDialog').open() + } else { + this.sendMessage(stringifyMessageObject, typeMessage) + } } + } catch (error) { + this.isLoading = false + this.isUploadingImage = false + return } + } async sendMessage(messageText, typeMessage, chatReference, isForward) { diff --git a/plugins/plugins/core/components/ChatTextEditor.js b/plugins/plugins/core/components/ChatTextEditor.js index 123df641..b13dc72f 100644 --- a/plugins/plugins/core/components/ChatTextEditor.js +++ b/plugins/plugins/core/components/ChatTextEditor.js @@ -506,21 +506,6 @@ mwc-checkbox::shadow .mdc-checkbox::after, mwc-checkbox::shadow .mdc-checkbox::b - ${this.setOpenGifModal ? - html` - - ` - : ''} ${this.editedMessageObj ? ( html`
diff --git a/plugins/plugins/core/messaging/q-chat/q-chat.src.js b/plugins/plugins/core/messaging/q-chat/q-chat.src.js index 1f60e079..ca9540a8 100644 --- a/plugins/plugins/core/messaging/q-chat/q-chat.src.js +++ b/plugins/plugins/core/messaging/q-chat/q-chat.src.js @@ -26,11 +26,12 @@ import '@material/mwc-icon' import '@material/mwc-snackbar' import '@polymer/paper-spinner/paper-spinner-lite.js' import '@vaadin/grid' +import { ModalHelper } from '../../../utils/publish-modal.js' passiveSupport({ events: ['touchstart'] }) const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) - +export const modalHelper = new ModalHelper(); class Chat extends LitElement { static get properties() { return { @@ -910,4 +911,4 @@ class Chat extends LitElement { } } -window.customElements.define('q-chat', Chat) +window.customElements.define('q-chat', Chat) \ No newline at end of file diff --git a/plugins/plugins/core/qdn/browser/browser.src.js b/plugins/plugins/core/qdn/browser/browser.src.js index 3dfad150..02b8aa9b 100644 --- a/plugins/plugins/core/qdn/browser/browser.src.js +++ b/plugins/plugins/core/qdn/browser/browser.src.js @@ -3027,10 +3027,7 @@ async function showModalAndWait(type, data) { `).join('')}
- - +
` : ''} @@ -3043,10 +3040,7 @@ async function showModalAndWait(type, data) {
- - +
` : ''} @@ -3118,7 +3112,8 @@ async function showModalAndWait(type, data) { const userData = {}; if (type === actions.PUBLISH_QDN_RESOURCE || type === actions.PUBLISH_MULTIPLE_QDN_RESOURCES) { const isWithFeeCheckbox = modal.querySelector('#isWithFee'); - userData.isWithFee = isWithFeeCheckbox.checked; + // userData.isWithFee = isWithFeeCheckbox.checked; + userData.isWithFee = true } if (modal.parentNode === document.body) { document.body.removeChild(modal); diff --git a/plugins/plugins/core/qdn/publish/publish.src.js b/plugins/plugins/core/qdn/publish/publish.src.js index 77b99317..a4662628 100644 --- a/plugins/plugins/core/qdn/publish/publish.src.js +++ b/plugins/plugins/core/qdn/publish/publish.src.js @@ -14,8 +14,10 @@ import '@material/mwc-select' import '@material/mwc-dialog' import '@material/mwc-list/mwc-list-item.js' import '@polymer/paper-progress/paper-progress.js' +import { ModalHelper } from '../../../utils/publish-modal' const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) +const modalHelper = new ModalHelper(); class PublishData extends LitElement { static get properties() { @@ -299,8 +301,10 @@ class PublishData extends LitElement {

${this.successMessage}

${this.loading ? html` ` : ''}
- this.doPublish(e, true, false)}> ${translate("appspage.schange40")} - this.shadowRoot.querySelector('#publishWithFeeDialog').show()}> ${translate("publishpage.pchange11")} + this.shadowRoot.querySelector('#publishWithFeeDialog').close()}> ${translate("appspage.schange40")} + { + this.doPublish(e, false, true) + }}> ${translate("publishpage.pchange11")}
@@ -310,7 +314,7 @@ class PublishData extends LitElement { ${translate("general.no")} - + ${translate("general.yes")} @@ -418,7 +422,7 @@ class PublishData extends LitElement { this.shadowRoot.querySelector('#publishWithFeeDialog').close() } - doPublish(e, preview, fee) { + async doPublish(e, preview, fee) { let registeredName = this.shadowRoot.getElementById('registeredName').value let service = this.shadowRoot.getElementById('service').value let identifier = this.shadowRoot.getElementById('identifier').value @@ -464,7 +468,22 @@ class PublishData extends LitElement { parentEpml.request('showSnackBar', `${err5string}`) } else { - this.publishData(registeredName, path, file, service, identifier, preview, fee) + try { + if(!preview){ + const arbitraryFeeData = await modalHelper.getArbitraryFee() + const res = await modalHelper.showModalAndWaitPublish( + { + feeAmount: arbitraryFeeData.feeToShow + } + ); + if (res.action !== 'accept') throw new Error('User declined publish') + } + + this.publishData(registeredName, path, file, service, identifier, preview, fee) + } catch (error) { + this.shadowRoot.querySelector('#publishWithFeeDialog').close() + } + } } diff --git a/plugins/plugins/utils/publish-modal.css b/plugins/plugins/utils/publish-modal.css new file mode 100644 index 00000000..f5ded060 --- /dev/null +++ b/plugins/plugins/utils/publish-modal.css @@ -0,0 +1,147 @@ +.backdrop { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgb(186 186 186 / 26%); + overflow: hidden; + animation: backdrop_blur cubic-bezier(0.22, 1, 0.36, 1) 1s forwards; + z-index: 1000000; +} + +@keyframes backdrop_blur { + 0% { + backdrop-filter: blur(0px); + background: transparent; + } + 100% { + backdrop-filter: blur(5px); + background: rgb(186 186 186 / 26%); + } +} + +@keyframes modal_transition { + 0% { + visibility: hidden; + opacity: 0; +} + 100% { + visibility: visible; + opacity: 1; + } +} + +.modal { + position: relative; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + animation: 1s cubic-bezier(0.22, 1, 0.36, 1) 0s 1 normal forwards running modal_transition; + z-index: 1000001; +} + +@keyframes modal_transition { + 0% { + visibility: hidden; + opacity: 0; + } + 100% { + visibility: visible; + opacity: 1; + } +} + +.modal-content { + background-color: var(--white); + border-radius: 10px; + padding: 20px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + max-width: 80%; + min-width: 300px; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.modal-body { + padding: 25px; +} + +.modal-subcontainer { + color: var(--black); + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 15px; +} + +.modal-subcontainer-error { + color: var(--black); + display: flex; + flex-direction: column; + align-items: center; + gap: 15px; +} + +.modal-paragraph-error { + font-family: Roboto, sans-serif; + font-size: 20px; + letter-spacing: 0.3px; + font-weight: 700; + color: var(--black); + margin: 0; +} + +.modal-paragraph { + font-family: Roboto, sans-serif; + font-size: 18px; + letter-spacing: 0.3px; + font-weight: 300; + color: var(--black); + margin: 0; + word-wrap: break-word; + overflow-wrap: break-word; +} + +.capitalize-first { + text-transform: capitalize; +} + +.checkbox-row { + display: flex; + align-items: center; + font-family: Montserrat, sans-serif; + font-weight: 600; + color: var(--black); +} + +.modal-buttons { + display: flex; + justify-content: space-between; + margin-top: 20px; +} + +.modal-buttons button { + background-color: #4caf50; + border: none; + color: #fff; + padding: 10px 20px; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.2s; +} + +.modal-buttons button:hover { + background-color: #3e8e41; +} + +#cancel-button { + background-color: #f44336; +} + +#cancel-button:hover { + background-color: #d32f2f; +} \ No newline at end of file diff --git a/plugins/plugins/utils/publish-modal.js b/plugins/plugins/utils/publish-modal.js new file mode 100644 index 00000000..3358083c --- /dev/null +++ b/plugins/plugins/utils/publish-modal.js @@ -0,0 +1,263 @@ +import { get } from 'lit-translate'; + +export class ModalHelper { + constructor() { + this.initializeStyles(); + } + + async getArbitraryFee() { + const timestamp = Date.now(); + const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; + const nodeUrl = `${myNode.protocol}://${myNode.domain}:${myNode.port}`; + const url = `${nodeUrl}/transactions/unitfee?txType=ARBITRARY×tamp=${timestamp}`; + const response = await fetch(url); + + if (!response.ok) { + throw new Error('Error when fetching arbitrary fee'); + } + + const data = await response.json(); + const arbitraryFee = (Number(data) / 1e8).toFixed(8); + return { + timestamp, + fee: Number(data), + feeToShow: arbitraryFee + }; + } + + async showModalAndWaitPublish(data) { + console.log({ data }); + + return new Promise((resolve) => { + const modal = this.createModal(data); + document.body.appendChild(modal); + this.addModalEventListeners(modal, resolve); + }); + } + + createModal(data) { + const modal = document.createElement('div'); + modal.id = "backdrop"; + modal.classList.add("backdrop"); + modal.innerHTML = ` + + `; + return modal; + } + + addModalEventListeners(modal, resolve) { + // Event listener for the 'OK' button + const okButton = modal.querySelector('#ok-button'); + okButton.addEventListener('click', () => { + const userData = { isWithFee: true }; + if (modal.parentNode === document.body) { + document.body.removeChild(modal); + } + resolve({ action: 'accept', userData }); + }); + + // Prevent modal content from closing the modal + const modalContent = modal.querySelector('.modal-content'); + modalContent.addEventListener('click', e => { + e.stopPropagation(); + }); + + // Event listeners for backdrop and 'Cancel' button + const backdropClick = document.getElementById('backdrop'); + backdropClick.addEventListener('click', () => { + if (modal.parentNode === document.body) { + document.body.removeChild(modal); + } + resolve({ action: 'reject' }); + }); + + const cancelButton = modal.querySelector('#cancel-button'); + cancelButton.addEventListener('click', () => { + if (modal.parentNode === document.body) { + document.body.removeChild(modal); + } + resolve({ action: 'reject' }); + }); + } + + initializeStyles() { + const styles = ` + * { + --mdc-theme-primary: rgb(3, 169, 244); + --mdc-theme-secondary: var(--mdc-theme-primary); + --paper-input-container-focus-color: var(--mdc-theme-primary); + --mdc-checkbox-unchecked-color: var(--black); + --mdc-theme-on-surface: var(--black); + --mdc-checkbox-disabled-color: var(--black); + --mdc-checkbox-ink-color: var(--black); + } + + .backdrop { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgb(186 186 186 / 26%); + overflow: hidden; + animation: backdrop_blur cubic-bezier(0.22, 1, 0.36, 1) 0.1s forwards; + z-index: 1000000; + } + + @keyframes backdrop_blur { + 0% { + backdrop-filter: blur(0px); + background: transparent; + } + 100% { + backdrop-filter: blur(5px); + background: rgb(186 186 186 / 26%); + } + } + + @keyframes modal_transition { + 0% { + visibility: hidden; + opacity: 0; + } + 100% { + visibility: visible; + opacity: 1; + } + } + + .modal { + position: relative; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + animation: 0.1s cubic-bezier(0.22, 1, 0.36, 1) 0s 1 normal forwards running modal_transition; + z-index: 1000001; + } + + @keyframes modal_transition { + 0% { + visibility: hidden; + opacity: 0; + } + 100% { + visibility: visible; + opacity: 1; + } + } + + .modal-content { + background-color: var(--white); + border-radius: 10px; + padding: 20px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + max-width: 80%; + min-width: 300px; + display: flex; + flex-direction: column; + justify-content: space-between; + } + + .modal-body { + padding: 25px; + } + + .modal-subcontainer { + color: var(--black); + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 15px; + } + + .modal-subcontainer-error { + color: var(--black); + display: flex; + flex-direction: column; + align-items: center; + gap: 15px; + } + + .modal-paragraph-error { + font-family: Roboto, sans-serif; + font-size: 20px; + letter-spacing: 0.3px; + font-weight: 700; + color: var(--black); + margin: 0; + } + + .modal-paragraph { + font-family: Roboto, sans-serif; + font-size: 18px; + letter-spacing: 0.3px; + font-weight: 300; + color: var(--black); + margin: 0; + word-wrap: break-word; + overflow-wrap: break-word; + } + + .capitalize-first { + text-transform: capitalize; + } + + .checkbox-row { + display: flex; + align-items: center; + font-family: Montserrat, sans-serif; + font-weight: 600; + color: var(--black); + } + + .modal-buttons { + display: flex; + justify-content: space-between; + margin-top: 20px; + } + + .modal-buttons button { + background-color: #4caf50; + border: none; + color: #fff; + padding: 10px 20px; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.2s; + } + + .modal-buttons button:hover { + background-color: #3e8e41; + } + + #cancel-button { + background-color: #f44336; + } + + #cancel-button:hover { + background-color: #d32f2f; + } + `; + + const styleSheet = new CSSStyleSheet(); + styleSheet.replaceSync(styles); + + document.adoptedStyleSheets = [styleSheet]; + } +}