From d822c65fc52a448c463bdaabb75be5dadcf6f443 Mon Sep 17 00:00:00 2001 From: AlphaX-Qortal Date: Sun, 9 Feb 2025 19:14:49 +0100 Subject: [PATCH 1/8] Various updates - Add display Qortal-Hub embed links - Add encrypted icon to messages - Add qortal request DECRYPT_AESGCM - Minor fixes --- crypto/api/deps/Base64Message.js | 38 +- .../plugins/core/components/ChatScroller.js | 29 +- .../core/components/qdn-action-constants.js | 120 ++++ .../core/components/qdn-action-types.js | 3 + .../components/webworkerDecodeMessages.js | 41 +- .../plugins/core/qdn/browser/browser.src.js | 581 ++++++++---------- plugins/plugins/utils/classes.js | 17 +- 7 files changed, 495 insertions(+), 334 deletions(-) diff --git a/crypto/api/deps/Base64Message.js b/crypto/api/deps/Base64Message.js index 27d5822f..f74c282f 100644 --- a/crypto/api/deps/Base64Message.js +++ b/crypto/api/deps/Base64Message.js @@ -4,6 +4,12 @@ import { uint8ArrayToObject, decryptSingle } from '../../../plugins/plugins/core/components/GroupEncryption.js' +import { + extensionToPointer, + encodedToChar, + embedToString, + parseQortalLink +} from '../../../plugins/plugins/core/components/qdn-action-constants.js' const Base64Message = {} @@ -29,13 +35,16 @@ Base64Message.decode = function (string, keys, ref) { } } else { let repliedToStr = '' + let addedFileStr = '' let messageStr = '' let hubString = '' + let messageRep = '' + let messageUseEmbed = {} const res = decryptSingle(string, keys, false) if (res === 'noKey' || res === 'decryptionFailed') { - return '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This message could not be decrypted"}]}]},"images":[""],"repliedTo":"","version":3}' + return '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This message could not be decrypted"}]}]}' + addedFileStr + ',"repliedTo":"","version":3,"isFromHub":true}' } const decryptToUnit8Array = base64ToUint8Array(res) @@ -54,7 +63,26 @@ Base64Message.decode = function (string, keys, ref) { } if (responseData.hasOwnProperty('message') && typeof responseData['message'] === 'string' && responseData['message'].length) { - const messageRep = responseData.message + if (responseData.message.includes('qortal://use-embed/')) { + const useEmbed1 = extensionToPointer(responseData.message) + const useEmbed2 = /(.*?)<\/newpointer>/g.exec(useEmbed1) + const useEmbed3 = encodedToChar(useEmbed2[1]) + + messageUseEmbed = parseQortalLink(useEmbed3) + addedFileStr = embedToString(messageUseEmbed) + + const useEmbed4 = responseData.message.split(useEmbed2[1]).join('') + + if (useEmbed4 === "

") { + messageRep = useEmbed4.split('

').join('

Qortal-Hub embed link

') + } else { + messageRep = useEmbed4 + } + } else { + messageRep = responseData.message + addedFileStr = ',"images":[""]' + } + const messageRep1 = messageRep.split('"').join('') const messageRep2 = messageRep1.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') const messageRep3 = messageRep2.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') @@ -77,11 +105,11 @@ Base64Message.decode = function (string, keys, ref) { } if (responseData.type === "edit") { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]},"images":[""],"repliedTo":"' + repliedToStr + '","version":3,"isEdited":true}' + hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isEdited":true,"isFromHub":true}' } else if (responseData.type === "reaction") { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]},"images":[""],"repliedTo":"' + repliedToStr + '","version":3,"isReaction":true}' + hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isReaction":true,"isFromHub":true}' } else { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]},"images":[""],"repliedTo":"' + repliedToStr + '","version":3}' + hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isFromHub":true}' } const preparedString = hubString.split('').join('\\"') diff --git a/plugins/plugins/core/components/ChatScroller.js b/plugins/plugins/core/components/ChatScroller.js index c5ebbeb0..42b803e8 100644 --- a/plugins/plugins/core/components/ChatScroller.js +++ b/plugins/plugins/core/components/ChatScroller.js @@ -177,7 +177,7 @@ function processText(input) { }) ) } catch (error) { - console.log({ error }) + console.error({ error }) } }) @@ -1081,7 +1081,7 @@ class MessageTemplate extends LitElement { let version = 0 let isForwarded = false let isEdited = false - + let isFromHub = false try { const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage) @@ -1101,6 +1101,7 @@ class MessageTemplate extends LitElement { version = parsedMessageObj.version isForwarded = parsedMessageObj.type === 'forward' isEdited = parsedMessageObj.isEdited && true + isFromHub = parsedMessageObj.isFromHub && true if (parsedMessageObj.images && Array.isArray(parsedMessageObj.images) && parsedMessageObj.images.length > 0) { image = parsedMessageObj.images[0] @@ -1132,6 +1133,8 @@ class MessageTemplate extends LitElement { let hideit = hidemsg.includes(this.messageObj.sender) let forwarded = '' let edited = '' + let fromHubOk = '' + let fromHubNo = '' levelFounder = html`` @@ -1247,6 +1250,18 @@ class MessageTemplate extends LitElement { ` + fromHubOk = html` +

+ key   +
+ ` + + fromHubNo = html` +
+ key_off   +
+ ` + if (repliedToData) { try { repliedToData.decodedMessage = JSON.parse(repliedToData.decodedMessage) @@ -1536,9 +1551,10 @@ class MessageTemplate extends LitElement {

${attachment && attachment.attachmentName}

-

+ ${attachment.attachmentSize > 0 ? + `

${roundToNearestDecimal(attachment.attachmentSize)} mb -

+

` : ''} await this.downloadAttachment(attachment)} @@ -1662,18 +1678,21 @@ class MessageTemplate extends LitElement { ${this.isInProgress ? html`

${translate('chatpage.cchange91')}

` : this.isAgo ? html` + ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`}
` : this.isIso ? html` + ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`}
${new Date(this.messageObj.timestamp).toLocaleString()}
` : this.isBoth ? html` + ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`}
${new Date(this.messageObj.timestamp).toLocaleString()} @@ -2176,7 +2195,7 @@ class MessageTemplate extends LitElement { await writeFile(fileHandle, blob).then(() => console.log('FILE SAVED')) } catch (error) { - console.log(error) + console.error(error) } } diff --git a/plugins/plugins/core/components/qdn-action-constants.js b/plugins/plugins/core/components/qdn-action-constants.js index 323f6f10..5f311f53 100644 --- a/plugins/plugins/core/components/qdn-action-constants.js +++ b/plugins/plugins/core/components/qdn-action-constants.js @@ -55,6 +55,125 @@ export const mimeToExtensionMap = { "application/x-bzip2": ".bz2", } +export const parseQortalLink = (link) => { + const prefix = "qortal://use-embed/" + + let params = {} + + if (!link.startsWith(prefix)) { + throw new Error("Invalid link format") + } + + const [typePart, queryPart] = link.slice(prefix.length).split("?") + const type = typePart.split("/")[0].toUpperCase() + + if (queryPart) { + const queryPairs = queryPart.split("&") + queryPairs.forEach((pair) => { + const [key, value] = pair.split("=") + if (key && value) { + const decodedKey = decodeURIComponent(key.trim()) + const decodedValue = value.trim().replace(/<\/?[^>]+(>|$)/g,"") + params[decodedKey] = decodedValue + } + }) + } + + return { type, ...params } +} + +export const extensionToPointer = (repString) => { + const replace00 = repString.split('qortal://use-embed/').join('qortal://use-embed/') + const replace01 = replace00.split('.pdf').join('.pdf') + const replace02 = replace01.split('.doc').join('.doc') + const replace03 = replace02.split('.xls').join('.xls') + const replace04 = replace03.split('.ppt').join('.ppt') + const replace05 = replace04.split('.odt').join('.odt') + const replace06 = replace05.split('.ods').join('.ods') + const replace07 = replace06.split('.odp').join('.odp') + const replace08 = replace07.split('.txt').join('.txt') + const replace09 = replace08.split('.csv').join('.csv') + const replace10 = replace09.split('.html').join('.html') + const replace11 = replace10.split('.xml').join('.xml') + const replace12 = replace11.split('.json').join('.json') + const replace13 = replace12.split('.jpg').join('.jpg') + const replace14 = replace13.split('.png').join('.png') + const replace15 = replace14.split('.gif').join('.gif') + const replace16 = replace15.split('.webp').join('.webp') + const replace17 = replace16.split('.svg').join('.svg') + const replace18 = replace17.split('.tif').join('.tif') + const replace19 = replace18.split('.bmp').join('.bmp') + const replace20 = replace19.split('.mp3').join('.mp3') + const replace21 = replace20.split('.ogg').join('.ogg') + const replace22 = replace21.split('.wav').join('.wav') + const replace23 = replace22.split('.webm').join('.webm') + const replace24 = replace23.split('.ogv').join('.ogv') + const replace25 = replace24.split('.avi').join('.avi') + const replace26 = replace25.split('.mov').join('.mov') + const replace27 = replace26.split('.wmv').join('.wmv') + const replace28 = replace27.split('.mpeg').join('.mpeg') + const replace29 = replace28.split('.3gp').join('.3gp') + const replace30 = replace29.split('.3g2').join('.3g2') + const replace31 = replace30.split('.mkv').join('.mkv') + const replace32 = replace31.split('.flv').join('.flv') + const replace33 = replace32.split('.zip').join('.zip') + const replace34 = replace33.split('.rar').join('.rar') + const replace35 = replace34.split('.tar').join('.tar') + const replace36 = replace35.split('.7z').join('.7z') + const replace37 = replace36.split('.gz').join('.gz') + const replace38 = replace37.split('.bz2').join('.bz2') + + return replace38 +} + +export const encodedToChar = (encodedString) => { + const encode01 = encodedString.split('&').join('&') + const encode02 = encode01.split(' ').join(' ') + const encode03 = encode02.split('<').join('<') + const encode04 = encode03.split('>').join('>') + const encode05 = encode04.split('"').join('"') + const encode06 = encode05.split('%20').join(' ') + const encode07 = encode06.split('%23').join('#') + const encode08 = encode07.split('%24').join('$') + const encode09 = encode08.split('%26').join('&') + const encode10 = encode09.split('%2B').join('+') + const encode11 = encode10.split('%2C').join(',') + const encode12 = encode11.split('%2F').join('/') + const encode13 = encode12.split('%3A').join(':') + const encode14 = encode13.split('%3B').join(';') + const encode15 = encode14.split('%3D').join('=') + const encode16 = encode15.split('%3F').join('?') + const encode17 = encode16.split('%40').join('@') + + return encode17 +} + +export const embedToString = (embed) => { + let embedString = '' + let embedService = '' + let embedName = '' + let embedIdentifier = '' + let embedAttachmentName = '' + + if (embed.type === "IMAGE") { + embedService = embed.service + embedName = embed.name + embedIdentifier = embed.identifier + embedString = ',"images":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '"}],"isImageDeleted":false' + } else if (embed.type === "ATTACHMENT") { + embedService = embed.service + embedName = embed.name + embedIdentifier = embed.identifier + embedAttachmentName = embed.fileName + embedString = ',"attachments":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '","attachmentName":"' + embedAttachmentName + '","attachmentSize":0}],"isAttachmentDeleted":false' + } else { + embedString = ',"images":[""]' + } + + return embedString +} + + export const listOfAllQortalRequests = [ 'IS_USING_GATEWAY', 'ADMIN_ACTION', @@ -69,6 +188,7 @@ export const listOfAllQortalRequests = [ 'DECRYPT_QORTAL_GROUP_DATA', 'ENCRYPT_DATA_WITH_SHARING_KEY', 'DECRYPT_DATA_WITH_SHARING_KEY', + 'DECRYPT_AESGCM', 'CREATE_TRADE_BUY_ORDER', 'CREATE_TRADE_SELL_ORDER', 'CANCEL_TRADE_SELL_ORDER', diff --git a/plugins/plugins/core/components/qdn-action-types.js b/plugins/plugins/core/components/qdn-action-types.js index 25fc7f68..b0aaf8b5 100644 --- a/plugins/plugins/core/components/qdn-action-types.js +++ b/plugins/plugins/core/components/qdn-action-types.js @@ -33,6 +33,9 @@ export const ENCRYPT_DATA_WITH_SHARING_KEY = 'ENCRYPT_DATA_WITH_SHARING_KEY' // DECRYPT_DATA_WITH_SHARING_KEY export const DECRYPT_DATA_WITH_SHARING_KEY = 'DECRYPT_DATA_WITH_SHARING_KEY' +// DECRYPT_AESGCM +export const DECRYPT_AESGCM = 'DECRYPT_AESGCM' + // CREATE_TRADE_BUY_ORDER export const CREATE_TRADE_BUY_ORDER = 'CREATE_TRADE_BUY_ORDER' diff --git a/plugins/plugins/core/components/webworkerDecodeMessages.js b/plugins/plugins/core/components/webworkerDecodeMessages.js index e811cc52..7c37cad7 100644 --- a/plugins/plugins/core/components/webworkerDecodeMessages.js +++ b/plugins/plugins/core/components/webworkerDecodeMessages.js @@ -5,7 +5,12 @@ import { uint8ArrayToObject, decryptSingle } from './GroupEncryption.js' - +import { + extensionToPointer, + encodedToChar, + embedToString, + parseQortalLink +} from './qdn-action-constants.js' const nacl = {} @@ -2738,7 +2743,6 @@ class Curve25519 { } const base58Instant = new Base58() - const curve25519Instance = new Curve25519() self.addEventListener('message', async (e) => { @@ -2762,7 +2766,6 @@ self.addEventListener('message', async (e) => { } }) - const decode = (string, keys, ref) => { const binaryString = atob(string) const binaryLength = binaryString.length @@ -2785,13 +2788,16 @@ const decode = (string, keys, ref) => { } } else { let repliedToStr = '' + let addedFileStr = '' let messageStr = '' let hubString = '' + let messageRep = '' + let messageUseEmbed = {} const res = decryptSingle(string, keys, false) if (res === 'noKey' || res === 'decryptionFailed') { - return '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This message could not be decrypted"}]}]},"images":[""],"repliedTo":"","version":3}' + return '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This message could not be decrypted"}]}]}' + addedFileStr + ',"repliedTo":"","version":3,"isFromHub":true}' } const decryptToUnit8Array = base64ToUint8Array(res) @@ -2810,7 +2816,26 @@ const decode = (string, keys, ref) => { } if (responseData.hasOwnProperty('message') && typeof responseData['message'] === 'string' && responseData['message'].length) { - const messageRep = responseData.message + if (responseData.message.includes('qortal://use-embed/')) { + const useEmbed1 = extensionToPointer(responseData.message) + const useEmbed2 = /(.*?)<\/newpointer>/g.exec(useEmbed1) + const useEmbed3 = encodedToChar(useEmbed2[1]) + + messageUseEmbed = parseQortalLink(useEmbed3) + addedFileStr = embedToString(messageUseEmbed) + + const useEmbed4 = responseData.message.split(useEmbed2[1]).join('') + + if (useEmbed4 === "

") { + messageRep = useEmbed4.split('

').join('

Qortal-Hub embed link

') + } else { + messageRep = useEmbed4 + } + } else { + messageRep = responseData.message + addedFileStr = ',"images":[""]' + } + const messageRep1 = messageRep.split('"').join('') const messageRep2 = messageRep1.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') const messageRep3 = messageRep2.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') @@ -2833,11 +2858,11 @@ const decode = (string, keys, ref) => { } if (responseData.type === "edit") { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]},"images":[""],"repliedTo":"' + repliedToStr + '","version":3,"isEdited":true}' + hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isEdited":true,"isFromHub":true}' } else if (responseData.type === "reaction") { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]},"images":[""],"repliedTo":"' + repliedToStr + '","version":3,"isReaction":true}' + hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isReaction":true,"isFromHub":true}' } else { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]},"images":[""],"repliedTo":"' + repliedToStr + '","version":3}' + hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isFromHub":true}' } const preparedString = hubString.split('').join('\\"') diff --git a/plugins/plugins/core/qdn/browser/browser.src.js b/plugins/plugins/core/qdn/browser/browser.src.js index d7c7f20f..c49dbbb5 100644 --- a/plugins/plugins/core/qdn/browser/browser.src.js +++ b/plugins/plugins/core/qdn/browser/browser.src.js @@ -1,29 +1,30 @@ -import { html, LitElement } from 'lit' -import { Epml } from '../../../../epml' +import {html, LitElement} from 'lit' +import {Epml} from '../../../../epml' +import {Sha256} from 'asmcrypto.js' import { - Loader, - publishData, - getPublishesFromAdmins, - getGroupAdmins, - getPublishesFromAdminsAdminSpace, - isUsingPublicNode, - createBuyOrderTx, - requestQueueGetAtAddresses, - getUserWalletFunc, - tradeBotCreateRequest, cancelTradeOfferTradeBot, - processTransactionV2 + createBuyOrderTx, + getGroupAdmins, + getPublishesFromAdmins, + getPublishesFromAdminsAdminSpace, + getUserWalletFunc, + isUsingPublicNode, + Loader, + processTransactionV2, + publishData, + requestQueueGetAtAddresses, + tradeBotCreateRequest } from '../../../utils/classes' -import { appendBuffer } from '../../../utils/utilities' -import { QORT_DECIMALS } from '../../../../../crypto/api/constants' -import { mimeToExtensionMap, listOfAllQortalRequests } from '../../components/qdn-action-constants' +import {appendBuffer} from '../../../utils/utilities' +import {QORT_DECIMALS} from '../../../../../crypto/api/constants' +import {listOfAllQortalRequests} from '../../components/qdn-action-constants' import { - uint8ArrayToObject, - validateSecretKey, - encryptSingle, - decryptSingle, createSymmetricKeyAndNonce, - decryptGroupEncryptionWithSharingKey + decryptGroupEncryptionWithSharingKey, + decryptSingle, + encryptSingle, + uint8ArrayToObject, + validateSecretKey } from '../../components/GroupEncryption' import { base64ToUint8Array, @@ -33,28 +34,28 @@ import { encryptDataGroup, encryptDataGroupNew, fileToBase64, - uint8ArrayStartsWith, - uint8ArrayToBase64, - base64ToBlobUrl, groupSecretkeys, objectToBase64, - roundUpToDecimals + roundUpToDecimals, + uint8ArrayStartsWith, + uint8ArrayToBase64 } from '../../components/qdn-action-encryption' -import { webBrowserStyles, webBrowserModalStyles } from '../../components/plugins-css' +import {webBrowserModalStyles, webBrowserStyles} from '../../components/plugins-css' import * as actions from '../../components/qdn-action-types' import isElectron from 'is-electron' import ShortUniqueId from 'short-unique-id' -import FileSaver from 'file-saver' import WebWorker from 'web-worker:./computePowWorkerFile.js' import WebWorkerChat from 'web-worker:./computePowWorker.js' import Base58 from '../../../../../crypto/api/deps/Base58' +import ed2curve from '../../../../../crypto/api/deps/ed2curve' import nacl from '../../../../../crypto/api/deps/nacl-fast' import '@material/mwc-button' import '@material/mwc-icon' import '@material/mwc-checkbox' // Multi language support -import { get, registerTranslateConfig, translate, use } from '../../../../../core/translate' +import {get, registerTranslateConfig, translate, use} from '../../../../../core/translate' + registerTranslateConfig({ loader: lang => fetch(`/language/${lang}.json`).then(res => res.json()) }) @@ -148,11 +149,11 @@ class WebBrowser extends LitElement { } else { displayUrl = 'qortal://' + this.service + '/' + this.name - if (this.identifier && this.identifier != 'null' && this.identifier != 'default') { + if (this.identifier && this.identifier !== 'null' && this.identifier !== 'default') { displayUrl = displayUrl.concat('/' + this.identifier) } - if (this.path != null && this.path != '/') { + if (this.path != null && this.path !== '/') { displayUrl = displayUrl.concat(this.path) } } @@ -192,7 +193,7 @@ class WebBrowser extends LitElement { this.url = `${this.link}` } else { // Normal mode - this.url = `${nodeUrl}/render/${this.service}/${this.name}${this.path != null ? this.path : ''}?theme=${this.theme}&identifier=${(this.identifier != null && this.identifier != 'null') ? this.identifier : ''}` + this.url = `${nodeUrl}/render/${this.service}/${this.name}${this.path != null ? this.path : ''}?theme=${this.theme}&identifier=${(this.identifier != null && this.identifier !== 'null') ? this.identifier : ''}` } } @@ -252,7 +253,7 @@ class WebBrowser extends LitElement { this.goBackToList()} title="${translate('browserpage.bchange3')}" class="address-bar-button"> home - + ${this.renderFullScreen()} this.delete()} title="${translate('browserpage.bchange4')} ${this.service} ${this.name} ${translate('browserpage.bchange5')}" class="address-bar-button float-right"> delete @@ -305,7 +306,7 @@ class WebBrowser extends LitElement { } window.addEventListener('message', async (event) => { - if (event == null || event.data == null || event.data.length == 0 || event.data.action == null) { + if (event == null || event.data == null || event.data.length === 0 || event.data.action == null) { return } @@ -314,10 +315,9 @@ class WebBrowser extends LitElement { switch (data.action) { case actions.IS_USING_PUBLIC_NODE: { - const res = await isUsingPublicNode() - response = res - break + response = await isUsingPublicNode() } + break case actions.ADMIN_ACTION: { let type = data.type @@ -375,7 +375,8 @@ class WebBrowser extends LitElement { includeValueInBody = true break default: - throw new Error(`Unknown admin action type: ${type}`) + console.error(`Unknown admin action type: ${type}`) + break } // Set up options for the API call let options = { @@ -402,13 +403,13 @@ class WebBrowser extends LitElement { data['error'] = `User declined admin action: ${type}` response = JSON.stringify(data) } - break } + break case actions.SHOW_ACTIONS: { response = listOfAllQortalRequests - break } + break case actions.GET_USER_ACCOUNT: { let skip = false @@ -436,9 +437,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = "User declined to share account details" response = JSON.stringify(data) - break } } + break case actions.ENCRYPT_DATA: { try { @@ -469,9 +470,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message || "Error in encrypting data" response = JSON.stringify(data) - break } } + break case actions.DECRYPT_DATA: { const { encryptedData, publicKey } = data @@ -510,12 +511,12 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message || "Error in decrypting data" response = JSON.stringify(data) - break } } + break case actions.ENCRYPT_QORTAL_GROUP_DATA: { - let data64 = data.data64 || data.base64 + let data64 = data.data64 ? data.data64 : data.base64 let groupId = data.groupId let isAdmins = data.isAdmins let dataSentBack = {} @@ -542,7 +543,6 @@ class WebBrowser extends LitElement { ) { secretKeyObject = groupSecretkeys[groupId].secretKeyObject } - if(!secretKeyObject) { const { names } = await getGroupAdmins(groupId) const publish = await getPublishesFromAdmins(names, groupId) @@ -551,10 +551,10 @@ class WebBrowser extends LitElement { response = JSON.stringify(dataSentBack) break } - const res = await parentEpml.request('apiCall', { + const resData = await parentEpml.request('apiCall', { + type: 'api', url: `/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${publish.identifier}?encoding=base64` }) - const resData = await res.text() const decryptedKey = await this.decryptResourceQDN(resData) const dataint8Array = base64ToUint8Array(decryptedKey.data) const decryptedKeyToObject = uint8ArrayToObject(dataint8Array) @@ -564,7 +564,8 @@ class WebBrowser extends LitElement { break } secretKeyObject = decryptedKeyToObject - groupSecretkeys[groupId] = { + let groupSecretkeys = {} + groupSecretkeys[`${groupId}`] = { secretKeyObject, timestamp: Date.now() } @@ -586,10 +587,10 @@ class WebBrowser extends LitElement { response = JSON.stringify(dataSentBack) break } - const res = await parentEpml.request('apiCall', { + const resData = await parentEpml.request('apiCall', { + type: 'api', url: `/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${publish.identifier}?encoding=base64` }) - const resData = await res.text() const decryptedKey = await this.decryptResourceQDN(resData) const dataint8Array = base64ToUint8Array(decryptedKey.data) const decryptedKeyToObject = uint8ArrayToObject(dataint8Array) @@ -599,26 +600,25 @@ class WebBrowser extends LitElement { break } secretKeyObject = decryptedKeyToObject + let groupSecretkeys = {} groupSecretkeys[`admins-${groupId}`] = { secretKeyObject, timestamp: Date.now() } } } - const resGroupEncryptedResource = encryptSingle({ - data64, secretKeyObject: secretKeyObject - }) + const resGroupEncryptedResource = encryptSingle(data64, secretKeyObjec) if (resGroupEncryptedResource) { - return resGroupEncryptedResource + response = resGroupEncryptedResource } else { dataSentBack['error'] = "Unable to encrypt" response = JSON.stringify(dataSentBack) - break } } + break case actions.DECRYPT_QORTAL_GROUP_DATA: { - let data64 = data.data64 || data.base64 + let data64 = data.daat64 ? data.daat64 : data.base64 let groupId = data.groupId let isAdmins = data.isAdmins let dataSentBack = {} @@ -642,7 +642,6 @@ class WebBrowser extends LitElement { ) { secretKeyObject = groupSecretkeys[groupId].secretKeyObject } - if (!secretKeyObject) { const { names } = await getGroupAdmins(groupId) const publish = await getPublishesFromAdmins(names, groupId) @@ -651,10 +650,10 @@ class WebBrowser extends LitElement { response = JSON.stringify(dataSentBack) break } - const res = await parentEpml.request('apiCall', { + const resData = await parentEpml.request('apiCall', { + type: 'api', url: `/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${publish.identifier}?encoding=base64` }) - const resData = await res.text() const decryptedKey = await this.decryptResourceQDN(resData) const dataint8Array = base64ToUint8Array(decryptedKey.data) const decryptedKeyToObject = uint8ArrayToObject(dataint8Array) @@ -664,7 +663,8 @@ class WebBrowser extends LitElement { break } secretKeyObject = decryptedKeyToObject - groupSecretkeys[groupId] = { + let groupSecretkeys ={} + groupSecretkeys[`${groupId}`] = { secretKeyObject, timestamp: Date.now() } @@ -686,10 +686,10 @@ class WebBrowser extends LitElement { response = JSON.stringify(dataSentBack) break } - const res = await parentEpml.request('apiCall', { + const resData = await parentEpml.request('apiCall', { + type: 'api', url: `/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${publish.identifier}?encoding=base64` }) - const resData = await res.text() const decryptedKey = await this.decryptResourceQDN(resData) const dataint8Array = base64ToUint8Array(decryptedKey.data) const decryptedKeyToObject = uint8ArrayToObject(dataint8Array) @@ -699,23 +699,22 @@ class WebBrowser extends LitElement { break } secretKeyObject = decryptedKeyToObject + let groupSecretkeys ={} groupSecretkeys[`admins-${groupId}`] = { secretKeyObject, timestamp: Date.now() } } } - const resGroupDecryptResource = decryptSingle({ - data64, secretKeyObject: secretKeyObject, skipDecodeBase64: true - }) + const resGroupDecryptResource = decryptSingle(data64, secretKeyObject, false) if (resGroupDecryptResource) { - return resGroupDecryptResource + response = resGroupDecryptResource } else { dataSentBack['error'] = "Unable to decrypt" response = JSON.stringify(dataSentBack) - break } } + break case actions.ENCRYPT_DATA_WITH_SHARING_KEY: { let data64 = data.data64 || data.base64 @@ -749,9 +748,9 @@ class WebBrowser extends LitElement { } else { dataSentBack['error'] = "Unable to encrypt" response = JSON.stringify(dataSentBack) - break } } + break case actions.DECRYPT_DATA_WITH_SHARING_KEY: { let dataSentBack = {} @@ -771,9 +770,82 @@ class WebBrowser extends LitElement { } else { dataSentBack['error'] = "No data in the decrypted resource" response = JSON.stringify(dataSentBack) - break } } + break + + case actions.DECRYPT_AESGCM: { + const requiredFields = ["encryptedData", "iv", "senderPublicKey"] + const missingFields = [] + let dataSentBack = {} + requiredFields.forEach((field) => { + if (!data[field]) { + missingFields.push(field) + } + }) + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(', ') + const tryAgain = get("walletpage.wchange44") + await showErrorAndWait( + "MISSING_FIELDS", + { + id1: missingFieldsString, + id2: tryAgain + } + ) + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` + response = JSON.stringify(dataSentBack) + break + } + const encryptedData = data.encryptedData + const iv = data.iv + const senderPublicKeyBase58 = data.senderPublicKey + // Decode keys and IV + const senderPublicKey = Base58.decode(senderPublicKeyBase58) + const uint8PrivateKey = window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey + // Convert ed25519 keys to Curve25519 + const convertedPrivateKey = ed2curve.convertSecretKey(uint8PrivateKey) + const convertedPublicKey = ed2curve.convertPublicKey(senderPublicKey) + // Generate shared secret + const sharedSecret = new Uint8Array(32) + nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey) + // Derive encryption key + let encryptionKey = new Uint8Array(32) + encryptionKey = new Sha256().process(sharedSecret).finish().result + // Convert IV and ciphertext from Base64 + const base64ToUint8Array = (base64) => Uint8Array.from(atob(base64), c => c.charCodeAt(0)) + const ivUint8Array = base64ToUint8Array(iv) + const ciphertext = base64ToUint8Array(encryptedData) + // Validate IV and key lengths + if (ivUint8Array.length !== 12) { + let myMsg1 = get("managegroup.mg58") + let myMsg2 = get("walletpage.wchange44") + await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) + response = '{"error": "Invalid IV: AES-GCM requires a 12-byte IV."}' + break + } + if (encryptionKey.length !== 32) { + let myMsg1 = get("managegroup.mg58") + let myMsg2 = get("walletpage.wchange44") + await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) + response = '{"error": "Invalid key: AES-GCM requires a 256-bit key."}' + break + } + try { + // Decrypt data + const algorithm = { name: "AES-GCM", iv: ivUint8Array } + const cryptoKey = await crypto.subtle.importKey("raw", encryptionKey, algorithm, false, ["decrypt"]) + const decryptedArrayBuffer = await crypto.subtle.decrypt(algorithm, cryptoKey, ciphertext) + // Return decrypted data as Base64 + return uint8ArrayToBase64(new Uint8Array(decryptedArrayBuffer)) + } catch (error) { + let myMsg1 = get("managegroup.mg58") + let myMsg2 = get("walletpage.wchange44") + await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) + response = '{"error": "Failed to decrypt the message. Ensure the data and keys are correct."}' + } + } + break case actions.CREATE_TRADE_BUY_ORDER: { const node = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] @@ -796,8 +868,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -809,7 +880,6 @@ class WebBrowser extends LitElement { const url = `${nodeUrl}/crosschain/trade/${atAddress}` const resAddress = await fetch(url) const resData = await resAddress.json() - if (foreignBlockchain !== resData.foreignBlockchain) { let myMsg1 = get("modals.mpchange1") let myMsg2 = get("walletpage.wchange44") @@ -817,7 +887,6 @@ class WebBrowser extends LitElement { response = '{"error": "All requested ATs need to be of the same foreign Blockchain."}' throw new Error("All requested ATs need to be of the same foreign Blockchain.") } - return resData }) ) @@ -873,6 +942,7 @@ class WebBrowser extends LitElement { break } } + break case actions.CREATE_TRADE_SELL_ORDER: { const requiredFields = ["qortAmount", "foreignBlockchain", "foreignAmount"] @@ -893,8 +963,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -952,6 +1021,7 @@ class WebBrowser extends LitElement { break } } + break case actions.CANCEL_TRADE_SELL_ORDER: { const requiredFields = ["atAddress"] @@ -972,8 +1042,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -1038,6 +1107,7 @@ class WebBrowser extends LitElement { break } } + break case actions.GET_LIST_ITEMS: { const requiredFields = ['list_name'] @@ -1058,8 +1128,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -1083,6 +1152,7 @@ class WebBrowser extends LitElement { url: `/lists/${data.list_name}?apiKey=${this.getApiKey()}` }) response = JSON.stringify(list) + break } catch (error) { let myMsg1 = get("modals.mpchange16") let myMsg2 = get("walletpage.wchange44") @@ -1090,7 +1160,6 @@ class WebBrowser extends LitElement { const data = {} data['error'] = "Error in retrieving list." response = JSON.stringify(data) - } finally { break } } else { @@ -1098,9 +1167,9 @@ class WebBrowser extends LitElement { let myMsg2 = get("walletpage.wchange44") await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 }) response = '{"error": "User declined request"}' - break } } + break case actions.ADD_LIST_ITEMS: { const requiredFields = ['list_name', 'items'] @@ -1121,8 +1190,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -1150,6 +1218,7 @@ class WebBrowser extends LitElement { 'Content-Type': 'application/json' } }) + break } catch (error) { let myMsg1 = get("modals.mpchange17") let myMsg2 = get("walletpage.wchange44") @@ -1157,7 +1226,6 @@ class WebBrowser extends LitElement { const data = {} data['error'] = "Error in adding to list." response = JSON.stringify(data) - } finally { break } } else { @@ -1165,9 +1233,9 @@ class WebBrowser extends LitElement { let myMsg2 = get("walletpage.wchange44") await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 }) response = '{"error": "User declined request"}' - break } } + break case actions.DELETE_LIST_ITEM: { const requiredFields = ['list_name', 'item'] @@ -1188,8 +1256,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -1217,6 +1284,7 @@ class WebBrowser extends LitElement { 'Content-Type': 'application/json' } }) + break } catch (error) { let myMsg1 = get("modals.mpchange18") let myMsg2 = get("walletpage.wchange44") @@ -1224,7 +1292,6 @@ class WebBrowser extends LitElement { const data = {} data['error'] = "Error in delete list." response = JSON.stringify(data) - } finally { break } } else { @@ -1232,9 +1299,9 @@ class WebBrowser extends LitElement { let myMsg2 = get("walletpage.wchange44") await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 }) response = '{"error": "User declined request"}' - break } } + break case actions.GET_FRIENDS_LIST: { let skip = false @@ -1252,6 +1319,7 @@ class WebBrowser extends LitElement { let list = JSON.parse(localStorage.getItem('friends-my-friend-list') || "[]") list = list.map((friend) => friend.name || "") response = JSON.stringify(list) + break } catch (error) { let myMsg1 = get("modals.mpchange19") let myMsg2 = get("walletpage.wchange44") @@ -1259,7 +1327,6 @@ class WebBrowser extends LitElement { const data = {} data['error'] = "Error in retrieving friends list." response = JSON.stringify(data) - } finally { break } } else { @@ -1267,9 +1334,9 @@ class WebBrowser extends LitElement { let myMsg2 = get("walletpage.wchange44") await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 }) response = '{"error": "User declined request"}' - break } } + break case actions.LINK_TO_QDN_RESOURCE: case actions.QDN_RESOURCE_DISPLAYED: @@ -1277,14 +1344,14 @@ class WebBrowser extends LitElement { // Note: don't update this.url here, as we don't want to force reload the iframe each time. if (this.preview != null && this.preview.length > 0) { this.displayUrl = translate("appspage.schange40") - return + break } let url = 'qortal://' + data.service + '/' + data.name this.path = data.path != null ? (data.path.startsWith('/') ? '' : '/') + data.path : null - if (data.identifier != null && data.identifier != '' && data.identifier != 'default') { + if (data.identifier != null && data.identifier !== '' && data.identifier !== 'default') { url = url.concat('/' + data.identifier) } - if (this.path != null && this.path != '/') { + if (this.path != null && this.path !== '/') { url = url.concat(this.path) } this.name = data.name @@ -1304,7 +1371,7 @@ class WebBrowser extends LitElement { service: data.service, id: tabId ? tabId : '' })) - return + break case actions.SET_TAB_NOTIFICATIONS: { const { count } = data @@ -1327,8 +1394,8 @@ class WebBrowser extends LitElement { count: count })) response = true - break } + break case actions.PUBLISH_QDN_RESOURCE: { // optional fields: encrypt:boolean recipientPublicKey:string @@ -1350,8 +1417,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -1422,7 +1488,6 @@ class WebBrowser extends LitElement { response = JSON.stringify(obj) break } - } const res2 = await showModalAndWait( actions.PUBLISH_QDN_RESOURCE, @@ -1489,8 +1554,8 @@ class WebBrowser extends LitElement { // TODO: prompt user for publish. If they confirm, call `POST /arbitrary/{service}/{name}/{identifier}/base64` and sign+process transaction // then set the response string from the core to the `response` variable (defined above) // If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}` - break } + break case actions.PUBLISH_MULTIPLE_QDN_RESOURCES: { const requiredFields = ['resources'] @@ -1512,8 +1577,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -1591,7 +1655,6 @@ class WebBrowser extends LitElement { }) continue } - const service = resource.service const name = resource.name let identifier = resource.identifier @@ -1699,8 +1762,8 @@ class WebBrowser extends LitElement { break } response = true - break } + break case actions.VOTE_ON_POLL: { const requiredFields = ['pollName', 'optionIndex'] @@ -1721,8 +1784,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -1768,8 +1830,8 @@ class WebBrowser extends LitElement { } finally { this.loader.hide() } - break } + break case actions.CREATE_POLL: { const requiredFields = ['pollName', 'pollDescription', 'pollOptions', 'pollOwnerAddress'] @@ -1790,8 +1852,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -1813,8 +1874,8 @@ class WebBrowser extends LitElement { } finally { this.loader.hide() } - break } + break case actions.OPEN_NEW_TAB: { if (!data.qortalLink) { @@ -1837,9 +1898,9 @@ class WebBrowser extends LitElement { const obj = {} obj['error'] = "Invalid qortal link." response = JSON.stringify(obj) - break } } + break case actions.NOTIFICATIONS_PERMISSION: { try { @@ -1858,16 +1919,25 @@ class WebBrowser extends LitElement { break } } catch (error) { - break + console.error(error) } } + break case actions.SEND_LOCAL_NOTIFICATION: { const { title, url, icon, message } = data try { const id = `appNotificationList-${this.selectedAddress.address}` const checkData = localStorage.getItem(id) ? JSON.parse(localStorage.getItem(id)) : null - if (!checkData || !checkData[this.name]) throw new Error('App not on permission list') + if (!checkData || !checkData[this.name]) { + let myMsg1 = get("modals.mpchange34") + let myMsg2 = get("walletpage.wchange44") + await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) + const obj = {} + obj['error'] = "App not on permission list" + response = JSON.stringify(obj) + break + } const appInfo = checkData[this.name] const lastNotification = appInfo.lastNotification const interval = appInfo.interval @@ -1881,7 +1951,13 @@ class WebBrowser extends LitElement { this.updateLastNotification(id, this.name) break } else { - throw new Error(`invalid data`) + let myMsg1 = get("modals.mpchange34") + let myMsg2 = get("walletpage.wchange44") + await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) + const obj = {} + obj['error'] = "Invalid data" + response = JSON.stringify(obj) + break } } else if (!lastNotification) { parentEpml.request('showNotification', { @@ -1891,11 +1967,13 @@ class WebBrowser extends LitElement { this.updateLastNotification(id) break } else { - let myMsg1 = get("modals.mpchange27") + let myMsg1 = get("modals.mpchange34") let myMsg2 = get("walletpage.wchange44") await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) - throw new Error(`invalid data.`) - } + const obj = {} + obj['error'] = "Invalid data" + response = JSON.stringify(obj) + break } } catch (error) { let myMsg1 = get("modals.mpchange35") let myMsg2 = get("walletpage.wchange44") @@ -1903,9 +1981,9 @@ class WebBrowser extends LitElement { const obj = {} obj['error'] = error.message ? error.message : get("modals.mpchange35") response = JSON.stringify(obj) - break } } + break case actions.SEND_CHAT_MESSAGE: { const message = data.message @@ -2073,8 +2151,8 @@ class WebBrowser extends LitElement { // TODO: prompt user to send chat message. If they confirm, sign+process a CHAT transaction // then set the response string from the core to the `response` variable (defined above) // If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}` - break } + break case actions.JOIN_GROUP: { const requiredFields = ['groupId'] @@ -2095,8 +2173,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2173,118 +2250,7 @@ class WebBrowser extends LitElement { break } } - - case actions.SAVE_FILE: { - try { - const requiredFields = ['filename', 'blob'] - const missingFields = [] - let dataSentBack = {} - requiredFields.forEach((field) => { - if (!data[field]) { - missingFields.push(field) - } - }) - if (missingFields.length > 0) { - const missingFieldsString = missingFields.join(', ') - const tryAgain = get("walletpage.wchange44") - await showErrorAndWait( - "MISSING_FIELDS", - { - id1: missingFieldsString, - id2: tryAgain - } - ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg - response = JSON.stringify(dataSentBack) - break - } - const filename = data.filename - const blob = data.blob - const res = await showModalAndWait( - actions.SAVE_FILE, - { - filename - } - ) - if (res.action === 'reject') { - let myMsg1 = get("transactions.declined") - let myMsg2 = get("walletpage.wchange44") - await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 }) - response = '{"error": "User declined request"}' - break - } - const mimeType = blob.type || data.mimeType - let backupExention = filename.split('.').pop() - if (backupExention) { - backupExention = '.' + backupExention - } - const fileExtension = mimeToExtensionMap[mimeType] || backupExention - let fileHandleOptions = {} - if (!mimeType) { - let myMsg1 = get("modals.mpchange45") - let myMsg2 = get("walletpage.wchange44") - await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) - const obj = {} - obj['error'] = 'A mime type could not be derived.' - response = JSON.stringify(obj) - break - } - if (!fileExtension) { - let myMsg1 = get("modals.mpchange46") - let myMsg2 = get("walletpage.wchange44") - await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) - const obj = {} - obj['error'] = 'A file extension could not be derived.' - response = JSON.stringify(obj) - break - } - if (fileExtension && mimeType) { - fileHandleOptions = { - accept: { - [mimeType]: [fileExtension] - } - } - } - try { - const fileHandle = await self.showSaveFilePicker({ - suggestedName: filename, - types: [ - { - description: mimeType, - ...fileHandleOptions - } - ] - }) - const writeFile = async (fileHandle, contents) => { - const writable = await fileHandle.createWritable() - await writable.write(contents) - await writable.close() - } - writeFile(fileHandle, blob).then(() => console.log("FILE SAVED")) - } catch (error) { - if (error.name === 'AbortError') { - let myMsg1 = get("modals.mpchange47") - let myMsg2 = get("walletpage.wchange44") - await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) - const obj = {} - obj['error'] = 'User declined the download.' - response = JSON.stringify(obj) - break - } - FileSaver.saveAs(blob, filename) - } - response = JSON.stringify(true) - } catch (error) { - let myMsg1 = get("modals.mpchange48") - let myMsg2 = get("walletpage.wchange44") - await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) - const obj = {} - obj['error'] = error.message ? error.message : get("modals.mpchange48") - response = JSON.stringify(obj) - } break - } case actions.DEPLOY_AT: { const requiredFields = ['name', 'description', 'tags', 'creationBytes', 'amount', 'assetId', 'type'] @@ -2305,8 +2271,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2314,18 +2279,19 @@ class WebBrowser extends LitElement { this.loader.show() const resDeployAt = await this._deployAt(data.name, data.description, data.tags, data.creationBytes, data.amount, data.assetId, data.type) response = JSON.stringify(resDeployAt) + this.loader.hide() + break } catch (error) { + this.loader.hide() let myMsg1 = get("modals.mpchange49") let myMsg2 = get("walletpage.wchange44") await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) const obj = {} obj['error'] = error.message ? error.message : get("modals.mpchange49") response = JSON.stringify(obj) - } finally { - this.loader.hide() } - break } + break case actions.GET_PROFILE_DATA: { const defaultProperties = ['tagline', 'bio', 'wallets'] @@ -2347,8 +2313,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2421,9 +2386,9 @@ class WebBrowser extends LitElement { const obj = {} obj['error'] = error.message ? error.message : get("modals.mpchange52") response = JSON.stringify(obj) - break } } + break case actions.SET_PROFILE_DATA: { const requiredFields = ['property', 'data'] @@ -2444,8 +2409,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2511,8 +2475,8 @@ class WebBrowser extends LitElement { obj['error'] = error.message ? error.message : get("modals.mpchange53") response = JSON.stringify(obj) } - break } + break case actions.OPEN_PROFILE: { const requiredFields = ['name'] @@ -2533,8 +2497,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2552,9 +2515,9 @@ class WebBrowser extends LitElement { const obj = {} obj['error'] = error.message ? error.message : get("modals.mpchange54") response = JSON.stringify(obj) - break } } + break case actions.GET_USER_WALLET: { const requiredFields = ['coin'] @@ -2575,8 +2538,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2635,6 +2597,7 @@ class WebBrowser extends LitElement { break } } + break case actions.GET_WALLET_BALANCE: { const requiredFields = ['coin'] @@ -2657,8 +2620,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2683,16 +2645,16 @@ class WebBrowser extends LitElement { response = await parentEpml.request('apiCall', { url: `/addresses/balance/${qortAddress}?apiKey=${this.getApiKey()}` }) + this.loader.hide() + break } catch (error) { this.loader.hide() let myMsg1 = get("browserpage.bchange21") let myMsg2 = get("walletpage.wchange44") - await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) + await showErrorAndWait("ACTION_FAILED", {id1: myMsg1, id2: myMsg2}) const data = {} data['error'] = error.message ? error.message : get("browserpage.bchange21") response = JSON.stringify(data) - } finally { - this.loader.hide() } } else { let _url = `` @@ -2740,9 +2702,11 @@ class WebBrowser extends LitElement { const data = {} data['error'] = get("browserpage.bchange21") response = JSON.stringify(data) - return + break } else { + this.loader.hide() response = (Number(res) / 1e8).toFixed(8) + break } } catch (error) { this.loader.hide() @@ -2752,9 +2716,7 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message ? error.message : get("browserpage.bchange21") response = JSON.stringify(data) - return - } finally { - this.loader.hide() + break } } } else if (res3.action === 'reject') { @@ -2762,9 +2724,10 @@ class WebBrowser extends LitElement { let myMsg2 = get("walletpage.wchange44") await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 }) response = '{"error": "User declined request"}' + break } - break } + break case actions.GET_USER_WALLET_INFO: { const requiredFields = ['coin'] @@ -2785,8 +2748,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2829,8 +2791,8 @@ class WebBrowser extends LitElement { await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 }) response = '{"error": "User declined request"}' } - break } + break case actions.GET_CROSSCHAIN_SERVER_INFO: { const requiredFields = ['coin'] @@ -2851,8 +2813,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2879,8 +2840,8 @@ class WebBrowser extends LitElement { } finally { this.loader.hide() } - break } + break case actions.GET_TX_ACTIVITY_SUMMARY: { const requiredFields = ['coin'] @@ -2901,8 +2862,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -2917,6 +2877,7 @@ class WebBrowser extends LitElement { 'Content-Type': 'application/json' } }) + break } catch (error) { let myMsg1 = get("modals.mpchange56") let myMsg2 = get("walletpage.wchange44") @@ -2924,10 +2885,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message ? error.message : get("modals.mpchange56") response = JSON.stringify(data) - } finally { - break } } + break case actions.GET_FOREIGN_FEE: { const requiredFields = ['coin','type'] @@ -2948,13 +2908,12 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } try { - let coin = data.coin + let coin = data.coin.toLowerCase() let type = data.type response = await parentEpml.request('apiCall', { type: 'api', @@ -2965,6 +2924,7 @@ class WebBrowser extends LitElement { 'Content-Type': 'application/json' }, }) + break } catch (error) { let myMsg1 = get("modals.mpchange57") let myMsg2 = get("walletpage.wchange44") @@ -2972,10 +2932,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message ? error.message : get("modals.mpchange57") response = JSON.stringify(data) - } finally { - break } } + break case actions.UPDATE_FOREIGN_FEE: { const requiredFields = ['coin','type'] @@ -2996,13 +2955,12 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } try { - let coin = data.coin + let coin = data.coin.toLowerCase() let type = data.type let value = data.value response = await parentEpml.request('apiCall', { @@ -3015,6 +2973,7 @@ class WebBrowser extends LitElement { }, body: `${value}` }) + break } catch (error) { let myMsg1 = get("modals.mpchange58") let myMsg2 = get("walletpage.wchange44") @@ -3022,10 +2981,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message ? error.message : get("modals.mpchange58") response = JSON.stringify(data) - } finally { - break } } + break case actions.GET_SERVER_CONNECTION_HISTORY: { const requiredFields = ['coin'] @@ -3046,8 +3004,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -3062,6 +3019,7 @@ class WebBrowser extends LitElement { 'Content-Type': 'application/json' }, }) + break } catch (error) { let myMsg1 = get("modals.mpchange59") let myMsg2 = get("walletpage.wchange44") @@ -3069,10 +3027,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message ? error.message : get("modals.mpchange59") response = JSON.stringify(data) - } finally { - break } } + break case actions.SET_CURRENT_FOREIGN_SERVER: { const requiredFields = ['coin'] @@ -3093,13 +3050,12 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } try { - let coin = data.coin + let coin = data.coin.toLowerCase() let host = data.host let port = data.port let type = data.type @@ -3119,6 +3075,7 @@ class WebBrowser extends LitElement { }, body: `${bodyToString}` }) + break } catch (error) { let myMsg1 = get("modals.mpchange60") let myMsg2 = get("walletpage.wchange44") @@ -3126,10 +3083,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message ? error.message : get("modals.mpchange60") response = JSON.stringify(data) - } finally { - break } } + break case actions.ADD_FOREIGN_SERVER: { const requiredFields = ['coin'] @@ -3150,13 +3106,12 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } try { - let coin = data.coin + let coin = data.coin.toLowerCase() let host = data.host let port = data.port let type = data.type @@ -3176,6 +3131,7 @@ class WebBrowser extends LitElement { }, body: `${bodyToString}` }) + break } catch (error) { let myMsg1 = get("modals.mpchange61") let myMsg2 = get("walletpage.wchange44") @@ -3183,10 +3139,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message ? error.message : get("modals.mpchange61") response = JSON.stringify(data) - } finally { - break } } + break case actions.REMOVE_FOREIGN_SERVER: { const requiredFields = ['coin'] @@ -3207,13 +3162,12 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } try { - let coin = data.coin + let coin = data.coin.toLowerCase() let host = data.host let port = data.port let type = data.type @@ -3233,6 +3187,7 @@ class WebBrowser extends LitElement { }, body: `${bodyToString}` }) + break } catch (error) { let myMsg1 = get("modals.mpchange62") let myMsg2 = get("walletpage.wchange44") @@ -3240,10 +3195,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message ? error.message : get("modals.mpchange62") response = JSON.stringify(data) - } finally { - break } } + break case actions.GET_DAY_SUMMARY: { try { @@ -3251,6 +3205,7 @@ class WebBrowser extends LitElement { type: 'api', url: `/admin/summary?apiKey=${this.getApiKey()}` }) + break } catch (error) { let myMsg1 = get("modals.mpchange63") let myMsg2 = get("walletpage.wchange44") @@ -3258,10 +3213,9 @@ class WebBrowser extends LitElement { const data = {} data['error'] = error.message ? error.message : get("modals.mpchange63") response = JSON.stringify(data) - } finally { - break } } + break case actions.SIGN_TRANSACTION: { const signNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] @@ -3284,8 +3238,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -3380,9 +3333,9 @@ class WebBrowser extends LitElement { let myMsg2 = get("walletpage.wchange44") await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 }) response = '{"error": "User declined request"}' - break } } + break case actions.SEND_COIN: { const requiredFields = ['coin', 'amount'] @@ -3403,8 +3356,7 @@ class WebBrowser extends LitElement { id2: tryAgain } ) - const errorMsg = `Missing fields: ${missingFieldsString}` - dataSentBack['error'] = errorMsg + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` response = JSON.stringify(dataSentBack) break } @@ -3577,7 +3529,7 @@ class WebBrowser extends LitElement { this.loader.hide() let myMsg1 = txnResponse.message let myMsg2 = get("walletpage.wchange44") - showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) + showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) throw new Error(txnResponse.message) } else if (txnResponse.success === true && !txnResponse.data.error) { this.loader.hide() @@ -4201,10 +4153,11 @@ class WebBrowser extends LitElement { break } } - break + break + default: console.log('Unhandled message: ' + JSON.stringify(data)) - return + break } // Parse response let responseObj @@ -4234,7 +4187,7 @@ class WebBrowser extends LitElement { } renderFullScreen() { - if (window.innerHeight == screen.height) { + if (window.innerHeight === screen.height) { return html` this.exitFullScreen()} @@ -4862,7 +4815,7 @@ class WebBrowser extends LitElement { } goBackToList() { - if (this.service == "APP") { + if (this.service === "APP") { this.exitFullScreen() window.location = '../../q-app/index.html' } @@ -4908,7 +4861,7 @@ class WebBrowser extends LitElement { // Remove it first by filtering the list - doing it this way ensures the UI updates // immediately, as apposed to only adding if it doesn't already exist this.followedNames = this.followedNames.filter( - (item) => item != name + (item) => item !== name ) this.followedNames.push(name) } else { @@ -4932,7 +4885,7 @@ class WebBrowser extends LitElement { if (ret === true) { // Successfully unfollowed - remove from local list this.followedNames = this.followedNames.filter( - (item) => item != name + (item) => item !== name ) } else { let err2string = get('browserpage.bchange12') @@ -4957,7 +4910,7 @@ class WebBrowser extends LitElement { // Remove it first by filtering the list - doing it this way ensures the UI updates // immediately, as apposed to only adding if it doesn't already exist this.blockedNames = this.blockedNames.filter( - (item) => item != name + (item) => item !== name ) this.blockedNames.push(name) } else { @@ -4980,7 +4933,7 @@ class WebBrowser extends LitElement { }) if (ret === true) { // Successfully unblocked - remove from local list - this.blockedNames = this.blockedNames.filter((item) => item != name) + this.blockedNames = this.blockedNames.filter((item) => item !== name) } else { let err4string = get('browserpage.bchange14') parentEpml.request('showSnackBar', `${err4string}`) @@ -4989,13 +4942,13 @@ class WebBrowser extends LitElement { } async deleteCurrentResource() { - if (this.followedNames.indexOf(this.name) != -1) { + if (this.followedNames.indexOf(this.name) !== -1) { // Following name - so deleting won't work let err5string = get('browserpage.bchange15') parentEpml.request('showSnackBar', `${err5string}`) return } - let identifier = (this.identifier == null || this.identifier.length == 0) ? 'default' : this.identifier + let identifier = (this.identifier == null || this.identifier.length === 0) ? 'default' : this.identifier let ret = await parentEpml.request('apiCall', { url: `/arbitrary/resource/${this.service}/${this.name}/${identifier}?apiKey=${this.getApiKey()}`, method: 'DELETE' diff --git a/plugins/plugins/utils/classes.js b/plugins/plugins/utils/classes.js index 605f28b8..751c7194 100644 --- a/plugins/plugins/utils/classes.js +++ b/plugins/plugins/utils/classes.js @@ -1105,6 +1105,19 @@ export const publishData = async ({ } } +export async function getNameInfo(address) { + 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 response = await fetch(`${nodeUrl}/names/address/` + address) + const nameData = await response.json() + + if (nameData.length > 0) { + return nameData[0].name + } else { + return "" + } +} + export const getPublishesFromAdmins = async (admins, groupId) => { const queryString = admins.map((name) => `name=${name}`).join("&") const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] @@ -1113,7 +1126,7 @@ export const getPublishesFromAdmins = async (admins, groupId) => { const response = await fetch(url) if (!response.ok) { - consoöe.error("network error") + console.error("network error") return false } @@ -1178,7 +1191,7 @@ export const getPublishesFromAdminsAdminSpace = async (admins, groupId) => { const response = await fetch(url) if (!response.ok) { - consoöe.error("network error") + console.error("network error") return false } From 72ec9fc0923cd5658ba19387d0da14f0aebaba87 Mon Sep 17 00:00:00 2001 From: AlphaX-Qortal Date: Sun, 9 Feb 2025 19:47:15 +0100 Subject: [PATCH 2/8] Update dependencies --- package-lock.json | 244 ++++++++++++++++++++++++---------------------- package.json | 6 +- 2 files changed, 129 insertions(+), 121 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9bd82e7..5d306830 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,7 +53,7 @@ "xhr2": "0.2.1" }, "devDependencies": { - "@babel/core": "7.26.7", + "@babel/core": "7.26.8", "@electron/packager": "18.3.6", "@material/mwc-button": "0.27.0", "@material/mwc-checkbox": "0.27.0", @@ -107,7 +107,7 @@ "@vaadin/tooltip": "24.2.9", "@zip.js/zip.js": "2.7.57", "axios": "1.7.9", - "electron": "34.1.0", + "electron": "34.1.1", "electron-builder": "25.1.8", "epml": "0.3.3", "file-saver": "2.0.5", @@ -119,7 +119,7 @@ "pwa-helpers": "0.9.1", "redux": "5.0.1", "redux-thunk": "3.1.0", - "rollup": "4.34.4", + "rollup": "4.34.6", "rollup-plugin-node-globals": "1.4.0", "rollup-plugin-progress": "1.1.2", "rollup-plugin-scss": "3.0.0", @@ -169,22 +169,23 @@ } }, "node_modules/@babel/core": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", - "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.8.tgz", + "integrity": "sha512-l+lkXCHS6tQEc5oUpK28xBOZ6+HwaH7YwoYQbLFiYb4nS2/l1tKnZEtEWkD0GuiYdvArf9qBS0XlQGXzPMsNqQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.5", + "@babel/generator": "^7.26.8", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", "@babel/helpers": "^7.26.7", - "@babel/parser": "^7.26.7", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.26.7", - "@babel/types": "^7.26.7", + "@babel/parser": "^7.26.8", + "@babel/template": "^7.26.8", + "@babel/traverse": "^7.26.8", + "@babel/types": "^7.26.8", + "@types/gensync": "^1.0.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -200,14 +201,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", - "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.8.tgz", + "integrity": "sha512-ef383X5++iZHWAXX0SXQR6ZyQhw/0KtTkrTz61WXRhFM6dhpHulO/RJz79L8S6ugZHJkOOkUrUdxgdF2YiPFnA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.5", - "@babel/types": "^7.26.5", + "@babel/parser": "^7.26.8", + "@babel/types": "^7.26.8", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -310,13 +311,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", - "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.8.tgz", + "integrity": "sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.7" + "@babel/types": "^7.26.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -326,32 +327,32 @@ } }, "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.8.tgz", + "integrity": "sha512-iNKaX3ZebKIsCvJ+0jd6embf+Aulaa3vNBqZ41kM7iTWjx5qzWKXGHiJUW3+nTpQ18SG11hdF8OAzKrpXkb96Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.8", + "@babel/types": "^7.26.8" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", - "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.8.tgz", + "integrity": "sha512-nic9tRkjYH0oB2dzr/JoGIm+4Q6SuYeLEiIiZDwBscRMYFJ+tMAz98fuel9ZnbXViA2I0HVSSRRK8DW5fjXStA==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.7", - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.7", + "@babel/generator": "^7.26.8", + "@babel/parser": "^7.26.8", + "@babel/template": "^7.26.8", + "@babel/types": "^7.26.8", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -360,9 +361,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", - "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.8.tgz", + "integrity": "sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==", "dev": true, "license": "MIT", "dependencies": { @@ -3069,9 +3070,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.4.tgz", - "integrity": "sha512-gGi5adZWvjtJU7Axs//CWaQbQd/vGy8KGcnEaCWiyCqxWYDxwIlAHFuSe6Guoxtd0SRvSfVTDMPd5H+4KE2kKA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.6.tgz", + "integrity": "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==", "cpu": [ "arm" ], @@ -3083,9 +3084,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.4.tgz", - "integrity": "sha512-1aRlh1gqtF7vNPMnlf1vJKk72Yshw5zknR/ZAVh7zycRAGF2XBMVDAHmFQz/Zws5k++nux3LOq/Ejj1WrDR6xg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.6.tgz", + "integrity": "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==", "cpu": [ "arm64" ], @@ -3097,9 +3098,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.4.tgz", - "integrity": "sha512-drHl+4qhFj+PV/jrQ78p9ch6A0MfNVZScl/nBps5a7u01aGf/GuBRrHnRegA9bP222CBDfjYbFdjkIJ/FurvSQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.6.tgz", + "integrity": "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==", "cpu": [ "arm64" ], @@ -3111,9 +3112,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.4.tgz", - "integrity": "sha512-hQqq/8QALU6t1+fbNmm6dwYsa0PDD4L5r3TpHx9dNl+aSEMnIksHZkSO3AVH+hBMvZhpumIGrTFj8XCOGuIXjw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.6.tgz", + "integrity": "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==", "cpu": [ "x64" ], @@ -3125,9 +3126,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.4.tgz", - "integrity": "sha512-/L0LixBmbefkec1JTeAQJP0ETzGjFtNml2gpQXA8rpLo7Md+iXQzo9kwEgzyat5Q+OG/C//2B9Fx52UxsOXbzw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.6.tgz", + "integrity": "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==", "cpu": [ "arm64" ], @@ -3139,9 +3140,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.4.tgz", - "integrity": "sha512-6Rk3PLRK+b8L/M6m/x6Mfj60LhAUcLJ34oPaxufA+CfqkUrDoUPQYFdRrhqyOvtOKXLJZJwxlOLbQjNYQcRQfw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.6.tgz", + "integrity": "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==", "cpu": [ "x64" ], @@ -3153,9 +3154,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.4.tgz", - "integrity": "sha512-kmT3x0IPRuXY/tNoABp2nDvI9EvdiS2JZsd4I9yOcLCCViKsP0gB38mVHOhluzx+SSVnM1KNn9k6osyXZhLoCA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.6.tgz", + "integrity": "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==", "cpu": [ "arm" ], @@ -3167,9 +3168,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.4.tgz", - "integrity": "sha512-3iSA9tx+4PZcJH/Wnwsvx/BY4qHpit/u2YoZoXugWVfc36/4mRkgGEoRbRV7nzNBSCOgbWMeuQ27IQWgJ7tRzw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.6.tgz", + "integrity": "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==", "cpu": [ "arm" ], @@ -3181,9 +3182,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.4.tgz", - "integrity": "sha512-7CwSJW+sEhM9sESEk+pEREF2JL0BmyCro8UyTq0Kyh0nu1v0QPNY3yfLPFKChzVoUmaKj8zbdgBxUhBRR+xGxg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.6.tgz", + "integrity": "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==", "cpu": [ "arm64" ], @@ -3195,9 +3196,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.4.tgz", - "integrity": "sha512-GZdafB41/4s12j8Ss2izofjeFXRAAM7sHCb+S4JsI9vaONX/zQ8cXd87B9MRU/igGAJkKvmFmJJBeeT9jJ5Cbw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.6.tgz", + "integrity": "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==", "cpu": [ "arm64" ], @@ -3209,9 +3210,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.4.tgz", - "integrity": "sha512-uuphLuw1X6ur11675c2twC6YxbzyLSpWggvdawTUamlsoUv81aAXRMPBC1uvQllnBGls0Qt5Siw8reSIBnbdqQ==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.6.tgz", + "integrity": "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==", "cpu": [ "loong64" ], @@ -3223,9 +3224,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.4.tgz", - "integrity": "sha512-KvLEw1os2gSmD6k6QPCQMm2T9P2GYvsMZMRpMz78QpSoEevHbV/KOUbI/46/JRalhtSAYZBYLAnT9YE4i/l4vg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.6.tgz", + "integrity": "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==", "cpu": [ "ppc64" ], @@ -3237,9 +3238,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.4.tgz", - "integrity": "sha512-wcpCLHGM9yv+3Dql/CI4zrY2mpQ4WFergD3c9cpRowltEh5I84pRT/EuHZsG0In4eBPPYthXnuR++HrFkeqwkA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.6.tgz", + "integrity": "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==", "cpu": [ "riscv64" ], @@ -3251,9 +3252,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.4.tgz", - "integrity": "sha512-nLbfQp2lbJYU8obhRQusXKbuiqm4jSJteLwfjnunDT5ugBKdxqw1X9KWwk8xp1OMC6P5d0WbzxzhWoznuVK6XA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.6.tgz", + "integrity": "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==", "cpu": [ "s390x" ], @@ -3265,9 +3266,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.4.tgz", - "integrity": "sha512-JGejzEfVzqc/XNiCKZj14eb6s5w8DdWlnQ5tWUbs99kkdvfq9btxxVX97AaxiUX7xJTKFA0LwoS0KU8C2faZRg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.6.tgz", + "integrity": "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==", "cpu": [ "x64" ], @@ -3279,9 +3280,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.4.tgz", - "integrity": "sha512-/iFIbhzeyZZy49ozAWJ1ZR2KW6ZdYUbQXLT4O5n1cRZRoTpwExnHLjlurDXXPKEGxiAg0ujaR9JDYKljpr2fDg==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.6.tgz", + "integrity": "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==", "cpu": [ "x64" ], @@ -3293,9 +3294,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.4.tgz", - "integrity": "sha512-qORc3UzoD5UUTneiP2Afg5n5Ti1GAW9Gp5vHPxzvAFFA3FBaum9WqGvYXGf+c7beFdOKNos31/41PRMUwh1tpA==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.6.tgz", + "integrity": "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==", "cpu": [ "arm64" ], @@ -3307,9 +3308,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.4.tgz", - "integrity": "sha512-5g7E2PHNK2uvoD5bASBD9aelm44nf1w4I5FEI7MPHLWcCSrR8JragXZWgKPXk5i2FU3JFfa6CGZLw2RrGBHs2Q==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.6.tgz", + "integrity": "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==", "cpu": [ "ia32" ], @@ -3321,9 +3322,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.4.tgz", - "integrity": "sha512-p0scwGkR4kZ242xLPBuhSckrJ734frz6v9xZzD+kHVYRAkSUmdSLCIJRfql6H5//aF8Q10K+i7q8DiPfZp0b7A==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.6.tgz", + "integrity": "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==", "cpu": [ "x64" ], @@ -3893,6 +3894,13 @@ "@types/node": "*" } }, + "node_modules/@types/gensync": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/gensync/-/gensync-1.0.4.tgz", + "integrity": "sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", @@ -6185,9 +6193,9 @@ } }, "node_modules/electron": { - "version": "34.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-34.1.0.tgz", - "integrity": "sha512-ZUid8XrGPA0dfes97PPADc8ecWOUX/qYRNp1glze9coZLEYc+PsMvgjVDCHSvjfHfiI+V3unwngSVpBouX71YQ==", + "version": "34.1.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-34.1.1.tgz", + "integrity": "sha512-1aDYk9Gsv1/fFeClMrxWGoVMl7uCUgl1pe26BiTnLXmAoqEXCa3f3sCKFWV+cuDzUjQGAZcpkWhGYTgWUSQrLA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -9876,9 +9884,9 @@ } }, "node_modules/rollup": { - "version": "4.34.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.4.tgz", - "integrity": "sha512-spF66xoyD7rz3o08sHP7wogp1gZ6itSq22SGa/IZTcUDXDlOyrShwMwkVSB+BUxFRZZCUYqdb3KWDEOMVQZxuw==", + "version": "4.34.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.6.tgz", + "integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9892,25 +9900,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.4", - "@rollup/rollup-android-arm64": "4.34.4", - "@rollup/rollup-darwin-arm64": "4.34.4", - "@rollup/rollup-darwin-x64": "4.34.4", - "@rollup/rollup-freebsd-arm64": "4.34.4", - "@rollup/rollup-freebsd-x64": "4.34.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.4", - "@rollup/rollup-linux-arm-musleabihf": "4.34.4", - "@rollup/rollup-linux-arm64-gnu": "4.34.4", - "@rollup/rollup-linux-arm64-musl": "4.34.4", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.4", - "@rollup/rollup-linux-riscv64-gnu": "4.34.4", - "@rollup/rollup-linux-s390x-gnu": "4.34.4", - "@rollup/rollup-linux-x64-gnu": "4.34.4", - "@rollup/rollup-linux-x64-musl": "4.34.4", - "@rollup/rollup-win32-arm64-msvc": "4.34.4", - "@rollup/rollup-win32-ia32-msvc": "4.34.4", - "@rollup/rollup-win32-x64-msvc": "4.34.4", + "@rollup/rollup-android-arm-eabi": "4.34.6", + "@rollup/rollup-android-arm64": "4.34.6", + "@rollup/rollup-darwin-arm64": "4.34.6", + "@rollup/rollup-darwin-x64": "4.34.6", + "@rollup/rollup-freebsd-arm64": "4.34.6", + "@rollup/rollup-freebsd-x64": "4.34.6", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.6", + "@rollup/rollup-linux-arm-musleabihf": "4.34.6", + "@rollup/rollup-linux-arm64-gnu": "4.34.6", + "@rollup/rollup-linux-arm64-musl": "4.34.6", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.6", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.6", + "@rollup/rollup-linux-riscv64-gnu": "4.34.6", + "@rollup/rollup-linux-s390x-gnu": "4.34.6", + "@rollup/rollup-linux-x64-gnu": "4.34.6", + "@rollup/rollup-linux-x64-musl": "4.34.6", + "@rollup/rollup-win32-arm64-msvc": "4.34.6", + "@rollup/rollup-win32-ia32-msvc": "4.34.6", + "@rollup/rollup-win32-x64-msvc": "4.34.6", "fsevents": "~2.3.2" } }, diff --git a/package.json b/package.json index ffc6614a..a276870e 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "xhr2": "0.2.1" }, "devDependencies": { - "@babel/core": "7.26.7", + "@babel/core": "7.26.8", "@electron/packager": "18.3.6", "@material/mwc-button": "0.27.0", "@material/mwc-checkbox": "0.27.0", @@ -128,7 +128,7 @@ "@vaadin/tooltip": "24.2.9", "@zip.js/zip.js": "2.7.57", "axios": "1.7.9", - "electron": "34.1.0", + "electron": "34.1.1", "electron-builder": "25.1.8", "epml": "0.3.3", "file-saver": "2.0.5", @@ -140,7 +140,7 @@ "pwa-helpers": "0.9.1", "redux": "5.0.1", "redux-thunk": "3.1.0", - "rollup": "4.34.4", + "rollup": "4.34.6", "rollup-plugin-node-globals": "1.4.0", "rollup-plugin-progress": "1.1.2", "rollup-plugin-scss": "3.0.0", From 137dc4d0b3fa513847f085eb7612a9cdea72e8b0 Mon Sep 17 00:00:00 2001 From: AlphaX-Qortal Date: Mon, 10 Feb 2025 16:37:01 +0100 Subject: [PATCH 3/8] Fix key icon --- .../plugins/core/components/ChatScroller.js | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/plugins/plugins/core/components/ChatScroller.js b/plugins/plugins/core/components/ChatScroller.js index 42b803e8..4d10a4a7 100644 --- a/plugins/plugins/core/components/ChatScroller.js +++ b/plugins/plugins/core/components/ChatScroller.js @@ -1250,17 +1250,9 @@ class MessageTemplate extends LitElement { ` - fromHubOk = html` -

- key   -
- ` + fromHubOk = html`   key   ` - fromHubNo = html` -
- key_off   -
- ` + fromHubNo = html`   key_off   ` if (repliedToData) { try { @@ -1678,26 +1670,38 @@ class MessageTemplate extends LitElement { ${this.isInProgress ? html`

${translate('chatpage.cchange91')}

` : this.isAgo ? html` - ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`} -
- - - +
+
+ ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`} +
+
+ + + +
` : this.isIso ? html` - ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`} -
- - ${new Date(this.messageObj.timestamp).toLocaleString()} - +
+
+ ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`} +
+
+ + ${new Date(this.messageObj.timestamp).toLocaleString()} + +
` : this.isBoth ? html` - ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`} -
- - ${new Date(this.messageObj.timestamp).toLocaleString()} - ( ) - +
+
+ ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`} +
+
+ + ${new Date(this.messageObj.timestamp).toLocaleString()} + ( ) + +
` : '' } From d915b25b47274ff96849b4d49ad6d4b9c47f402e Mon Sep 17 00:00:00 2001 From: AlphaX-Qortal Date: Tue, 11 Feb 2025 20:29:22 +0100 Subject: [PATCH 4/8] Various updates - Add display private messages from Qortal-Hub - Re-add accidentally deleted qortal request SAVE_FILE - Reworked decoding Qortal-Hub messages - Update languages files --- core/language/de.json | 3 +- core/language/es.json | 3 +- core/language/et.json | 3 +- core/language/fi.json | 3 +- core/language/fr.json | 3 +- core/language/hindi.json | 3 +- core/language/hr.json | 3 +- core/language/hu.json | 3 +- core/language/it.json | 3 +- core/language/jp.json | 3 +- core/language/ko.json | 3 +- core/language/nl.json | 3 +- core/language/no.json | 3 +- core/language/pl.json | 3 +- core/language/pt.json | 3 +- core/language/ro.json | 3 +- core/language/rs.json | 3 +- core/language/ru.json | 3 +- core/language/us.json | 3 +- core/language/zhc.json | 3 +- core/language/zht.json | 3 +- crypto/api/deps/Base64Message.js | 87 ++++++--------- .../plugins/core/components/ChatScroller.js | 27 +++-- .../plugins/core/components/plugins-css.js | 20 +++- .../core/components/qdn-action-constants.js | 6 +- .../components/webworkerDecodeMessages.js | 87 ++++++--------- plugins/plugins/core/q-chat/q-chat.src.js | 4 +- .../plugins/core/qdn/browser/browser.src.js | 104 +++++++++++++++++- 28 files changed, 242 insertions(+), 156 deletions(-) diff --git a/core/language/de.json b/core/language/de.json index dacd55c6..1885f833 100644 --- a/core/language/de.json +++ b/core/language/de.json @@ -1417,6 +1417,7 @@ "mpchange83": "ABGELEHNT", "mpchange84": "FEHLER", "mpchange85": "ERFOLGREICH", - "mpchange86": "Immer automatisches Abrufen des Wallet-Guthabens zulassen" + "mpchange86": "Immer automatisches Abrufen des Wallet-Guthabens zulassen", + "mpchange87": "Bitte geben Sie die Gruppen-ID ein" } } diff --git a/core/language/es.json b/core/language/es.json index af48f747..a7924a9b 100644 --- a/core/language/es.json +++ b/core/language/es.json @@ -1417,6 +1417,7 @@ "mpchange83": "RECHAZADO", "mpchange84": "ERROR", "mpchange85": "ÉXITO", - "mpchange86": "Permitir siempre obtener el saldo de la billetera automáticamente" + "mpchange86": "Permitir siempre obtener el saldo de la billetera automáticamente", + "mpchange87": "Por favor, introduzca el ID del grupo" } } diff --git a/core/language/et.json b/core/language/et.json index 86b12aa6..73beeeeb 100644 --- a/core/language/et.json +++ b/core/language/et.json @@ -1417,6 +1417,7 @@ "mpchange83": "DECLINED", "mpchange84": "FAILURE", "mpchange85": "EDU", - "mpchange86": "Luba alati rahakoti saldo automaatne hankimine" + "mpchange86": "Luba alati rahakoti saldo automaatne hankimine", + "mpchange87": "Palun sisestage grupi ID" } } diff --git a/core/language/fi.json b/core/language/fi.json index b112ce0b..2602e3d0 100644 --- a/core/language/fi.json +++ b/core/language/fi.json @@ -1417,6 +1417,7 @@ "mpchange83": "hylätty", "mpchange84": "FAILURE", "mpchange85": "SUCCESS", - "mpchange86": "Salli aina saada lompakon saldo automaattisesti" + "mpchange86": "Salli aina saada lompakon saldo automaattisesti", + "mpchange87": "Anna ryhmän tunnus" } } diff --git a/core/language/fr.json b/core/language/fr.json index 230082c3..d469ac46 100644 --- a/core/language/fr.json +++ b/core/language/fr.json @@ -1417,6 +1417,7 @@ "mpchange83": "REFUSÉ", "mpchange84": "ÉCHEC", "mpchange85": "SUCCÈS", - "mpchange86": "Toujours autoriser l'obtention automatique du solde du portefeuille" + "mpchange86": "Toujours autoriser l'obtention automatique du solde du portefeuille", + "mpchange87": "Veuillez saisir l'ID du groupe" } } diff --git a/core/language/hindi.json b/core/language/hindi.json index b0a5d56a..260f227c 100644 --- a/core/language/hindi.json +++ b/core/language/hindi.json @@ -1417,6 +1417,7 @@ "mpchange83": "अस्वीकृत", "mpchange84": "विफल", "mpchange85": "सफल", - "mpchange86": "हमेशा वॉलेट बैलेंस को स्वचालित रूप से प्राप्त करने की अनुमति दें" + "mpchange86": "हमेशा वॉलेट बैलेंस को स्वचालित रूप से प्राप्त करने की अनुमति दें", + "mpchange87": "कृपया ग्रुप आईडी दर्ज करें" } } diff --git a/core/language/hr.json b/core/language/hr.json index a250954b..4255c9e5 100644 --- a/core/language/hr.json +++ b/core/language/hr.json @@ -1417,6 +1417,7 @@ "mpchange83": "ODBIJENO", "mpchange84": "GREŠKA", "mpchange85": "USPJEH", - "mpchange86": "Uvijek dopusti automatsko dobivanje stanja novčanika" + "mpchange86": "Uvijek dopusti automatsko dobivanje stanja novčanika", + "mpchange87": "Molimo unesite ID grupe" } } diff --git a/core/language/hu.json b/core/language/hu.json index e160715b..638e73de 100644 --- a/core/language/hu.json +++ b/core/language/hu.json @@ -1417,6 +1417,7 @@ "mpchange83": "Elutasítva", "mpchange84": "FAILURE", "mpchange85": "SIKER", - "mpchange86": "Mindig engedélyezze a pénztárcaegyenleg automatikus lekérését" + "mpchange86": "Mindig engedélyezze a pénztárcaegyenleg automatikus lekérését", + "mpchange87": "Kérjük, adja meg a csoport azonosítóját" } } diff --git a/core/language/it.json b/core/language/it.json index 1151d6db..ad818b9c 100644 --- a/core/language/it.json +++ b/core/language/it.json @@ -1417,6 +1417,7 @@ "mpchange83": "RIFIUTATO", "mpchange84": "FALLITO", "mpchange85": "RIUSCITO", - "mpchange86": "Consenti sempre di ottenere automaticamente il saldo del portafoglio" + "mpchange86": "Consenti sempre di ottenere automaticamente il saldo del portafoglio", + "mpchange87": "Inserisci l'ID del gruppo" } } diff --git a/core/language/jp.json b/core/language/jp.json index c78bea3f..11194383 100644 --- a/core/language/jp.json +++ b/core/language/jp.json @@ -1417,6 +1417,7 @@ "mpchange83": "拒否されました", "mpchange84": "失敗", "mpchange85": "成功", - "mpchange86": "ウォレット残高の自動取得を常に許可する" + "mpchange86": "ウォレット残高の自動取得を常に許可する", + "mpchange87": "グループ ID を入力してください" } } diff --git a/core/language/ko.json b/core/language/ko.json index 6d2569db..109b8a8c 100644 --- a/core/language/ko.json +++ b/core/language/ko.json @@ -1417,6 +1417,7 @@ "mpchange83": "거부됨", "mpchange84": "실패", "mpchange85": "성공", - "mpchange86": "항상 지갑 잔액을 자동으로 가져오도록 허용" + "mpchange86": "항상 지갑 잔액을 자동으로 가져오도록 허용", + "mpchange87": "그룹 ID를 입력하세요" } } diff --git a/core/language/nl.json b/core/language/nl.json index 5606d115..092016cd 100644 --- a/core/language/nl.json +++ b/core/language/nl.json @@ -1417,6 +1417,7 @@ "mpchange83": "GEWEIGERD", "mpchange84": "MISLUKT", "mpchange85": "SUCCES", - "mpchange86": "Altijd toestaan ​​om automatisch saldo in portemonnee op te halen" + "mpchange86": "Altijd toestaan ​​om automatisch saldo in portemonnee op te halen", + "mpchange87": "Voer de groeps-ID in" } } diff --git a/core/language/no.json b/core/language/no.json index 75004ffc..6108dff5 100644 --- a/core/language/no.json +++ b/core/language/no.json @@ -1417,6 +1417,7 @@ "mpchange83": "AVSLAGT", "mpchange84": "FEIL", "mpchange85": "SUKSESS", - "mpchange86": "Tillat alltid få lommeboksaldo automatisk" + "mpchange86": "Tillat alltid få lommeboksaldo automatisk", + "mpchange87": "Vennligst skriv inn gruppe-ID" } } diff --git a/core/language/pl.json b/core/language/pl.json index 9c2a84ba..6a2fad25 100644 --- a/core/language/pl.json +++ b/core/language/pl.json @@ -1417,6 +1417,7 @@ "mpchange83": "ODRZUCONE", "mpchange84": "NIEPOWODZENIE", "mpchange85": "POWODZENIE", - "mpchange86": "Zawsze zezwalaj na automatyczne pobieranie salda portfela" + "mpchange86": "Zawsze zezwalaj na automatyczne pobieranie salda portfela", + "mpchange87": "Wprowadź identyfikator grupy" } } diff --git a/core/language/pt.json b/core/language/pt.json index 4b7c9657..255b1193 100644 --- a/core/language/pt.json +++ b/core/language/pt.json @@ -1417,6 +1417,7 @@ "mpchange83": "RECLINADO", "mpchange84": "FALHA", "mpchange85": "SUCESSO", - "mpchange86": "Permitir sempre obter saldo da carteira automaticamente" + "mpchange86": "Permitir sempre obter saldo da carteira automaticamente", + "mpchange87": "Por favor introduza o ID do grupo" } } diff --git a/core/language/ro.json b/core/language/ro.json index 5d2d41f6..2df1152f 100644 --- a/core/language/ro.json +++ b/core/language/ro.json @@ -1417,6 +1417,7 @@ "mpchange83": "RESFUS", "mpchange84": "Eșec", "mpchange85": "SUCCES", - "mpchange86": "Permiteți întotdeauna obținerea automată a soldului portofelului" + "mpchange86": "Permiteți întotdeauna obținerea automată a soldului portofelului", + "mpchange87": "Vă rugăm să introduceți ID-ul grupului" } } diff --git a/core/language/rs.json b/core/language/rs.json index d1bf2ba7..bc58e4d9 100644 --- a/core/language/rs.json +++ b/core/language/rs.json @@ -1417,6 +1417,7 @@ "mpchange83": "ODBIJENO", "mpchange84": "GREŠKA", "mpchange85": "USPEH", - "mpchange86": "Uvek dozvoli automatsko dobijanje stanja novčanika" + "mpchange86": "Uvek dozvoli automatsko dobijanje stanja novčanika", + "mpchange87": "Unesite ID grupe" } } diff --git a/core/language/ru.json b/core/language/ru.json index f95411ae..00c7e278 100644 --- a/core/language/ru.json +++ b/core/language/ru.json @@ -1417,6 +1417,7 @@ "mpchange83": "ОТКЛОНЕНО", "mpchange84": "НЕУДАЧА", "mpchange85": "УСПЕШНО", - "mpchange86": "Всегда разрешать автоматически получать баланс кошелька" + "mpchange86": "Всегда разрешать автоматически получать баланс кошелька", + "mpchange87": "Пожалуйста, введите идентификатор группы" } } diff --git a/core/language/us.json b/core/language/us.json index 8f619c65..be7d6b2e 100644 --- a/core/language/us.json +++ b/core/language/us.json @@ -1417,6 +1417,7 @@ "mpchange83": "DECLINED", "mpchange84": "FAILURE", "mpchange85": "SUCCESS", - "mpchange86": "Always allow get wallet balance automatically" + "mpchange86": "Always allow get wallet balance automatically", + "mpchange87": "Please Enter The Group ID" } } diff --git a/core/language/zhc.json b/core/language/zhc.json index 1bacf2e5..455e4d03 100644 --- a/core/language/zhc.json +++ b/core/language/zhc.json @@ -1417,6 +1417,7 @@ "mpchange83": "拒绝", "mpchange84": "失败", "mpchange85": "成功", - "mpchange86": "始终允许自动获取钱包余额" + "mpchange86": "始终允许自动获取钱包余额", + "mpchange87": "请输入群组ID" } } diff --git a/core/language/zht.json b/core/language/zht.json index 65adf665..96c3b989 100644 --- a/core/language/zht.json +++ b/core/language/zht.json @@ -1417,6 +1417,7 @@ "mpchange83": "拒絕", "mpchange84": "失敗", "mpchange85": "成功", - "mpchange86": "隨時允許自動取得錢包餘額" + "mpchange86": "隨時允許自動取得錢包餘額", + "mpchange87": "請輸入群組 ID" } } diff --git a/crypto/api/deps/Base64Message.js b/crypto/api/deps/Base64Message.js index f74c282f..bd6adef0 100644 --- a/crypto/api/deps/Base64Message.js +++ b/crypto/api/deps/Base64Message.js @@ -14,6 +14,15 @@ import { const Base64Message = {} Base64Message.decode = function (string, keys, ref) { + let repliedToStr = '' + let hubSpecialId = '' + let hubMessageStr = '' + let newMessageObject = '' + let messageUseEmbed = {} + let isHubReaction = false + let editStr = false + let embedFileStr = '"images":[""]' + const binaryString = atob(string) const binaryLength = binaryString.length const bytes = new Uint8Array(binaryLength) @@ -34,88 +43,54 @@ Base64Message.decode = function (string, keys, ref) { return decodedString } } else { - let repliedToStr = '' - let addedFileStr = '' - let messageStr = '' - let hubString = '' - let messageRep = '' - let messageUseEmbed = {} - const res = decryptSingle(string, keys, false) if (res === 'noKey' || res === 'decryptionFailed') { - return '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This message could not be decrypted"}]}]}' + addedFileStr + ',"repliedTo":"","version":3,"isFromHub":true}' + return '{"specialId":"","message":"

This message could not be decrypted

","repliedTo":"","isEdited":false,"isFromHub":true,"isReaction":false,"version": 3}' } const decryptToUnit8Array = base64ToUint8Array(res) const responseData = uint8ArrayToObject(decryptToUnit8Array) if (responseData.type === "notification") { - const messageStrRaw = responseData.data.message - messageStr = messageStrRaw.trim() + hubMessageStr = responseData.data.message } if (ref !== "noref") { if (responseData.type === "reaction") { + isHubReaction = true repliedToStr = ref - messageStr = responseData.content + hubMessageStr = responseData.content } } - if (responseData.hasOwnProperty('message') && typeof responseData['message'] === 'string' && responseData['message'].length) { - if (responseData.message.includes('qortal://use-embed/')) { - const useEmbed1 = extensionToPointer(responseData.message) - const useEmbed2 = /(.*?)<\/newpointer>/g.exec(useEmbed1) - const useEmbed3 = encodedToChar(useEmbed2[1]) - - messageUseEmbed = parseQortalLink(useEmbed3) - addedFileStr = embedToString(messageUseEmbed) - - const useEmbed4 = responseData.message.split(useEmbed2[1]).join('') - - if (useEmbed4 === "

") { - messageRep = useEmbed4.split('

').join('

Qortal-Hub embed link

') - } else { - messageRep = useEmbed4 - } - } else { - messageRep = responseData.message - addedFileStr = ',"images":[""]' - } - - const messageRep1 = messageRep.split('"').join('') - const messageRep2 = messageRep1.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep3 = messageRep2.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep4 = messageRep3.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep5 = messageRep4.replace('

', '') - const messageRep6 = messageRep5.replace('

', '') - const messageRep7 = messageRep6.replace('

', '') - const messageRep8 = messageRep7.replace('

', '') - const messageRep9 = messageRep8.replace('

', '') - const messageRep10 = messageRep9.trim() - const messageRep11 = messageRep10.split('



').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep12 = messageRep11.split('


').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep13 = messageRep12.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep14 = messageRep13.split('
').join('"},{"type":"hardBreak"},{"type":"text","text":"') - messageStr = messageRep14 + if (responseData.type === "edit") { + editStr = true } if (responseData.repliedTo) { repliedToStr = responseData.repliedTo } - if (responseData.type === "edit") { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isEdited":true,"isFromHub":true}' - } else if (responseData.type === "reaction") { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isReaction":true,"isFromHub":true}' - } else { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isFromHub":true}' + if (responseData.specialId) { + hubSpecialId = responseData.specialId } - const preparedString = hubString.split('').join('\\"') - const finalString = preparedString.replace(/<\/?[^>]+(>|$)/g, '') + if (responseData.message.includes('qortal://use-embed/')) { + const useEmbed1 = extensionToPointer(responseData.message) + const useEmbed2 = /(.*?)<\/newpointer>/g.exec(useEmbed1) + const useEmbed3 = encodedToChar(useEmbed2[1]) - return finalString + messageUseEmbed = parseQortalLink(useEmbed3) + embedFileStr = embedToString(messageUseEmbed) + hubMessageStr = responseData.message.split(useEmbed2[1]).join('') + } else { + hubMessageStr = responseData.message + } + + newMessageObject = '{"specialId":"' + hubSpecialId + '","message":"' + hubMessageStr + '",' + embedFileStr + ',"repliedTo":"' + repliedToStr + '","isEdited":' + editStr + ',"isFromHub":true,"isReaction":' + isHubReaction + ',"version": 3}' + + return newMessageObject } } diff --git a/plugins/plugins/core/components/ChatScroller.js b/plugins/plugins/core/components/ChatScroller.js index 4d10a4a7..7438e0e3 100644 --- a/plugins/plugins/core/components/ChatScroller.js +++ b/plugins/plugins/core/components/ChatScroller.js @@ -1081,17 +1081,22 @@ class MessageTemplate extends LitElement { let version = 0 let isForwarded = false let isEdited = false - let isFromHub = false + let isEncrypted = false try { const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage) - if (+parsedMessageObj.version > 1 && parsedMessageObj.messageText) { + if (parsedMessageObj.version > 1 && parsedMessageObj.messageText) { messageVersion2 = generateHTML(parsedMessageObj.messageText, [StarterKit, Underline, Highlight, Mention]) messageVersion2WithLink = processText(messageVersion2) } - message = parsedMessageObj.messageText + if (parsedMessageObj.version > 1 && parsedMessageObj.message) { + messageVersion2 = parsedMessageObj.message + messageVersion2WithLink = processText(messageVersion2) + } + + message = parsedMessageObj.messageText ? parsedMessageObj.messageText : parsedMessageObj.message repliedToData = this.messageObj.repliedToData isImageDeleted = parsedMessageObj.isImageDeleted isGifDeleted = parsedMessageObj.isGifDeleted @@ -1101,7 +1106,7 @@ class MessageTemplate extends LitElement { version = parsedMessageObj.version isForwarded = parsedMessageObj.type === 'forward' isEdited = parsedMessageObj.isEdited && true - isFromHub = parsedMessageObj.isFromHub && true + isEncrypted = parsedMessageObj.isFromHub || parsedMessageObj.message ? true : false if (parsedMessageObj.images && Array.isArray(parsedMessageObj.images) && parsedMessageObj.images.length > 0) { image = parsedMessageObj.images[0] @@ -1133,8 +1138,8 @@ class MessageTemplate extends LitElement { let hideit = hidemsg.includes(this.messageObj.sender) let forwarded = '' let edited = '' - let fromHubOk = '' - let fromHubNo = '' + let encrypted = '' + let decrypted = '' levelFounder = html`` @@ -1250,9 +1255,9 @@ class MessageTemplate extends LitElement { ` - fromHubOk = html`   key   ` + encrypted = html`   key   ` - fromHubNo = html`   key_off   ` + decrypted = html`   key_off   ` if (repliedToData) { try { @@ -1672,7 +1677,7 @@ class MessageTemplate extends LitElement { ` : this.isAgo ? html`
- ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`} + ${isEncrypted ? html`${encrypted}` : html`${decrypted}`}
@@ -1683,7 +1688,7 @@ class MessageTemplate extends LitElement { ` : this.isIso ? html`
- ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`} + ${isEncrypted ? html`${encrypted}` : html`${decrypted}`}
@@ -1694,7 +1699,7 @@ class MessageTemplate extends LitElement { ` : this.isBoth ? html`
- ${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`} + ${isEncrypted ? html`${encrypted}` : html`${decrypted}`}
diff --git a/plugins/plugins/core/components/plugins-css.js b/plugins/plugins/core/components/plugins-css.js index c616dba5..cc782eb5 100644 --- a/plugins/plugins/core/components/plugins-css.js +++ b/plugins/plugins/core/components/plugins-css.js @@ -2014,8 +2014,13 @@ export const chatStyles = css` } #messageContent code { - background-color: rgba(#616161, 0.1); - color: #616161; + background: #0D0D0D; + color: #FFF; + font-family: 'JetBrainsMono', monospace; + padding: 0.75rem 1rem; + border-radius: 0.5rem; + white-space: pre-wrap; + margin-top: 10px; } #messageContent pre { @@ -2034,12 +2039,10 @@ export const chatStyles = css` font-size: 0.8rem; } - #messageContent img { width: 1.7em; height: 1.5em; margin: 0px; - } #messageContent blockquote { @@ -2078,8 +2081,13 @@ export const chatStyles = css` } .replied-message code { - background-color: rgba(#616161, 0.1); - color: #616161; + background: #0D0D0D; + color: #FFF; + font-family: 'JetBrainsMono', monospace; + padding: 0.75rem 1rem; + border-radius: 0.5rem; + white-space: pre-wrap; + margin: 0px; } .replied-message pre { diff --git a/plugins/plugins/core/components/qdn-action-constants.js b/plugins/plugins/core/components/qdn-action-constants.js index 5f311f53..498388a8 100644 --- a/plugins/plugins/core/components/qdn-action-constants.js +++ b/plugins/plugins/core/components/qdn-action-constants.js @@ -159,15 +159,15 @@ export const embedToString = (embed) => { embedService = embed.service embedName = embed.name embedIdentifier = embed.identifier - embedString = ',"images":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '"}],"isImageDeleted":false' + embedString = '"images":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '"}],"isImageDeleted":false' } else if (embed.type === "ATTACHMENT") { embedService = embed.service embedName = embed.name embedIdentifier = embed.identifier embedAttachmentName = embed.fileName - embedString = ',"attachments":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '","attachmentName":"' + embedAttachmentName + '","attachmentSize":0}],"isAttachmentDeleted":false' + embedString = '"attachments":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '","attachmentName":"' + embedAttachmentName + '","attachmentSize":0}],"isAttachmentDeleted":false' } else { - embedString = ',"images":[""]' + embedString = '"images":[""]' } return embedString diff --git a/plugins/plugins/core/components/webworkerDecodeMessages.js b/plugins/plugins/core/components/webworkerDecodeMessages.js index 7c37cad7..14717e7a 100644 --- a/plugins/plugins/core/components/webworkerDecodeMessages.js +++ b/plugins/plugins/core/components/webworkerDecodeMessages.js @@ -2767,6 +2767,15 @@ self.addEventListener('message', async (e) => { }) const decode = (string, keys, ref) => { + let repliedToStr = '' + let hubSpecialId = '' + let hubMessageStr = '' + let newMessageObject = '' + let messageUseEmbed = {} + let isHubReaction = false + let editStr = false + let embedFileStr = '"images":[""]' + const binaryString = atob(string) const binaryLength = binaryString.length const bytes = new Uint8Array(binaryLength) @@ -2787,88 +2796,54 @@ const decode = (string, keys, ref) => { return decodedString } } else { - let repliedToStr = '' - let addedFileStr = '' - let messageStr = '' - let hubString = '' - let messageRep = '' - let messageUseEmbed = {} - const res = decryptSingle(string, keys, false) if (res === 'noKey' || res === 'decryptionFailed') { - return '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This message could not be decrypted"}]}]}' + addedFileStr + ',"repliedTo":"","version":3,"isFromHub":true}' + return '{"specialId":"","message":"

This message could not be decrypted

","repliedTo":"","isEdited":false,"isFromHub":true,"isReaction":false,"version": 3}' } const decryptToUnit8Array = base64ToUint8Array(res) const responseData = uint8ArrayToObject(decryptToUnit8Array) if (responseData.type === "notification") { - const messageStrRaw = responseData.data.message - messageStr = messageStrRaw.trim() + hubMessageStr = responseData.data.message } if (ref !== "noref") { if (responseData.type === "reaction") { + isHubReaction = true repliedToStr = ref - messageStr = responseData.content + hubMessageStr = responseData.content } } - if (responseData.hasOwnProperty('message') && typeof responseData['message'] === 'string' && responseData['message'].length) { - if (responseData.message.includes('qortal://use-embed/')) { - const useEmbed1 = extensionToPointer(responseData.message) - const useEmbed2 = /(.*?)<\/newpointer>/g.exec(useEmbed1) - const useEmbed3 = encodedToChar(useEmbed2[1]) - - messageUseEmbed = parseQortalLink(useEmbed3) - addedFileStr = embedToString(messageUseEmbed) - - const useEmbed4 = responseData.message.split(useEmbed2[1]).join('') - - if (useEmbed4 === "

") { - messageRep = useEmbed4.split('

').join('

Qortal-Hub embed link

') - } else { - messageRep = useEmbed4 - } - } else { - messageRep = responseData.message - addedFileStr = ',"images":[""]' - } - - const messageRep1 = messageRep.split('"').join('') - const messageRep2 = messageRep1.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep3 = messageRep2.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep4 = messageRep3.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep5 = messageRep4.replace('

', '') - const messageRep6 = messageRep5.replace('

', '') - const messageRep7 = messageRep6.replace('

', '') - const messageRep8 = messageRep7.replace('

', '') - const messageRep9 = messageRep8.replace('

', '') - const messageRep10 = messageRep9.trim() - const messageRep11 = messageRep10.split('



').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep12 = messageRep11.split('


').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep13 = messageRep12.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageRep14 = messageRep13.split('
').join('"},{"type":"hardBreak"},{"type":"text","text":"') - messageStr = messageRep14 + if (responseData.type === "edit") { + editStr = true } if (responseData.repliedTo) { repliedToStr = responseData.repliedTo } - if (responseData.type === "edit") { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isEdited":true,"isFromHub":true}' - } else if (responseData.type === "reaction") { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isReaction":true,"isFromHub":true}' - } else { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isFromHub":true}' + if (responseData.specialId) { + hubSpecialId = responseData.specialId } - const preparedString = hubString.split('').join('\\"') - const finalString = preparedString.replace(/<\/?[^>]+(>|$)/g, '') + if (responseData.message.includes('qortal://use-embed/')) { + const useEmbed1 = extensionToPointer(responseData.message) + const useEmbed2 = /(.*?)<\/newpointer>/g.exec(useEmbed1) + const useEmbed3 = encodedToChar(useEmbed2[1]) - return finalString + messageUseEmbed = parseQortalLink(useEmbed3) + embedFileStr = embedToString(messageUseEmbed) + hubMessageStr = responseData.message.split(useEmbed2[1]).join('') + } else { + hubMessageStr = responseData.message + } + + newMessageObject = '{"specialId":"' + hubSpecialId + '","message":"' + hubMessageStr + '",' + embedFileStr + ',"repliedTo":"' + repliedToStr + '","isEdited":' + editStr + ',"isFromHub":true,"isReaction":' + isHubReaction + ',"version": 3}' + + return newMessageObject } } diff --git a/plugins/plugins/core/q-chat/q-chat.src.js b/plugins/plugins/core/q-chat/q-chat.src.js index 37dc4b2c..bb99d469 100644 --- a/plugins/plugins/core/q-chat/q-chat.src.js +++ b/plugins/plugins/core/q-chat/q-chat.src.js @@ -317,7 +317,7 @@ class Chat extends LitElement {
-

Please Enter The Group ID

+

${translate("modals.mpchange87")}



@@ -326,7 +326,7 @@ class Chat extends LitElement { style="width: 100%;" required id="groupIdInput" - label="Emter Group ID" + label="${translate("managegroup.mg8")}" type="number" auto-validate="false" value="" diff --git a/plugins/plugins/core/qdn/browser/browser.src.js b/plugins/plugins/core/qdn/browser/browser.src.js index c49dbbb5..d3172925 100644 --- a/plugins/plugins/core/qdn/browser/browser.src.js +++ b/plugins/plugins/core/qdn/browser/browser.src.js @@ -17,7 +17,7 @@ import { } from '../../../utils/classes' import {appendBuffer} from '../../../utils/utilities' import {QORT_DECIMALS} from '../../../../../crypto/api/constants' -import {listOfAllQortalRequests} from '../../components/qdn-action-constants' +import {mimeToExtensionMap, listOfAllQortalRequests} from '../../components/qdn-action-constants' import { createSymmetricKeyAndNonce, decryptGroupEncryptionWithSharingKey, @@ -2252,6 +2252,108 @@ class WebBrowser extends LitElement { } break + case actions.SAVE_FILE: { + try { + const requiredFields = ['filename', 'blob'] + const missingFields = [] + let dataSentBack = {} + requiredFields.forEach((field) => { + if (!data[field]) { + missingFields.push(field) + } + }) + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(', ') + const tryAgain = get("walletpage.wchange44") + await showErrorAndWait( + "MISSING_FIELDS", + { + id1: missingFieldsString, + id2: tryAgain + } + ) + dataSentBack['error'] = `Missing fields: ${missingFieldsString}` + response = JSON.stringify(dataSentBack) + break + } + const filename = data.filename + const blob = data.blob + const res = await showModalAndWait( + actions.SAVE_FILE, + { + filename + } + ) + if (res.action === 'reject') { + let myMsg1 = get("transactions.declined") + let myMsg2 = get("walletpage.wchange44") + await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 }) + response = '{"error": "User declined request"}' + break + } + const mimeType = blob.type || data.mimeType + let backupExention = filename.split('.').pop() + if (backupExention) { + backupExention = '.' + backupExention + } + const fileExtension = mimeToExtensionMap[mimeType] || backupExention + let fileHandleOptions = {} + if (!mimeType) { + const obj = {} + obj['error'] = 'A mimeType could not be derived' + response = JSON.stringify(obj) + break + } + if (!fileExtension) { + const obj = {} + obj['error'] = 'A file extension could not be derived' + response = JSON.stringify(obj) + break + } + if (fileExtension && mimeType) { + fileHandleOptions = { + accept: { + [mimeType]: [fileExtension] + } + } + } + try { + const fileHandle = await self.showSaveFilePicker({ + suggestedName: filename, + types: [ + { + description: mimeType, + ...fileHandleOptions + } + ] + }) + const writeFile = async (fileHandle, contents) => { + const writable = await fileHandle.createWritable() + await writable.write(contents) + await writable.close() + } + writeFile(fileHandle, blob).then(() => console.log("FILE SAVED")) + } catch (error) { + if (error.name === 'AbortError') { + const obj = {} + obj['error'] = 'User declined the download' + response = JSON.stringify(obj) + break + } + FileSaver.saveAs(blob, filename) + } + response = JSON.stringify(true) + } catch (error) { + let myMsg1 = get("managegroup.mg58") + let myMsg2 = get("walletpage.wchange44") + await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 }) + const obj = {} + obj['error'] = error.message || 'Failed to initiate download' + response = JSON.stringify(obj) + } + } + break + case actions.DEPLOY_AT: { const requiredFields = ['name', 'description', 'tags', 'creationBytes', 'amount', 'assetId', 'type'] const missingFields = [] From 585d133143807aa41838f4b91d880aade4359203 Mon Sep 17 00:00:00 2001 From: AlphaX-Qortal Date: Wed, 12 Feb 2025 21:33:36 +0100 Subject: [PATCH 5/8] Fix message decoding --- crypto/api/deps/Base64Message.js | 29 +++++++---------- .../components/webworkerDecodeMessages.js | 31 ++++++++----------- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/crypto/api/deps/Base64Message.js b/crypto/api/deps/Base64Message.js index bd6adef0..c09c0551 100644 --- a/crypto/api/deps/Base64Message.js +++ b/crypto/api/deps/Base64Message.js @@ -18,8 +18,8 @@ Base64Message.decode = function (string, keys, ref) { let hubSpecialId = '' let hubMessageStr = '' let newMessageObject = '' + let reactionStr = '' let messageUseEmbed = {} - let isHubReaction = false let editStr = false let embedFileStr = '"images":[""]' @@ -46,24 +46,12 @@ Base64Message.decode = function (string, keys, ref) { const res = decryptSingle(string, keys, false) if (res === 'noKey' || res === 'decryptionFailed') { - return '{"specialId":"","message":"

This message could not be decrypted

","repliedTo":"","isEdited":false,"isFromHub":true,"isReaction":false,"version": 3}' + return '{"specialId":"","message":"

This message could not be decrypted

","repliedTo":"","isEdited":false,"isFromHub":true,"version": 3}' } const decryptToUnit8Array = base64ToUint8Array(res) const responseData = uint8ArrayToObject(decryptToUnit8Array) - if (responseData.type === "notification") { - hubMessageStr = responseData.data.message - } - - if (ref !== "noref") { - if (responseData.type === "reaction") { - isHubReaction = true - repliedToStr = ref - hubMessageStr = responseData.content - } - } - if (responseData.type === "edit") { editStr = true } @@ -76,11 +64,16 @@ Base64Message.decode = function (string, keys, ref) { hubSpecialId = responseData.specialId } - if (responseData.message.includes('qortal://use-embed/')) { + if (responseData.type === "notification") { + hubMessageStr = responseData.data.message + } else if (ref !== "noref" && responseData.type === "reaction") { + reactionStr = '"isReaction":true,' + repliedToStr = ref + hubMessageStr = responseData.content + } else if (responseData.message.includes('qortal://use-embed/')) { const useEmbed1 = extensionToPointer(responseData.message) const useEmbed2 = /(.*?)<\/newpointer>/g.exec(useEmbed1) const useEmbed3 = encodedToChar(useEmbed2[1]) - messageUseEmbed = parseQortalLink(useEmbed3) embedFileStr = embedToString(messageUseEmbed) hubMessageStr = responseData.message.split(useEmbed2[1]).join('') @@ -88,7 +81,9 @@ Base64Message.decode = function (string, keys, ref) { hubMessageStr = responseData.message } - newMessageObject = '{"specialId":"' + hubSpecialId + '","message":"' + hubMessageStr + '",' + embedFileStr + ',"repliedTo":"' + repliedToStr + '","isEdited":' + editStr + ',"isFromHub":true,"isReaction":' + isHubReaction + ',"version": 3}' + const hubMessageFinal = hubMessageStr.split('"').join('"') + + newMessageObject = '{"specialId":"' + hubSpecialId + '","message":"' + hubMessageFinal + '",' + embedFileStr + ',"repliedTo":"' + repliedToStr + '","isEdited":' + editStr + ',"isFromHub":true,' + reactionStr + '"version": 3}' return newMessageObject } diff --git a/plugins/plugins/core/components/webworkerDecodeMessages.js b/plugins/plugins/core/components/webworkerDecodeMessages.js index 14717e7a..91f20dbf 100644 --- a/plugins/plugins/core/components/webworkerDecodeMessages.js +++ b/plugins/plugins/core/components/webworkerDecodeMessages.js @@ -2771,8 +2771,8 @@ const decode = (string, keys, ref) => { let hubSpecialId = '' let hubMessageStr = '' let newMessageObject = '' + let reactionStr = '' let messageUseEmbed = {} - let isHubReaction = false let editStr = false let embedFileStr = '"images":[""]' @@ -2799,24 +2799,12 @@ const decode = (string, keys, ref) => { const res = decryptSingle(string, keys, false) if (res === 'noKey' || res === 'decryptionFailed') { - return '{"specialId":"","message":"

This message could not be decrypted

","repliedTo":"","isEdited":false,"isFromHub":true,"isReaction":false,"version": 3}' + return '{"specialId":"","message":"

This message could not be decrypted

","repliedTo":"","isEdited":false,"isFromHub":true,"version": 3}' } const decryptToUnit8Array = base64ToUint8Array(res) const responseData = uint8ArrayToObject(decryptToUnit8Array) - if (responseData.type === "notification") { - hubMessageStr = responseData.data.message - } - - if (ref !== "noref") { - if (responseData.type === "reaction") { - isHubReaction = true - repliedToStr = ref - hubMessageStr = responseData.content - } - } - if (responseData.type === "edit") { editStr = true } @@ -2829,11 +2817,16 @@ const decode = (string, keys, ref) => { hubSpecialId = responseData.specialId } - if (responseData.message.includes('qortal://use-embed/')) { + if (responseData.type === "notification") { + hubMessageStr = responseData.data.message + } else if (ref !== "noref" && responseData.type === "reaction") { + reactionStr = '"isReaction":true,' + repliedToStr = ref + hubMessageStr = responseData.content + } else if (responseData.message.includes('qortal://use-embed/')) { const useEmbed1 = extensionToPointer(responseData.message) const useEmbed2 = /(.*?)<\/newpointer>/g.exec(useEmbed1) const useEmbed3 = encodedToChar(useEmbed2[1]) - messageUseEmbed = parseQortalLink(useEmbed3) embedFileStr = embedToString(messageUseEmbed) hubMessageStr = responseData.message.split(useEmbed2[1]).join('') @@ -2841,7 +2834,9 @@ const decode = (string, keys, ref) => { hubMessageStr = responseData.message } - newMessageObject = '{"specialId":"' + hubSpecialId + '","message":"' + hubMessageStr + '",' + embedFileStr + ',"repliedTo":"' + repliedToStr + '","isEdited":' + editStr + ',"isFromHub":true,"isReaction":' + isHubReaction + ',"version": 3}' + const hubMessageFinal = hubMessageStr.split('"').join('"') + + newMessageObject = '{"specialId":"' + hubSpecialId + '","message":"' + hubMessageFinal + '",' + embedFileStr + ',"repliedTo":"' + repliedToStr + '","isEdited":' + editStr + ',"isFromHub":true,' + reactionStr + '"version": 3}' return newMessageObject } @@ -2950,4 +2945,4 @@ const decodeMessage = (encodedMessageObj, isReceipient, _publicKey, privateKey, } return decodedMessageObj -} \ No newline at end of file +} From f7971f70268b1beee63bce1ce53b5af8b6180116 Mon Sep 17 00:00:00 2001 From: AlphaX-Qortal Date: Wed, 12 Feb 2025 22:26:49 +0100 Subject: [PATCH 6/8] Change protocol check --- plugins/plugins/core/components/ChatPage.js | 12 ++++-------- plugins/plugins/core/streams/onNewBlock.js | 6 ++++-- plugins/plugins/core/streams/streams.js | 3 ++- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/plugins/plugins/core/components/ChatPage.js b/plugins/plugins/core/components/ChatPage.js index 2e2406b1..fc84eeaa 100644 --- a/plugins/plugins/core/components/ChatPage.js +++ b/plugins/plugins/core/components/ChatPage.js @@ -2551,15 +2551,13 @@ class ChatPage extends LitElement { const initDirect = async (cid, noInitial) => { let timeoutId let initial = 0 - let directSocketTimeout - let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] let nodeUrl = myNode.domain + ":" + myNode.port - + let nodeProtocol = myNode.protocol let directSocketLink - if (window.parent.location.protocol === "https:") { + if (nodeProtocol === "https") { directSocketLink = `wss://${nodeUrl}/websockets/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${cid}&encoding=BASE64&limit=1` } else { // Fallback to http @@ -2675,17 +2673,15 @@ class ChatPage extends LitElement { const initGroup = (gId, noInitial) => { let timeoutId let groupId = Number(gId) - let initial = 0 let count = 0 let groupSocketTimeout - let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] let nodeUrl = myNode.domain + ":" + myNode.port - + let nodeProtocol = myNode.protocol let groupSocketLink - if (window.parent.location.protocol === "https:") { + if (nodeProtocol === "https") { groupSocketLink = `wss://${nodeUrl}/websockets/chat/messages?txGroupId=${groupId}&encoding=BASE64&limit=1` } else { // Fallback to http diff --git a/plugins/plugins/core/streams/onNewBlock.js b/plugins/plugins/core/streams/onNewBlock.js index dda6e70f..a0e6efc2 100644 --- a/plugins/plugins/core/streams/onNewBlock.js +++ b/plugins/plugins/core/streams/onNewBlock.js @@ -136,9 +136,10 @@ function attemptReconnectNodeStatusSocket() { const initBlockSocket = () => { let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] let nodeUrl = myNode.domain + ":" + myNode.port + let nodeProtocol = myNode.protocol let activeBlockSocketLink - if (window.parent.location.protocol === "https:") { + if (nodeProtocol === "https") { activeBlockSocketLink = `wss://${nodeUrl}/websockets/blocks` } else { activeBlockSocketLink = `ws://${nodeUrl}/websockets/blocks` @@ -205,9 +206,10 @@ const pingactiveBlockSocket = () => { const initNodeStatusSocket = () => { let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] let nodeUrl = myNode.domain + ":" + myNode.port + let nodeProtocol = myNode.protocol let activeNodeStatusSocketLink - if (window.parent.location.protocol === "https:") { + if (nodeProtocol === "https") { activeNodeStatusSocketLink = `wss://${nodeUrl}/websockets/admin/status` } else { activeNodeStatusSocketLink = `ws://${nodeUrl}/websockets/admin/status` diff --git a/plugins/plugins/core/streams/streams.js b/plugins/plugins/core/streams/streams.js index 30a5ea3f..23b8d414 100644 --- a/plugins/plugins/core/streams/streams.js +++ b/plugins/plugins/core/streams/streams.js @@ -112,9 +112,10 @@ parentEpml.subscribe('logged_in', async isLoggedIn => { const initChatHeadSocket = () => { let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] let nodeUrl = myNode.domain + ":" + myNode.port + let nodeProtocol = myNode.protocol let activeChatSocketLink - if (window.parent.location.protocol === "https:") { + if (nodeProtocol === "https") { activeChatSocketLink = `wss://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}?encoding=BASE64` } else { activeChatSocketLink = `ws://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}?encoding=BASE64` From d6e0846d58a8f04dc040cdef15a77b15c0bfb989 Mon Sep 17 00:00:00 2001 From: AlphaX-Qortal <67390536+AlphaX-Qortal@users.noreply.github.com> Date: Thu, 13 Feb 2025 08:38:14 +0100 Subject: [PATCH 7/8] Change protocol check in trade portal and auto buy --- .../core/trade-bot/trade-bot-portal.src.js | 17 +++++++--- .../core/trade-portal/trade-portal.src.js | 34 ++++++++++++++----- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/plugins/plugins/core/trade-bot/trade-bot-portal.src.js b/plugins/plugins/core/trade-bot/trade-bot-portal.src.js index 909a40e5..28211d2d 100644 --- a/plugins/plugins/core/trade-bot/trade-bot-portal.src.js +++ b/plugins/plugins/core/trade-bot/trade-bot-portal.src.js @@ -2882,7 +2882,7 @@ class TradeBotPortal extends LitElement { const initTradeOffersWebSocket = (restarted = false) => { let tradeOffersSocketCounter = 0 let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true` + let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true` const socket = new WebSocket(socketLink) socket.onopen = () => { setTimeout(pingSocket, 50) @@ -2914,7 +2914,7 @@ class TradeBotPortal extends LitElement { const initTradeBotWebSocket = (restarted = false) => { let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN` + let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN` const socket = new WebSocket(socketLink) socket.onopen = () => { setTimeout(pingSocket, 50) @@ -2943,7 +2943,7 @@ class TradeBotPortal extends LitElement { const initTradePresenceWebSocket = (restarted = false) => { let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradepresence` + let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradepresence` const socket = new WebSocket(socketLink) socket.onopen = () => { setTimeout(pingSocket, 50) @@ -3289,10 +3289,19 @@ class TradeBotPortal extends LitElement { let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] let nodeUrl = myNode.domain + ':' + myNode.port + let nodeProtocol = myNode.protocol + let checkProtocol + + if (nodeProtocol === "https") { + checkProtocol = 'wss' + } else { + checkProtocol = 'ws' + } const modifiers = [ + { searchValue: 'PROTOCOL', replaceValue: checkProtocol }, { searchValue: 'NODEURL', replaceValue: nodeUrl }, - { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin }, + { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin } ] workers.get(this.selectedCoin).tradesConnectedWorker = this.inlineWorker(this.initSocket, modifiers) diff --git a/plugins/plugins/core/trade-portal/trade-portal.src.js b/plugins/plugins/core/trade-portal/trade-portal.src.js index f42d3ab3..9037fec8 100644 --- a/plugins/plugins/core/trade-portal/trade-portal.src.js +++ b/plugins/plugins/core/trade-portal/trade-portal.src.js @@ -2181,7 +2181,7 @@ class TradePortal extends LitElement { const initTradeOffersWebSocket = (restarted = false) => { let tradeOffersSocketCounter = 0 let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true` + let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true` const socket = new WebSocket(socketLink) socket.onopen = () => { setTimeout(pingSocket, 50) @@ -2213,7 +2213,7 @@ class TradePortal extends LitElement { const initTradeBotWebSocket = (restarted = false) => { let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN` + let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN` const socket = new WebSocket(socketLink) socket.onopen = () => { setTimeout(pingSocket, 50) @@ -2242,7 +2242,7 @@ class TradePortal extends LitElement { const initTradePresenceWebSocket = (restarted = false) => { let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradepresence` + let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradepresence` const socket = new WebSocket(socketLink) socket.onopen = () => { setTimeout(pingSocket, 50) @@ -2726,10 +2726,19 @@ class TradePortal extends LitElement { let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] let nodeUrl = myNode.domain + ':' + myNode.port + let nodeProtocol = myNode.protocol + let checkProtocol + + if (nodeProtocol === "https") { + checkProtocol = 'wss' + } else { + checkProtocol = 'ws' + } const modifiers = [ + { searchValue: 'PROTOCOL', replaceValue: checkProtocol }, { searchValue: 'NODEURL', replaceValue: nodeUrl }, - { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin }, + { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin } ] workers.get(this.selectedCoin).tradesConnectedWorker = this.inlineWorker(this.initSocket, modifiers) @@ -2791,7 +2800,7 @@ class TradePortal extends LitElement { }) const getCompletedTrades = async () => { - const url = `http://NODEURL/crosschain/trades?limit=25&reverse=true&foreignBlockchain=FOREIGN_BLOCKCHAIN` + const url = `PROTOCOL://NODEURL/crosschain/trades?limit=25&reverse=true&foreignBlockchain=FOREIGN_BLOCKCHAIN` const res = await fetch(url) const historicTrades = await res.json() const compareFn = (a, b) => { @@ -2810,7 +2819,7 @@ class TradePortal extends LitElement { } const getOffers = async () => { - const url = `http://NODEURL/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN` + const url = `PROTOCOL://NODEURL/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN` const res = await fetch(url) const openTradeOrders = await res.json() const myOpenTradeOrders = await openTradeOrders.filter((order) => order.mode === 'OFFERING' && order.qortalCreator === 'SELECTED_ADDRESS') @@ -2872,11 +2881,20 @@ class TradePortal extends LitElement { let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] let nodeUrl = myNode.domain + ':' + myNode.port + let nodeProtocol = myNode.protocol + let checkProtocol + + if (nodeProtocol === "https") { + checkProtocol = 'https' + } else { + checkProtocol = 'http' + } const modifiers = [ + { searchValue: 'PROTOCOL', replaceValue: checkProtocol }, { searchValue: 'NODEURL', replaceValue: nodeUrl }, - { searchValue: 'SELECTED_ADDRESS', replaceValue: this.selectedAddress.address, }, - { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin, }, + { searchValue: 'SELECTED_ADDRESS', replaceValue: this.selectedAddress.address }, + { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin, } ] workers.get(this.selectedCoin).handleStuckTradesConnectedWorker = this.inlineWorker(this.handleStuckTrades, modifiers) From 8b8ad3015fea54a5646e3d24df15b243ec383888 Mon Sep 17 00:00:00 2001 From: AlphaX-Qortal <67390536+AlphaX-Qortal@users.noreply.github.com> Date: Thu, 13 Feb 2025 10:37:15 +0100 Subject: [PATCH 8/8] Remove preview chat --- .../group-management/group-management.src.js | 1714 +---------------- 1 file changed, 19 insertions(+), 1695 deletions(-) diff --git a/plugins/plugins/core/group-management/group-management.src.js b/plugins/plugins/core/group-management/group-management.src.js index 0488968e..a657833d 100644 --- a/plugins/plugins/core/group-management/group-management.src.js +++ b/plugins/plugins/core/group-management/group-management.src.js @@ -1,24 +1,8 @@ -import { html, LitElement } from 'lit' -import { render } from 'lit/html.js' -import { unsafeHTML } from 'lit/directives/unsafe-html.js' -import { Epml } from '../../../epml' -import { generateHTML } from '@tiptap/core' -import { roundToNearestDecimal } from '../../utils/functions' -import { groupManagementStyles } from '../components/plugins-css' -import { - decryptGroupData, - uint8ArrayToBase64, - base64ToUint8Array, - uint8ArrayToObject, - validateSecretKey, - decryptSingle -} from '../components/GroupEncryption' -import Base58 from '../../../../crypto/api/deps/Base58' +import {html, LitElement} from 'lit' +import {render} from 'lit/html.js' +import {Epml} from '../../../epml' +import {groupManagementStyles} from '../components/plugins-css' import isElectron from 'is-electron' -import Highlight from '@tiptap/extension-highlight' -import ShortUniqueId from 'short-unique-id' -import StarterKit from '@tiptap/starter-kit' -import Underline from '@tiptap/extension-underline' import '../components/time-elements/index' import '@material/mwc-button' import '@material/mwc-dialog' @@ -38,7 +22,8 @@ import '@vaadin/grid/vaadin-grid-sort-column.js' import '@vaadin/text-field' // Multi language support -import { get, registerTranslateConfig, translate, use } from '../../../../core/translate' +import {get, registerTranslateConfig, translate, use} from '../../../../core/translate' + registerTranslateConfig({ loader: lang => fetch(`/language/${lang}.json`).then(res => res.json()) }) @@ -198,10 +183,6 @@ class GroupManagement extends LitElement { add ${translate("grouppage.gchange2")} - this.openPreviewGeneral()}> - pageview -  ${translate("general.view")} Qortal General Chat -
@@ -228,10 +209,6 @@ class GroupManagement extends LitElement {
- { - await this.getChatMessageCount(data.item) - render(html`${this.countArray.length}`, root) - }}> { if (data.item.isOpen === true) { @@ -250,14 +227,6 @@ class GroupManagement extends LitElement { `, root) }}> - { - render(html` - this.openPreviewChat(data.item)}> - pageview -  ${translate("general.view")} - - `, root) - }}>
@@ -265,26 +234,14 @@ class GroupManagement extends LitElement { - { - await this.getChatMessageCount(data.item) - render(html`${this.countArray.length}`, root) - }}> - { + { render(html`${this.renderRole(data.item)}`, root) }}> - { + { render(html`${this.renderManageButton(data.item)}`, root) }}> - { - render(html` - this.openPreviewChat(data.item)}> - pageview -  ${translate("general.view")} - - `, root) - }}> ${this.isEmptyArray(this.joinedGroups) ? html`
@@ -296,10 +253,6 @@ class GroupManagement extends LitElement {

${translate("managegroup.mg36")}

- { - await this.getChatMessageCount(data.item) - render(html`${this.countArray.length}`, root) - }}> { if (data.item.isOpen === true) { @@ -312,7 +265,7 @@ class GroupManagement extends LitElement { const expiryString = new Date(data.item.expiry).toLocaleString() render(html`${expiryString}`, root) }}> - { + { render(html` this.openJoinGroup(data.item)}> queue @@ -320,14 +273,6 @@ class GroupManagement extends LitElement { `, root) }}> - { - render(html` - this.openPreviewChat(data.item)}> - pageview -  ${translate("general.view")} - - `, root) - }}> ${this.isEmptyArray(this.groupInvites) ? html`
@@ -356,7 +301,7 @@ class GroupManagement extends LitElement { - { + { render(html` this.openJoinGroup(data.item)}> queue @@ -364,14 +309,6 @@ class GroupManagement extends LitElement { `, root) }}> - { - render(html` - this.openPreviewChat(data.item)}> - pageview -  ${translate("general.view")} - - `, root) - }}> ${this.isEmptyArray(this.publicGroups) ? html` ${translate("grouppage.gchange11")} @@ -684,39 +621,7 @@ class GroupManagement extends LitElement {
- -
-
-

${translate("grouppage.gchange4")}: ${this.chatInfoName} / ${translate("managegroup.mg8")}: ${this.chatInfoId} / ${translate("grouppage.gchange54")}: ${this.chatInfoMembers}

-
- this.shadowRoot.getElementById('chat-container').scrollIntoView({ - block: 'end', - behavior: 'smooth' - })} - title="${translate("managegroup.mg5")}" - > - arrow_circle_down - - this.shadowRoot.getElementById('chat-container').scrollIntoView({ - block: 'start', - behavior: 'smooth' - })} - title="${translate("managegroup.mg5")}" - > - arrow_circle_up - - this.closePreviewChat()} title="${translate("managegroup.mg5")}">highlight_off -
-
-
-
-
-
-
+
@@ -2049,10 +1954,7 @@ class GroupManagement extends LitElement { } uploadAvatar(subName, subIdentifier) { - let name = subName - let identifier = subIdentifier - - window.location.href = `../qdn/publish/index.html?service=THUMBNAIL&identifier=${identifier}&name=${name}&uploadType=file&category=Avatar&showName=false&showService=false&showIdentifier=false` + window.location.href = `../qdn/publish/index.html?service=THUMBNAIL&identifier=${subIdentifier}&name=${subName}&uploadType=file&category=Avatar&showName=false&showService=false&showIdentifier=false` } renderGroupAvatar() { @@ -2060,15 +1962,15 @@ class GroupManagement extends LitElement { let indentifierForRenderAvatar = 'qortal_group_avatar_' + this.manageGroupId if (this.manageGroupId === 1) { - return html`` + return html`` } else if (this.haveGoName) { const myRenderNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] const renderAvatarUrl = myRenderNode.protocol + '://' + myRenderNode.domain + ':' + myRenderNode.port const renderGroupAvatarUrl = `${renderAvatarUrl}/arbitrary/THUMBNAIL/${nameForRenderAvatar}/${indentifierForRenderAvatar}?async=true}` - return html`` + return html`` } else { - return html`` + return html`` } } @@ -2311,7 +2213,7 @@ class GroupManagement extends LitElement { if (_inviteMemberInfo === '' || _nviteMemberTime === 'reject') { this.shadowRoot.querySelector('#fieldErrorDialog').show() } else { - if (_inviteMemberInfo.startsWith('Q') && _inviteMemberInfo.length == 34) { + if (_inviteMemberInfo.startsWith('Q') && _inviteMemberInfo.length === 34) { this.getAddressUserResult(_inviteMemberInfo, _nviteMemberTime, _inviteGroupId) } else { this.getNameUserResult(_inviteMemberInfo, _nviteMemberTime, _inviteGroupId) @@ -2824,14 +2726,12 @@ class GroupManagement extends LitElement { async openJoinGroup(groupObj) { this.joinGroupObj = {} - let joinedHroups = [] + let joinedHroups let requestJoin - let resJoinedGroups = await parentEpml.request('apiCall', { + joinedHroups = await parentEpml.request('apiCall', { url: `/groups/member/${this.selectedAddress.address}` }) - - joinedHroups = resJoinedGroups requestJoin = groupObj.groupId if (joinedHroups.find(item => item.groupId === requestJoin)) { @@ -2851,1296 +2751,6 @@ class GroupManagement extends LitElement { this.shadowRoot.querySelector('#leaveDialog').show() } - async openPreviewChat(groupObj) { - this.chatInfoName = groupObj.groupName - this.chatInfoId = groupObj.groupId - this.chatInfoMembers = groupObj.memberCount - this.shadowRoot.getElementById('downloadProgressDialog').open() - await this.getSymKeyFile(groupObj.groupId) - await this.getChatContent(groupObj.groupId) - } - - async getSymKeyFile(groupId) { - this.secretKeys = {} - this.groupAdmins = {} - - let data - let supArray = [] - let allSymKeys = [] - let gAdmin = '' - let gAddress = '' - let keysToOld = "Wait until an admin re-encrypts the keys. Only unencrypted messages will be displayed." - let retryDownload = "Retry downloading and decrypt keys in 5 seconds! Please wait..." - let failDownload = "Error downloading and decrypt keys! Only unencrypted messages will be displayed. Please try again later..." - let all_ok = false - let counter = 0 - - const symIdentifier = 'symmetric-qchat-group-' + groupId - 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 getNameUrl = `${nodeUrl}/arbitrary/resources?service=DOCUMENT_PRIVATE&identifier=${symIdentifier}&limit=0&reverse=true` - const getAdminUrl = `${nodeUrl}/groups/members/${groupId}?onlyAdmins=true&limit=0` - - supArray = await fetch(getNameUrl).then(response => { - return response.json() - }) - - if (this.isEmptyArray(supArray) || groupId === 0) { - console.log("No Symetric Key") - } else { - supArray.forEach(item => { - const symInfoObj = { - name: item.name, - identifier: item.identifier, - timestamp: item.updated ? item.updated : item.created - } - allSymKeys.push(symInfoObj) - }) - - let allSymKeysSorted = allSymKeys.sort(function(a, b) { - return b.timestamp - a.timestamp - }) - - gAdmin = allSymKeysSorted[0].name - - const addressUrl = `${nodeUrl}/names/${gAdmin}` - - let addressObject = await fetch(addressUrl).then(response => { - return response.json() - }) - - gAddress = addressObject.owner - - let adminRes = await fetch(getAdminUrl).then(response => { - return response.json() - }) - - this.groupAdmins = adminRes.members - - const adminExists = (adminAddress) => { - return this.groupAdmins.some(function(checkAdmin) { - return checkAdmin.member === adminAddress - }) - } - - if (adminExists(gAddress)) { - const sleep = (t) => new Promise(r => setTimeout(r, t)) - const dataUrl = `${nodeUrl}/arbitrary/DOCUMENT_PRIVATE/${gAdmin}/${symIdentifier}?encoding=base64&rebuild=true&async=true` - const res = await fetch(dataUrl) - - do { - counter++ - - if (!res.ok) { - parentEpml.request('showSnackBar', `${retryDownload}`) - await sleep(5000) - } else { - data = await res.text() - all_ok = true - } - - if (counter > 10) { - parentEpml.request('showSnackBar', `${failDownload}`) - return - } - } while (!all_ok) - - const decryptedKey = await this.decryptGroupEncryption(data) - - if (decryptedKey === undefined) { - parentEpml.request('showSnackBar', `${keysToOld}`) - } else { - const dataint8Array = base64ToUint8Array(decryptedKey.data) - const decryptedKeyToObject = uint8ArrayToObject(dataint8Array) - - if (!validateSecretKey(decryptedKeyToObject)) { - throw new Error("SecretKey is not valid") - } - - this.secretKeys = decryptedKeyToObject - } - } - } - } - - async decryptGroupEncryption(data) { - try { - const privateKey = Base58.encode(window.parent.reduxStore.getState().app.wallet._addresses[0].keyPair.privateKey) - const encryptedData = decryptGroupData(data, privateKey) - - return { - data: uint8ArrayToBase64(encryptedData.decryptedData), - count: encryptedData.count - } - } catch (error) { - console.log("Error:", error.message) - } - } - - async openPreviewGeneral() { - this.chatInfoName = 'Qortal General Chat' - this.chatInfoId = 0 - this.chatInfoMembers = 'Everyone' - this.shadowRoot.getElementById('downloadProgressDialog').open() - await this.getChatContent(0) - } - - closePreviewChat() { - this.shadowRoot.getElementById('chatInfoDialog').close() - this.chatInfoName = '' - this.chatInfoId = '' - this.chatInfoMembers = '' - this.chatMessageArray = [] - this.shadowRoot.getElementById('chat-container').innerHTML = '' - - if (this.webSocket) { - this.webSocket.close(1000, 'closed preview') - this.webSocket = '' - } - } - - async getChatMessageCount(groupObj) { - this.countArray = [] - - let retChatArr = await parentEpml.request('apiCall', { - url: `/chat/messages?txGroupId=${groupObj.groupId}&haschatreference=false&encoding=BASE64&limit=0&reverse=false` - }) - - this.countArray = retChatArr - } - - decodeMessage(string) { - const binaryString = atob(string) - const binaryLength = binaryString.length - const bytes = new Uint8Array(binaryLength) - - for (let i = 0; i < binaryLength; i++) { - bytes[i] = binaryString.charCodeAt(i) - } - - const decoder = new TextDecoder() - const decodedString = decoder.decode(bytes) - - if (decodedString.includes("messageText") || decodedString === "4001") { - if (decodedString === "4001") { - const firstString = 'First group key created.' - const hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + firstString + '"}]}]},"images":[""],"repliedTo":"","version":3}' - return hubString - } else { - return decodedString - } - } else { - let repliedToStr = '' - let messageStr = '' - let hubString = '' - - const res = decryptSingle(string, this.secretKeys, false) - - if (res === 'noKey' || res === 'decryptionFailed') { - return '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This message could not be decrypted"}]}]},"images":[""],"repliedTo":"","version":3}' - } - - const decryptToUnit8Array = base64ToUint8Array(res) - const responseData = uint8ArrayToObject(decryptToUnit8Array) - - if (responseData.type === "notification") { - const messageStrRaw = responseData.data.message - messageStr = messageStrRaw.trim() - } - - if (responseData.hasOwnProperty('message') && typeof responseData['message'] === 'string' && responseData['message'].length) { - const messageStrRaw = responseData.message - const messageJoin1 = messageStrRaw.split('"').join('') - const messageReplace1 = messageJoin1.replace('

', '') - const messageReplace2 = messageReplace1.replace('

', '') - const messageTrim = messageReplace2.trim() - const messageJoin2 = messageTrim.split('

').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"') - const messageJoin3 = messageJoin2.split('
').join('"},{"type":"hardBreak"},{"type":"text","text":"') - - messageStr = messageJoin3 - } - - if (responseData.repliedTo) { - repliedToStr = responseData.repliedTo - } - - if (responseData.type === "edit") { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]},"images":[""],"repliedTo":"' + repliedToStr + '","version":3,"isEdited":true}' - } else { - hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]},"images":[""],"repliedTo":"' + repliedToStr + '","version":3}' - } - - const preparedString = hubString.split('').join('\\"') - const finalString = preparedString.replace(/<\/?[^>]+(>|$)/g, '') - - return finalString - } - } - - async getChatContent(involved) { - let chatArray = [] - let decodedArray = [] - this.chatMessageArray = [] - this.firstMessageTimestamp = 0 - const chatDelay = ms => new Promise(res => setTimeout(res, ms)) - - // Call the chat messages without chatreference ( without chatreference are messages in original ) - let retChat = await parentEpml.request('apiCall', { - url: `/chat/messages?txGroupId=${involved}&haschatreference=false&encoding=BASE64&limit=0&reverse=false` - }) - - chatArray = retChat - - // Decode the BASE64 Messagge and add to new array - chatArray.forEach(item => { - let decodedMessageObj = {} - let decodedMessage = this.decodeMessage(item.data) - - const messageObj = { - timestamp: item.timestamp, - txGroupId: item.txGroupId, - reference: item.reference, - senderPublicKey: item.senderPublicKey, - sender: item.sender, - senderName: item.senderName, - encoding: item.encoding, - isText: item.isText, - isEncrypted: item.isEncrypted, - signature: item.signature - } - - decodedMessageObj = { ...messageObj, decodedMessage } - - decodedArray.push(decodedMessageObj) - }) - - // Set decoded array to new array - this.chatMessageArray = decodedArray - - let chaEditedArray = [] - - // Call the chat messages with chatreference ( with chatreference means a message got edited ) - let getEditedArray = await parentEpml.request('apiCall', { - url: `/chat/messages?txGroupId=${involved}&haschatreference=true&encoding=BASE64&limit=0&reverse=false` - }) - - chaEditedArray = getEditedArray - - // Replace messages which got edited in the chatMessageArray - chaEditedArray.forEach(item => { - let editedDecodedMessage = '' - let editedSignature = '' - - editedDecodedMessage = this.decodeMessage(item.data) - editedSignature = item.chatReference - - const found = this.chatMessageArray.some(el => el.signature === editedSignature) - - if (found) { - this.chatMessageArray.find(v => v.signature === editedSignature).decodedMessage = editedDecodedMessage - } - }) - - this.shadowRoot.getElementById('downloadProgressDialog').close() - this.shadowRoot.getElementById('chatInfoDialog').open() - this.shadowRoot.getElementById('chat-container').innerHTML = '' - - // Render the chat messages from chatMessageArray - await this.renderChatMessagesGrid(this.chatMessageArray, false) - await chatDelay(250) - - this.shadowRoot.getElementById('chat-container').scrollIntoView({ - block: 'end', - behavior: 'smooth' - }) - - // Start the websocket for new messages - this.fetchChatMessages(involved) - } - - async scrollChatToEnd() { - const scrollDelay = ms => new Promise(res => setTimeout(res, ms)) - - await scrollDelay(100) - - this.shadowRoot.getElementById('chat-container').scrollIntoView({ - block: 'end', - behavior: 'smooth' - }) - } - - renderChatMessagesGrid(renderArray, scroll) { - 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 chatGridContainer = this.shadowRoot.getElementById('chat-container') - - let noMessagesString = get('grouppage.gchange70') - let forwardedString = get('blockpage.bcchange17') - let editedString = '( ' + get('chatpage.cchange68') + ' )' - let imageDeletedString = get('chatpage.cchange80') - let gifDeletedString = get('chatpage.cchange107') - let attachmentDeletedString = get('chatpage.cchange82') - let fileDeletedString = get('chatpage.cchange102') - let sizeString = get('websitespage.schange27') - - if (this.shadowRoot.getElementById('chat-container').innerHTML === '') { - this.shadowRoot.getElementById('chat-container').innerHTML = '' - } - - if (this.isEmptyArray(renderArray)) { - const chatEmpty = document.createElement('div') - chatEmpty.classList.add('no-messages') - chatEmpty.textContent = noMessagesString - - chatGridContainer.appendChild(chatEmpty) - } else { - renderArray.forEach(item => { - const parsedMessageObj = JSON.parse(item.decodedMessage) - - let chatID = '' - let messageID = '' - let messageTimeID = '' - let messageEditedID = '' - let messageImageID = '' - let messageGifID = '' - let messageAttachmentID = '' - let messageFileID = '' - let repliedID = '' - let repliedImageID = '' - let repliedGifID = '' - let repliedAttachmentID = '' - let repliedFileID = '' - let subcontainer1ID = '' - let subcontainer2ID = '' - let name = '' - let repliedName = '' - let messageAddress = '' - let repliedMessageAddress = '' - let repliedMessage = '' - let messageContent = '' - let imageLink = '' - let gifLink = '' - let attachmentLink = '' - let fileLink = '' - let attachmentName = '' - let fileName = '' - let attachmentSize = '' - let fileSize = '' - let repliedImageLink = '' - let repliedGifLink = '' - let repliedAttachmentLink = '' - let repliedFileLink = '' - let repliedAttachmentName = '' - let repliedFileName = '' - let repliedAttachmentSize = '' - let repliedFileSize = '' - let messageTimeString = '' - let haveImage = false - let haveGif = false - let haveAttachment = false - let haveFile = false - let haveRepliedImage = false - let haveRepliedGif = false - let haveRepliedAttachment = false - let haveRepliedFile = false - let hasImageDeleted = false - let hasGifDeleted = false - let hasAttachmentDeleted = false - let hasFileDeleted = false - let hasRepliedImageDeleted = false - let hasRepliedGifDeleted = false - let hasRepliedAttachmentDeleted = false - let hasRepliedFileDeleted = false - let isForwarded = false - let isEdited = false - let avatarFetches = 0 - let imageFetches = 0 - let repliedImageFetches = 0 - - messageTimeString = new Date(item.timestamp).toLocaleString() - - if (item.senderName) { - name = item.senderName - messageAddress = item.sender - } else { - name = item.sender - messageAddress = item.sender - } - - chatID = item.reference - messageID = item.signature - messageTimeID = 'time-' + item.signature - messageEditedID = 'edited-' + item.signature - messageImageID = 'image-' + item.signature - messageGifID = 'gif-' + item.signature - messageAttachmentID = 'attachment-' + item.signature - messageFileID = 'file-' + item.signature - subcontainer1ID = 'subcontainer1-' + item.signature - subcontainer2ID = 'subcontainer2-' + item.signature - isForwarded = parsedMessageObj.type === 'forward' - isEdited = parsedMessageObj.isEdited - - if (parsedMessageObj.version > 1 && parsedMessageObj.messageText) { - messageContent = generateHTML(parsedMessageObj.messageText, [StarterKit, Underline, Highlight]) - } - - if (parsedMessageObj.repliedTo) { - let replied = this.chatMessageArray.filter(obj => { - return obj.signature === parsedMessageObj.repliedTo - }) - - replied.forEach(item => { - const parsedRepliedMessageObj = JSON.parse(item.decodedMessage) - - if (item.senderName) { - repliedName = item.senderName - repliedMessageAddress = item.sender - } else { - repliedName = item.sender - repliedMessageAddress = item.sender - } - - repliedID = item.reference - repliedImageID = 'repimage-' + item.signature - repliedGifID = 'repgif-' + item.signature - repliedAttachmentID = 'repattachment-' + item.signature - repliedFileID = 'repfile-' + item.signature - - if (parsedRepliedMessageObj.isImageDeleted === false) { - haveRepliedImage = true - hasRepliedImageDeleted = false - - parsedRepliedMessageObj.images.forEach(item => { - if (item.name) { - repliedImageLink = item.service + '/' + item.name + '/' + item.identifier - } - }) - } else if (parsedRepliedMessageObj.isImageDeleted === true) { - haveRepliedImage = true - hasRepliedImageDeleted = true - } - - if (parsedRepliedMessageObj.isGifDeleted === false) { - haveRepliedGif = true - hasRepliedGifDeleted = false - - parsedRepliedMessageObj.gifs.forEach(item => { - if (item.name) { - repliedGifLink = item.service + '/' + item.name + '/' + item.identifier - } - }) - } else if (parsedRepliedMessageObj.isGifDeleted === true) { - haveRepliedGif = true - hasRepliedGifDeleted = true - } - - if (parsedRepliedMessageObj.isAttachmentDeleted === false) { - haveRepliedAttachment = true - hasRepliedAttachmentDeleted = false - - parsedRepliedMessageObj.attachments.forEach(item => { - if (item.name) { - repliedAttachmentLink = item.service + '/' + item.name + '/' + item.identifier - repliedAttachmentName = item.attachmentName - let repliedAttachmentSizeMb = roundToNearestDecimal(item.attachmentSize) - repliedAttachmentSize = sizeString + ': ' + repliedAttachmentSizeMb + ' mb' - } - }) - } else if (parsedRepliedMessageObj.isAttachmentDeleted === true) { - haveRepliedAttachment = true - hasRepliedAttachmentDeleted = true - } - - if (parsedRepliedMessageObj.isFileDeleted === false) { - haveRepliedFile = true - hasRepliedFileDeleted = false - - parsedRepliedMessageObj.files.forEach(item => { - if (item.name) { - repliedFileLink = item.service + '/' + item.name + '/' + item.identifier - repliedFileName = item.appFileName - let repliedFileSizeMb = roundToNearestDecimal(item.appFileSize) - repliedFileSize = sizeString + ': ' + repliedFileSizeMb + ' mb' - } - }) - } else if (parsedRepliedMessageObj.isFileDeleted === true) { - haveRepliedFile = true - hasRepliedFileDeleted = true - } - - if (parsedRepliedMessageObj.version > 1 && parsedRepliedMessageObj.messageText) { - repliedMessage = generateHTML(parsedRepliedMessageObj.messageText, [StarterKit, Underline, Highlight]) - } - }) - } - - if (parsedMessageObj.isImageDeleted === false) { - haveImage = true - hasImageDeleted = false - - parsedMessageObj.images.forEach(item => { - if (item.name) { - imageLink = item.service + '/' + item.name + '/' + item.identifier - } - }) - } else if (parsedMessageObj.isImageDeleted === true) { - haveImage = true - hasImageDeleted = true - } - - if (parsedMessageObj.isGifDeleted === false) { - haveGif = true - hasGifDeleted = false - - parsedMessageObj.gifs.forEach(item => { - if (item.name) { - gifLink = item.service + '/' + item.name + '/' + item.identifier - } - }) - } else if (parsedMessageObj.isGifDeleted === true) { - haveGif = true - hasGifDeleted = true - } - - if (parsedMessageObj.isAttachmentDeleted === false) { - haveAttachment = true - hasAttachmentDeleted = false - - parsedMessageObj.attachments.forEach(item => { - if (item.name) { - attachmentLink = item.service + '/' + item.name + '/' + item.identifier - attachmentName = item.attachmentName - let attachmentSizeMb = roundToNearestDecimal(item.attachmentSize) - attachmentSize = sizeString + ': ' + attachmentSizeMb + ' mb' - } - }) - } else if (parsedMessageObj.isAttachmentDeleted === true) { - haveAttachment = true - hasAttachmentDeleted = true - } - - if (parsedMessageObj.isFileDeleted === false) { - haveFile = true - hasFileDeleted = false - - parsedMessageObj.files.forEach(item => { - if (item.name) { - fileLink = item.service + '/' + item.name + '/' + item.identifier - fileName = item.appFileName - let fileSizeMb = roundToNearestDecimal(item.appFileSize) - fileSize = sizeString + ': ' + fileSizeMb + ' mb' - } - }) - } else if (parsedMessageObj.isFileDeleted === true) { - haveFile = true - hasFileDeleted = true - } - - const chatElement = document.createElement('div') - chatElement.setAttribute('id', chatID) - chatElement.classList.add('message-container') - - const forwarded = document.createElement('span') - forwarded.classList.add('message-data-forward') - forwarded.textContent = forwardedString - - const subcontainer1 = document.createElement('div') - subcontainer1.setAttribute('id', subcontainer1ID) - subcontainer1.classList.add('message-subcontainer1') - - const subcontainer2 = document.createElement('div') - subcontainer2.setAttribute('id', subcontainer2ID) - if (this.selectedAddress.address === messageAddress) { - subcontainer2.classList.add('message-subcontainer2-mybg', 'message-triangle-mybg') - } else { - subcontainer2.classList.add('message-subcontainer2', 'message-triangle') - } - - const avatarContainer = document.createElement('div') - avatarContainer.classList.add('message-avatar') - - const userinfo = document.createElement('div') - userinfo.classList.add('message-user-info') - - const username = document.createElement('span') - if (this.selectedAddress.address === messageAddress) { - username.classList.add('message-data-my-name') - } else { - username.classList.add('message-data-name') - } - username.textContent = name - - if (isForwarded) { - userinfo.appendChild(username) - userinfo.appendChild(forwarded) - } else { - userinfo.appendChild(username) - } - - const messageContainer = document.createElement('div') - messageContainer.setAttribute('id', messageID) - messageContainer.classList.add('message') - messageContainer.innerHTML = messageContent - - const messageTimeContainer = document.createElement('div') - messageTimeContainer.setAttribute('id', messageTimeID) - - const messageOrgTimeString = document.createElement('span') - messageOrgTimeString.classList.add('message-data-edited') - messageOrgTimeString.textContent = messageTimeString - - const messageEditedString = document.createElement('span') - messageEditedString.setAttribute('id', messageEditedID) - messageEditedString.classList.add('message-data-edited') - messageEditedString.textContent = editedString - - if (!isEdited) { - messageTimeContainer.classList.add('message-data-time') - messageTimeContainer.appendChild(messageOrgTimeString) - } else if (isEdited) { - messageTimeContainer.classList.add('message-data-time-edited') - messageTimeContainer.appendChild(messageEditedString) - messageTimeContainer.appendChild(messageOrgTimeString) - } - - const avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${name}/qortal_avatar?async=true` - const avatarImage = document.createElement('img') - avatarImage.src = `${avatarUrl}` - avatarImage.onerror = () => { - if (avatarFetches < 4) { - setTimeout(() => { - avatarFetches = avatarFetches + 1 - avatarImage.src = `${avatarUrl}` - }, 750) - } else { - avatarImage.src = '/img/incognito.png' - } - } - avatarContainer.appendChild(avatarImage) - - const contentDeltedContainer = document.createElement('div') - contentDeltedContainer.classList.add('attachment-container') - - const contentDeltedInfo = document.createElement('div') - contentDeltedInfo.classList.add('attachment-info') - - const contentDeltedText = document.createElement('p') - contentDeltedText.classList.add('attachment-deleted') - - const repliedtodata = document.createElement('div') - repliedtodata.classList.add('original-message') - repliedtodata.onclick = () => { - this.shadowRoot.getElementById(repliedID).scrollIntoView({ - behavior: 'smooth' - }) - } - - const repliedtoname = document.createElement('p') - if (this.selectedAddress.address === repliedMessageAddress) { - repliedtoname.classList.add('original-message-sender-wasme') - } else { - repliedtoname.classList.add('original-message-sender') - } - repliedtoname.textContent = repliedName - - const repliedtomessage = document.createElement('p') - repliedtomessage.classList.add('replied-message') - repliedtomessage.innerHTML = repliedMessage - - const attachmentContainer = document.createElement('div') - attachmentContainer.setAttribute('id', messageAttachmentID) - attachmentContainer.classList.add('attachment-container') - - const attachmentIconContainer = document.createElement('div') - attachmentIconContainer.classList.add('attachment-icon-container') - - const attachmentIconUrl = `/img/attachment-icon.png` - const attachmentIcon = document.createElement('img') - attachmentIcon.classList.add('attachment-icon') - attachmentIcon.src = `${attachmentIconUrl}` - - attachmentIconContainer.appendChild(attachmentIcon) - - const attachmentInfoContainer = document.createElement('div') - attachmentInfoContainer.classList.add('attachment-info') - - const attachmentNameContainer = document.createElement('p') - attachmentNameContainer.classList.add('attachment-name') - attachmentNameContainer.textContent = attachmentName - - const attachmentSizeContainer = document.createElement('p') - attachmentSizeContainer.classList.add('attachment-size') - attachmentSizeContainer.textContent = attachmentSize - - attachmentInfoContainer.appendChild(attachmentNameContainer) - attachmentInfoContainer.appendChild(attachmentSizeContainer) - - attachmentContainer.appendChild(attachmentIconContainer) - attachmentContainer.appendChild(attachmentInfoContainer) - - const repliedAttachmentContainer = document.createElement('div') - repliedAttachmentContainer.setAttribute('id', repliedAttachmentID) - repliedAttachmentContainer.classList.add('attachment-container') - - const repliedAttachmentIconContainer = document.createElement('div') - repliedAttachmentIconContainer.classList.add('attachment-icon-container') - - const repliedAttachmentIconUrl = `/img/attachment-icon.png` - const repliedAttachmentIcon = document.createElement('img') - repliedAttachmentIcon.classList.add('attachment-icon') - repliedAttachmentIcon.src = `${repliedAttachmentIconUrl}` - - repliedAttachmentIconContainer.appendChild(repliedAttachmentIcon) - - const repliedAttachmentInfoContainer = document.createElement('div') - repliedAttachmentInfoContainer.classList.add('attachment-info') - - const repliedAttachmentNameContainer = document.createElement('p') - repliedAttachmentNameContainer.classList.add('attachment-name') - repliedAttachmentNameContainer.textContent = repliedAttachmentName - - const repliedAttachmentSizeContainer = document.createElement('p') - repliedAttachmentSizeContainer.classList.add('attachment-size') - repliedAttachmentSizeContainer.textContent = repliedAttachmentSize - - repliedAttachmentInfoContainer.appendChild(repliedAttachmentNameContainer) - repliedAttachmentInfoContainer.appendChild(repliedAttachmentSizeContainer) - - repliedAttachmentContainer.appendChild(repliedAttachmentIconContainer) - repliedAttachmentContainer.appendChild(repliedAttachmentInfoContainer) - - const fileContainer = document.createElement('div') - fileContainer.setAttribute('id', messageFileID) - fileContainer.classList.add('file-container') - - const fileIconContainer = document.createElement('div') - fileIconContainer.classList.add('file-icon-container') - - const fileIconUrl = `/img/file-icon.png` - const fileIcon = document.createElement('img') - fileIcon.classList.add('file-icon') - fileIcon.src = `${fileIconUrl}` - - fileIconContainer.appendChild(fileIcon) - - const fileInfoContainer = document.createElement('div') - fileInfoContainer.classList.add('attachment-info') - - const fileNameContainer = document.createElement('p') - fileNameContainer.classList.add('attachment-name') - fileNameContainer.textContent = fileName - - const fileSizeContainer = document.createElement('p') - fileSizeContainer.classList.add('attachment-size') - fileSizeContainer.textContent = fileSize - - fileInfoContainer.appendChild(fileNameContainer) - fileInfoContainer.appendChild(fileSizeContainer) - - fileContainer.appendChild(fileIconContainer) - fileContainer.appendChild(fileInfoContainer) - - const repliedFileContainer = document.createElement('div') - repliedFileContainer.setAttribute('id', repliedFileID) - repliedFileContainer.classList.add('file-container') - - const repliedFileIconContainer = document.createElement('div') - repliedFileIconContainer.classList.add('file-icon-container') - - const repliedFileIconUrl = `/img/file-icon.png` - const repliedFileIcon = document.createElement('img') - repliedFileIcon.classList.add('file-icon') - repliedFileIcon.src = `${repliedFileIconUrl}` - - repliedFileIconContainer.appendChild(repliedFileIcon) - - const repliedFileInfoContainer = document.createElement('div') - repliedFileInfoContainer.classList.add('attachment-info') - - const repliedFileNameContainer = document.createElement('p') - repliedFileNameContainer.classList.add('attachment-name') - repliedFileNameContainer.textContent = repliedFileName - - const repliedFileSizeContainer = document.createElement('p') - repliedFileSizeContainer.classList.add('attachment-size') - repliedFileSizeContainer.textContent = repliedFileSize - - repliedFileInfoContainer.appendChild(repliedFileNameContainer) - repliedFileInfoContainer.appendChild(repliedFileSizeContainer) - - repliedFileContainer.appendChild(repliedFileIconContainer) - repliedFileContainer.appendChild(repliedFileInfoContainer) - - if (repliedMessage - && !haveRepliedImage - && !hasRepliedImageDeleted - && !haveRepliedGif - && !hasRepliedGifDeleted - && !haveRepliedAttachment - && !hasRepliedAttachmentDeleted - && !haveRepliedFile - && !hasRepliedFileDeleted - ) { - repliedtodata.appendChild(repliedtoname) - repliedtodata.appendChild(repliedtomessage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(repliedtodata) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (repliedMessage - && haveRepliedImage - && !hasRepliedImageDeleted - && !haveRepliedGif - && !hasRepliedGifDeleted - && !haveRepliedAttachment - && !hasRepliedAttachmentDeleted - && !haveRepliedFile - && !hasRepliedFileDeleted - ) { - const repliedImageContainer = document.createElement('div') - repliedImageContainer.setAttribute('id', repliedImageID) - repliedImageContainer.classList.add('image-container') - - const repliedImageUrl = `${nodeUrl}/arbitrary/${repliedImageLink}?async=true` - - const chatRepliedImage = document.createElement('img') - chatRepliedImage.classList.add('chat-replied-img') - chatRepliedImage.src = `${repliedImageUrl}` - chatRepliedImage.onerror = () => { - chatRepliedImage.src = '/img/img-loading.png' - if (repliedImageFetches < 400) { - setTimeout(() => { - repliedImageFetches = repliedImageFetches + 1 - chatRepliedImage.src = `${repliedImageUrl}` - }, 750) - } else { - chatRepliedImage.src = '/img/chain.png' - } - } - - repliedImageContainer.appendChild(chatRepliedImage) - - repliedtodata.appendChild(repliedtoname) - repliedtodata.appendChild(repliedImageContainer) - repliedtodata.appendChild(repliedtomessage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(repliedtodata) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (repliedMessage - && haveRepliedImage - && hasRepliedImageDeleted - && !haveRepliedGif - && !hasRepliedGifDeleted - && !haveRepliedAttachment - && !hasRepliedAttachmentDeleted - && !haveRepliedFile - && !hasRepliedFileDeleted - ) { - contentDeltedText.textContent = imageDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - contentDeltedContainer.appendChild(contentDeltedInfo) - - repliedtodata.appendChild(repliedtoname) - repliedtodata.appendChild(contentDeltedContainer) - repliedtodata.appendChild(repliedtomessage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(repliedtodata) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (repliedMessage - && !haveRepliedImage - && !hasRepliedImageDeleted - && haveRepliedGif - && !hasRepliedGifDeleted - && !haveRepliedAttachment - && !hasRepliedAttachmentDeleted - && !haveRepliedFile - && !hasRepliedFileDeleted - ) { - const repliedImageContainer = document.createElement('div') - repliedImageContainer.setAttribute('id', repliedGifID) - repliedImageContainer.classList.add('image-container') - - const repliedGifUrl = `${nodeUrl}/arbitrary/${repliedGifLink}?async=true` - - const chatRepliedImage = document.createElement('img') - chatRepliedImage.classList.add('chat-replied-img') - chatRepliedImage.src = `${repliedGifUrl}` - chatRepliedImage.onerror = () => { - chatRepliedImage.src = '/img/img-loading.png' - if (repliedImageFetches < 400) { - setTimeout(() => { - repliedImageFetches = repliedImageFetches + 1 - chatRepliedImage.src = `${repliedGifUrl}` - }, 750) - } else { - chatRepliedImage.src = '/img/chain.png' - } - } - - repliedImageContainer.appendChild(chatRepliedImage) - - repliedtodata.appendChild(repliedtoname) - repliedtodata.appendChild(repliedImageContainer) - repliedtodata.appendChild(repliedtomessage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(repliedtodata) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (repliedMessage - && !haveRepliedImage - && !hasRepliedImageDeleted - && haveRepliedGif - && hasRepliedGifDeleted - && !haveRepliedAttachment - && !hasRepliedAttachmentDeleted - && !haveRepliedFile - && !hasRepliedFileDeleted - ) { - contentDeltedText.textContent = gifDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - contentDeltedContainer.appendChild(contentDeltedInfo) - - repliedtodata.appendChild(repliedtoname) - repliedtodata.appendChild(contentDeltedContainer) - repliedtodata.appendChild(repliedtomessage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(repliedtodata) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (repliedMessage - && !haveRepliedImage - && !hasRepliedImageDeleted - && !haveRepliedGif - && !hasRepliedGifDeleted - && haveRepliedAttachment - && !hasRepliedAttachmentDeleted - && !haveRepliedFile - && !hasRepliedFileDeleted - ) { - repliedtodata.appendChild(repliedtoname) - repliedtodata.appendChild(repliedAttachmentContainer) - repliedtodata.appendChild(repliedtomessage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(repliedtodata) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (repliedMessage - && !haveRepliedImage - && !hasRepliedImageDeleted - && !haveRepliedGif - && !hasRepliedGifDeleted - && haveRepliedAttachment - && hasRepliedAttachmentDeleted - && !haveRepliedFile - && !hasRepliedFileDeleted - ) { - contentDeltedText.textContent = attachmentDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - contentDeltedContainer.appendChild(contentDeltedInfo) - - repliedtodata.appendChild(repliedtoname) - repliedtodata.appendChild(contentDeltedContainer) - repliedtodata.appendChild(repliedtomessage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(repliedtodata) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (repliedMessage - && !haveRepliedImage - && !hasRepliedImageDeleted - && !haveRepliedGif - && !hasRepliedGifDeleted - && !haveRepliedAttachment - && !hasRepliedAttachmentDeleted - && haveRepliedFile - && !hasRepliedFileDeleted - ) { - repliedtodata.appendChild(repliedtoname) - repliedtodata.appendChild(repliedFileContainer) - repliedtodata.appendChild(repliedtomessage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(repliedtodata) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (repliedMessage - && !haveRepliedImage - && !hasRepliedImageDeleted - && !haveRepliedGif - && !hasRepliedGifDeleted - && !haveRepliedAttachment - && !hasRepliedAttachmentDeleted - && haveRepliedFile - && hasRepliedFileDeleted - ) { - contentDeltedText.textContent = fileDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - contentDeltedContainer.appendChild(contentDeltedInfo) - - repliedtodata.appendChild(repliedtoname) - repliedtodata.appendChild(contentDeltedContainer) - repliedtodata.appendChild(repliedtomessage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(repliedtodata) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (haveImage && !hasImageDeleted) { - const imageContainer = document.createElement('div') - imageContainer.setAttribute('id', messageImageID) - imageContainer.classList.add('image-container') - - const imageUrl = `${nodeUrl}/arbitrary/${imageLink}?async=true` - const chatImage = document.createElement('img') - chatImage.classList.add('chat-img') - chatImage.src = `${imageUrl}` - chatImage.onerror = () => { - chatImage.src = '/img/img-loading.png' - if (imageFetches < 400) { - setTimeout(() => { - imageFetches = imageFetches + 1 - chatImage.src = `${imageUrl}` - }, 750) - } else { - chatImage.src = '/img/chain.png' - } - } - - imageContainer.appendChild(chatImage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(imageContainer) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (haveImage && hasImageDeleted) { - contentDeltedText.textContent = imageDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - contentDeltedContainer.appendChild(contentDeltedInfo) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(contentDeltedContainer) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (haveGif && !hasGifDeleted) { - const imageContainer = document.createElement('div') - imageContainer.setAttribute('id', messageGifID) - imageContainer.classList.add('image-container') - - const gifUrl = `${nodeUrl}/arbitrary/${gifLink}?async=true` - const chatImage = document.createElement('img') - chatImage.classList.add('chat-img') - chatImage.src = `${gifUrl}` - chatImage.onerror = () => { - chatImage.src = '/img/img-loading.png' - if (imageFetches < 400) { - setTimeout(() => { - imageFetches = imageFetches + 1 - chatImage.src = `${gifUrl}` - }, 750) - } else { - chatImage.src = '/img/chain.png' - } - } - - imageContainer.appendChild(chatImage) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(imageContainer) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (haveGif && hasGifDeleted) { - contentDeltedText.textContent = gifDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - contentDeltedContainer.appendChild(contentDeltedInfo) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(contentDeltedContainer) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (haveAttachment && !hasAttachmentDeleted) { - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(attachmentContainer) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (haveAttachment && hasAttachmentDeleted) { - contentDeltedText.textContent = attachmentDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - contentDeltedContainer.appendChild(contentDeltedInfo) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(contentDeltedContainer) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (haveFile && !hasFileDeleted) { - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(fileContainer) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else if (haveFile && hasFileDeleted) { - contentDeltedText.textContent = fileDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - contentDeltedContainer.appendChild(contentDeltedInfo) - - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(contentDeltedContainer) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } else { - subcontainer2.appendChild(userinfo) - subcontainer2.appendChild(messageContainer) - subcontainer2.appendChild(messageTimeContainer) - - subcontainer1.appendChild(avatarContainer) - subcontainer1.appendChild(subcontainer2) - - chatElement.appendChild(subcontainer1) - - chatGridContainer.appendChild(chatElement) - } - }) - - if (scroll) { - this.scrollChatToEnd() - } - } - } - timeIsoString(timestamp) { let myTimestamp = timestamp === undefined ? 1587560082346 : timestamp let time = new Date(myTimestamp) @@ -4226,7 +2836,7 @@ class GroupManagement extends LitElement { 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}/arbitrary/THUMBNAIL/${name}/qortal_avatar?async=true}` - return html`` + return html`` } setCreateGroupTxNotification(tx) { @@ -5533,292 +4143,6 @@ class GroupManagement extends LitElement { if (!arr) { return true } return arr.length === 0 } - - round(number) { - return (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8) - } - - async fetchChatMessages(chatId) { - const restartGroupWebSocket = () => { - let groupChatId = Number(chatId) - setTimeout(() => initGroup(groupChatId, 50)) - } - - const initGroup = (gId) => { - let timeoutId - let groupId = Number(gId) - let groupSocketTimeout - let groupSocketLink - let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - let nodeUrl = myNode.domain + ":" + myNode.port - - if (window.parent.location.protocol === "https:") { - // WSS is over https - groupSocketLink = `wss://${nodeUrl}/websockets/chat/messages?txGroupId=${groupId}&encoding=BASE64&limit=1` - } else { - // WSS is over http - groupSocketLink = `ws://${nodeUrl}/websockets/chat/messages?txGroupId=${groupId}&encoding=BASE64&limit=1` - } - - // Set the websocket - this.webSocket = new WebSocket(groupSocketLink) - - // When websocket is open ping every 50ms - this.webSocket.onopen = () => { - setTimeout(pingGroupSocket, 50) - } - - // Websocket message Event - this.webSocket.onmessage = async (e) => { - if (e.data === 'pong') { - clearTimeout(timeoutId) - groupSocketTimeout = setTimeout(pingGroupSocket, 45000) - return - } - - try { - if (e.data) { - let newMessage = [] - let newDecodedArray = [] - - newMessage = JSON.parse(e.data) - - // Check if message is new one (as first call is last message from before created array) - if (newMessage[0].timestamp > this.chatMessageArray[this.chatMessageArray.length - 1].timestamp) { - newMessage.forEach(item => { - let newDecodedMessageObj = {} - let decodedMessage = this.decodeMessage(item.data) - let checkEdited = JSON.parse(decodedMessage) - let editedString = '( ' + get('chatpage.cchange68') + ' )' - let imageDeletedString = get('chatpage.cchange80') - let gifDeletedString = get('chatpage.cchange107') - let attachmentDeletedString = get('chatpage.cchange82') - let fileDeletedString = get('chatpage.cchange102') - - // Check if message got edited - if (checkEdited.isEdited) { - let refSignature = '' - let refTimeSignature = '' - let refEditedMessage = '' - let messageEditedID = '' - - refSignature = item.chatReference - refTimeSignature = 'time-' + item.chatReference - refEditedMessage = generateHTML(checkEdited.messageText, [StarterKit, Underline, Highlight]) - messageEditedID = 'edited-' + item.chatReference - - const messageEditedString = document.createElement('span') - messageEditedString.setAttribute('id', messageEditedID) - messageEditedString.classList.add('message-data-edited') - messageEditedString.textContent = editedString - - this.shadowRoot.getElementById(refSignature).innerHTML = refEditedMessage - this.shadowRoot.getElementById(refTimeSignature).classList.remove('message-data-time-edited') - this.shadowRoot.getElementById(refTimeSignature).classList.remove('message-data-time') - this.shadowRoot.getElementById(refTimeSignature).classList.add('message-data-time-edited') - - if (this.shadowRoot.getElementById(refTimeSignature).childNodes.length > 1) { - this.shadowRoot.getElementById(refTimeSignature).removeChild(messageEditedString) - } - - this.shadowRoot.getElementById(refTimeSignature).insertBefore(messageEditedString, this.shadowRoot.getElementById(refTimeSignature).firstChild) - - this.chatMessageArray.find(v => v.signature === refSignature).decodedMessage = decodedMessage - } else if (checkEdited.isImageDeleted) { - let refSignature = '' - let refImageSignature = '' - let repImageSignature = '' - - refSignature = item.chatReference - refImageSignature = 'image-' + item.chatReference - repImageSignature = 'repimage-' + item.chatReference - - const contentDeltedInfo = document.createElement('div') - contentDeltedInfo.classList.add('attachment-info') - - const contentDeltedText = document.createElement('p') - contentDeltedText.classList.add('attachment-deleted') - contentDeltedText.textContent = imageDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - - if (this.shadowRoot.getElementById(refImageSignature)) { - this.shadowRoot.getElementById(refImageSignature).innerHTML = '' - this.shadowRoot.getElementById(refImageSignature).classList.remove('image-container') - this.shadowRoot.getElementById(refImageSignature).classList.add('attachment-container') - this.shadowRoot.getElementById(refImageSignature).appendChild(contentDeltedInfo) - } - - if (this.shadowRoot.getElementById(repImageSignature)) { - this.shadowRoot.getElementById(repImageSignature).innerHTML = '' - this.shadowRoot.getElementById(repImageSignature).classList.remove('image-container') - this.shadowRoot.getElementById(repImageSignature).classList.add('attachment-container') - this.shadowRoot.getElementById(repImageSignature).appendChild(contentDeltedInfo) - } - - this.chatMessageArray.find(v => v.signature === refSignature).decodedMessage = decodedMessage - } else if (checkEdited.isGifDeleted) { - let refSignature = '' - let refGifSignature = '' - let repGifSignature = '' - - refSignature = item.chatReference - refGifSignature = 'gif-' + item.chatReference - repGifSignature = 'repgif-' + item.chatReference - - const contentDeltedInfo = document.createElement('div') - contentDeltedInfo.classList.add('attachment-info') - - const contentDeltedText = document.createElement('p') - contentDeltedText.classList.add('attachment-deleted') - contentDeltedText.textContent = gifDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - - if (this.shadowRoot.getElementById(refGifSignature)) { - this.shadowRoot.getElementById(refGifSignature).innerHTML = '' - this.shadowRoot.getElementById(refGifSignature).classList.remove('image-container') - this.shadowRoot.getElementById(refGifSignature).classList.add('attachment-container') - this.shadowRoot.getElementById(refGifSignature).appendChild(contentDeltedInfo) - } - - if (this.shadowRoot.getElementById(repGifSignature)) { - this.shadowRoot.getElementById(repGifSignature).innerHTML = '' - this.shadowRoot.getElementById(repGifSignature).classList.remove('image-container') - this.shadowRoot.getElementById(repGifSignature).classList.add('attachment-container') - this.shadowRoot.getElementById(repGifSignature).appendChild(contentDeltedInfo) - } - - this.chatMessageArray.find(v => v.signature === refSignature).decodedMessage = decodedMessage - } else if (checkEdited.isAttachmentDeleted) { - let refSignature = '' - let refAttachmentSignature = '' - let repAttachmentSignature = '' - - refSignature = item.chatReference - refAttachmentSignature = 'attachment-' + item.chatReference - repAttachmentSignature = 'repattachment-' + item.chatReference - - const contentDeltedInfo = document.createElement('div') - contentDeltedInfo.classList.add('attachment-info') - - const contentDeltedText = document.createElement('p') - contentDeltedText.classList.add('attachment-deleted') - contentDeltedText.textContent = attachmentDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - - if (this.shadowRoot.getElementById(refAttachmentSignature)) { - this.shadowRoot.getElementById(refAttachmentSignature).innerHTML = '' - this.shadowRoot.getElementById(refAttachmentSignature).appendChild(contentDeltedInfo) - } - - if (this.shadowRoot.getElementById(repAttachmentSignature)) { - this.shadowRoot.getElementById(repAttachmentSignature).innerHTML = '' - this.shadowRoot.getElementById(repAttachmentSignature).appendChild(contentDeltedInfo) - } - - this.chatMessageArray.find(v => v.signature === refSignature).decodedMessage = decodedMessage - } else if (checkEdited.isFileDeleted) { - let refSignature = '' - let refFileSignature = '' - let repFileSignature = '' - - refSignature = item.chatReference - refFileSignature = 'file-' + item.chatReference - repFileSignature = 'repfile-' + item.chatReference - - const contentDeltedInfo = document.createElement('div') - contentDeltedInfo.classList.add('attachment-info') - - const contentDeltedText = document.createElement('p') - contentDeltedText.classList.add('attachment-deleted') - contentDeltedText.textContent = fileDeletedString - - contentDeltedInfo.appendChild(contentDeltedText) - - const contentDeltedInfoRep = document.createElement('div') - contentDeltedInfoRep.classList.add('attachment-info') - - const contentDeltedTextRep = document.createElement('p') - contentDeltedTextRep.classList.add('attachment-deleted') - contentDeltedTextRep.textContent = fileDeletedString - - contentDeltedInfoRep.appendChild(contentDeltedTextRep) - - if (this.shadowRoot.getElementById(refFileSignature)) { - this.shadowRoot.getElementById(refFileSignature).innerHTML = '' - this.shadowRoot.getElementById(refFileSignature).classList.remove('file-container') - this.shadowRoot.getElementById(refFileSignature).classList.add('attachment-container') - this.shadowRoot.getElementById(refFileSignature).appendChild(contentDeltedInfo) - } - - if (this.shadowRoot.getElementById(repFileSignature)) { - this.shadowRoot.getElementById(repFileSignature).innerHTML = '' - this.shadowRoot.getElementById(repFileSignature).classList.remove('file-container') - this.shadowRoot.getElementById(repFileSignature).classList.add('attachment-container') - this.shadowRoot.getElementById(repFileSignature).appendChild(contentDeltedInfoRep) - } - - this.chatMessageArray.find(v => v.signature === refSignature).decodedMessage = decodedMessage - } else { - const newMessageObj = { - timestamp: item.timestamp, - txGroupId: item.txGroupId, - reference: item.reference, - senderPublicKey: item.senderPublicKey, - sender: item.sender, - senderName: item.senderName, - encoding: item.encoding, - isText: item.isText, - isEncrypted: item.isEncrypted, - signature: item.signature - } - - newDecodedMessageObj = { ...newMessageObj, decodedMessage } - - newDecodedArray.push(newDecodedMessageObj) - - this.chatMessageArray.push(newDecodedMessageObj) - this.renderChatMessagesGrid(newDecodedArray, true) - } - }) - } - } - } catch (error) { /* empty */ } - } - - // Websocket close event - this.webSocket.onclose = (e) => { - clearTimeout(groupSocketTimeout) - if (e.reason === 'closed preview') return - restartGroupWebSocket() - } - - // Websocket error event - this.webSocket.onerror = () => { - clearTimeout(groupSocketTimeout) - this.webSocket.close() - } - - // Close the WebSocket connection if no pong message is received within 5 seconds. - const pingGroupSocket = () => { - this.webSocket.send('ping') - timeoutId = setTimeout(() => { - this.webSocket.close() - clearTimeout(groupSocketTimeout) - }, 5000) - } - } - - // Init the websocket - if (chatId !== undefined) { - let groupChatId = Number(chatId) - initGroup(groupChatId) - } else { - // ... Websocket not started - } - } } window.customElements.define('group-management', GroupManagement)