mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-06-14 20:11:22 +00:00
Merge pull request #77 from nbenaglia/feature/dom-exception
dom exception and other errors
This commit is contained in:
commit
c7ed7534cf
@ -440,7 +440,7 @@ const handleNotificationDirect = async (directs) => {
|
||||
let isFocused;
|
||||
const wallet = await getSaveWallet();
|
||||
const address = wallet.address0;
|
||||
let isDisableNotifications =
|
||||
const isDisableNotifications =
|
||||
(await getUserSettings({ key: 'disable-push-notifications' })) || false;
|
||||
const dataDirects = directs.filter((direct) => direct?.sender !== address);
|
||||
try {
|
||||
@ -1281,7 +1281,6 @@ export async function addUserSettings({ keyValue }) {
|
||||
getData<any>(`${address}-userSettings`)
|
||||
.then((storedData) => {
|
||||
storedData = storedData || {}; // Initialize if no data found
|
||||
|
||||
storedData[key] = value; // Update the key-value pair within stored data
|
||||
|
||||
// Save updated structure back to localStorage
|
||||
@ -1734,7 +1733,7 @@ export async function decryptSingleFunc({
|
||||
secretKeyObject,
|
||||
skipDecodeBase64,
|
||||
}) {
|
||||
let holdMessages = [];
|
||||
const holdMessages = [];
|
||||
|
||||
for (const message of messages) {
|
||||
try {
|
||||
@ -1744,9 +1743,11 @@ export async function decryptSingleFunc({
|
||||
skipDecodeBase64,
|
||||
});
|
||||
|
||||
const decryptToUnit8Array = base64ToUint8Array(res);
|
||||
const responseData = uint8ArrayToObject(decryptToUnit8Array);
|
||||
holdMessages.push({ ...message, decryptedData: responseData });
|
||||
if (res) {
|
||||
const decryptToUnit8Array = base64ToUint8Array(res);
|
||||
const responseData = uint8ArrayToObject(decryptToUnit8Array);
|
||||
holdMessages.push({ ...message, decryptedData: responseData });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
@ -1758,7 +1759,7 @@ export async function decryptSingleForPublishes({
|
||||
secretKeyObject,
|
||||
skipDecodeBase64,
|
||||
}) {
|
||||
let holdMessages = [];
|
||||
const holdMessages = [];
|
||||
|
||||
for (const message of messages) {
|
||||
try {
|
||||
@ -2888,6 +2889,7 @@ export async function getTimestampEnterChat() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTimestampMention() {
|
||||
const wallet = await getSaveWallet();
|
||||
const address = wallet.address0;
|
||||
@ -2900,6 +2902,7 @@ export async function getTimestampMention() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTimestampGroupAnnouncement() {
|
||||
const wallet = await getSaveWallet();
|
||||
const address = wallet.address0;
|
||||
@ -2996,6 +2999,7 @@ async function getGroupData() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export async function getGroupDataSingle(groupId) {
|
||||
const wallet = await getSaveWallet();
|
||||
const address = wallet.address0;
|
||||
@ -3266,6 +3270,7 @@ function setupMessageListener() {
|
||||
break;
|
||||
case 'updateThreadActivity':
|
||||
updateThreadActivityCase(request, event);
|
||||
break;
|
||||
case 'decryptGroupEncryption':
|
||||
decryptGroupEncryptionCase(request, event);
|
||||
break;
|
||||
@ -3387,7 +3392,7 @@ const checkGroupList = async () => {
|
||||
.filter(
|
||||
(item) =>
|
||||
item?.name !== 'extension-proxy' &&
|
||||
item?.address !== 'QSMMGSgysEuqDCuLw3S4cHrQkBrh3vP3VH'
|
||||
item?.address !== 'QSMMGSgysEuqDCuLw3S4cHrQkBrh3vP3VH' // TODO put address in a specific file
|
||||
)
|
||||
.sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));
|
||||
|
||||
@ -3411,7 +3416,7 @@ export const checkNewMessages = async () => {
|
||||
myName = userData.name;
|
||||
}
|
||||
|
||||
let newAnnouncements = [];
|
||||
const newAnnouncements = [];
|
||||
const activeData = (await getStoredData('active-groups-directs')) || {
|
||||
groups: [],
|
||||
directs: [],
|
||||
@ -3441,6 +3446,7 @@ export const checkNewMessages = async () => {
|
||||
const latestMessage = responseData.filter(
|
||||
(pub) => pub?.name !== myName
|
||||
)[0];
|
||||
|
||||
if (!latestMessage) {
|
||||
return; // continue to the next group
|
||||
}
|
||||
@ -3463,7 +3469,8 @@ export const checkNewMessages = async () => {
|
||||
}
|
||||
})
|
||||
);
|
||||
let isDisableNotifications =
|
||||
|
||||
const isDisableNotifications =
|
||||
(await getUserSettings({ key: 'disable-push-notifications' })) || false;
|
||||
|
||||
if (
|
||||
@ -3611,8 +3618,8 @@ export const checkThreads = async (bringBack) => {
|
||||
if (userData?.name) {
|
||||
myName = userData.name;
|
||||
}
|
||||
let newAnnouncements = [];
|
||||
let dataToBringBack = [];
|
||||
const newAnnouncements = [];
|
||||
const dataToBringBack = [];
|
||||
const threadActivity = await getThreadActivity();
|
||||
if (!threadActivity) return null;
|
||||
|
||||
@ -3627,7 +3634,6 @@ export const checkThreads = async (bringBack) => {
|
||||
for (const thread of selectedThreads) {
|
||||
try {
|
||||
const identifier = `thmsg-${thread?.threadId}`;
|
||||
const name = thread?.qortalName;
|
||||
const endpoint = await getArbitraryEndpoint();
|
||||
const url = await createEndpoint(
|
||||
`${endpoint}?mode=ALL&service=DOCUMENT&identifier=${identifier}&limit=1&includemetadata=false&offset=${0}&reverse=true&prefix=true`
|
||||
@ -3643,7 +3649,6 @@ export const checkThreads = async (bringBack) => {
|
||||
const latestMessage = responseData.filter(
|
||||
(pub) => pub?.name !== myName
|
||||
)[0];
|
||||
// const latestMessage = responseData[0]
|
||||
|
||||
if (!latestMessage) {
|
||||
continue;
|
||||
@ -3717,7 +3722,7 @@ export const checkThreads = async (bringBack) => {
|
||||
'_type=thread-post' +
|
||||
`_data=${JSON.stringify(newAnnouncements[0])}`
|
||||
);
|
||||
let isDisableNotifications =
|
||||
const isDisableNotifications =
|
||||
(await getUserSettings({ key: 'disable-push-notifications' })) || false;
|
||||
if (!isDisableNotifications) {
|
||||
// Check user settings to see if notifications are disabled
|
||||
|
@ -7,6 +7,15 @@ import { ChatOptions } from './ChatOptions';
|
||||
import ErrorBoundary from '../../common/ErrorBoundary';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type ReactionItem = {
|
||||
sender: string;
|
||||
senderName?: string;
|
||||
};
|
||||
|
||||
export type ReactionsMap = {
|
||||
[reactionType: string]: ReactionItem[];
|
||||
};
|
||||
|
||||
export const ChatList = ({
|
||||
initialMessages,
|
||||
myAddress,
|
||||
@ -236,7 +245,7 @@ export const ChatList = ({
|
||||
let message = messages[index] || null; // Safeguard against undefined
|
||||
let replyIndex = -1;
|
||||
let reply = null;
|
||||
let reactions = null;
|
||||
let reactions: ReactionsMap | null = null;
|
||||
let isUpdating = false;
|
||||
|
||||
try {
|
||||
@ -444,13 +453,13 @@ export const ChatList = ({
|
||||
|
||||
{enableMentions && (hasSecretKey || isPrivate === false) && (
|
||||
<ChatOptions
|
||||
openQManager={openQManager}
|
||||
messages={messages}
|
||||
goToMessage={goToMessage}
|
||||
members={members}
|
||||
myName={myName}
|
||||
selectedGroup={selectedGroup}
|
||||
isPrivate={isPrivate}
|
||||
members={members}
|
||||
messages={messages}
|
||||
myName={myName}
|
||||
openQManager={openQManager}
|
||||
selectedGroup={selectedGroup}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
|
@ -25,7 +25,6 @@ import {
|
||||
AppsSearchRight,
|
||||
} from '../Apps/Apps-styles';
|
||||
import IconClearInput from '../../assets/svgs/ClearInput.svg';
|
||||
import { CellMeasurerCache } from 'react-virtualized';
|
||||
import { getBaseApiReact } from '../../App';
|
||||
import { MessageDisplay } from './MessageDisplay';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
@ -36,6 +35,7 @@ import { generateHTML } from '@tiptap/react';
|
||||
import ErrorBoundary from '../../common/ErrorBoundary';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { isHtmlString } from '../../utils/chat';
|
||||
import TextStyle from '@tiptap/extension-text-style';
|
||||
|
||||
const extractTextFromHTML = (htmlString = '') => {
|
||||
return convert(htmlString, {
|
||||
@ -43,11 +43,6 @@ const extractTextFromHTML = (htmlString = '') => {
|
||||
})?.toLowerCase();
|
||||
};
|
||||
|
||||
const cache = new CellMeasurerCache({
|
||||
fixedWidth: true,
|
||||
defaultHeight: 50,
|
||||
});
|
||||
|
||||
export const ChatOptions = ({
|
||||
messages: untransformedMessages,
|
||||
goToMessage,
|
||||
@ -86,6 +81,7 @@ export const ChatOptions = ({
|
||||
Underline,
|
||||
Highlight,
|
||||
Mention,
|
||||
TextStyle,
|
||||
]);
|
||||
return {
|
||||
...item,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { EditorProvider, useCurrentEditor } from '@tiptap/react';
|
||||
import { Editor, EditorProvider, useCurrentEditor } from '@tiptap/react';
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
import { Color } from '@tiptap/extension-color';
|
||||
import ListItem from '@tiptap/extension-list-item';
|
||||
@ -34,16 +34,6 @@ import { fileToBase64 } from '../../utils/fileReading/index.js';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import i18n from 'i18next';
|
||||
|
||||
function textMatcher(doc, from) {
|
||||
const textBeforeCursor = doc.textBetween(0, from, ' ', ' ');
|
||||
const match = textBeforeCursor.match(/@[\w]*$/); // Match '@' followed by valid characters
|
||||
if (!match) return null;
|
||||
|
||||
const start = from - match[0].length;
|
||||
const query = match[0];
|
||||
return { start, query };
|
||||
}
|
||||
|
||||
const MenuBar = memo(
|
||||
({
|
||||
setEditorRef,
|
||||
@ -361,8 +351,8 @@ const MenuBar = memo(
|
||||
);
|
||||
|
||||
const extensions = [
|
||||
TextStyle,
|
||||
Color.configure({ types: [TextStyle.name, ListItem.name] }),
|
||||
TextStyle.configure({ types: [ListItem.name] }),
|
||||
StarterKit.configure({
|
||||
bulletList: {
|
||||
keepMarks: true,
|
||||
@ -383,11 +373,26 @@ const extensions = [
|
||||
|
||||
const content = ``;
|
||||
|
||||
export default ({
|
||||
type TiptapProps = {
|
||||
setEditorRef: (editorInstance: Editor | null) => void;
|
||||
onEnter: () => void | Promise<void>;
|
||||
disableEnter?: boolean;
|
||||
isChat?: boolean;
|
||||
maxHeightOffset?: number;
|
||||
overrideMobile?: boolean;
|
||||
customEditorHeight?: number | null;
|
||||
setIsFocusedParent: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
isFocusedParent: boolean;
|
||||
membersWithNames: unknown[];
|
||||
enableMentions?: boolean;
|
||||
insertImage: (image: any) => void;
|
||||
};
|
||||
|
||||
const Tiptap = ({
|
||||
setEditorRef,
|
||||
onEnter,
|
||||
disableEnter,
|
||||
isChat,
|
||||
disableEnter = false,
|
||||
isChat = false,
|
||||
maxHeightOffset,
|
||||
setIsFocusedParent,
|
||||
isFocusedParent,
|
||||
@ -396,7 +401,7 @@ export default ({
|
||||
membersWithNames,
|
||||
enableMentions,
|
||||
insertImage,
|
||||
}) => {
|
||||
}: TiptapProps) => {
|
||||
const theme = useTheme();
|
||||
const [isDisabledEditorEnter, setIsDisabledEditorEnter] = useAtom(
|
||||
isDisabledEditorEnterAtom
|
||||
@ -623,3 +628,5 @@ export default ({
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tiptap;
|
||||
|
@ -59,7 +59,7 @@ export const Embed = ({ embedLink }) => {
|
||||
const [openSnack, setOpenSnack] = useState(false);
|
||||
const [infoSnack, setInfoSnack] = useState(null);
|
||||
const [external, setExternal] = useState(null);
|
||||
const [imageUrl, setImageUrl] = useState('');
|
||||
const [imageUrl, setImageUrl] = useState(null);
|
||||
const [parsedData, setParsedData] = useState(null);
|
||||
const setBlobs = useSetAtom(blobControllerAtom);
|
||||
const [selectedGroupId] = useAtom(selectedGroupIdAtom);
|
||||
|
@ -209,9 +209,8 @@ export const ImageCard = ({
|
||||
);
|
||||
};
|
||||
|
||||
export function ImageViewer({ src, alt = '' }) {
|
||||
export function ImageViewer({ src = null, alt = '' }) {
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
const handleOpenFullscreen = () => setIsFullscreen(true);
|
||||
const handleCloseFullscreen = () => setIsFullscreen(false);
|
||||
const theme = useTheme();
|
||||
|
@ -276,15 +276,13 @@ export async function getNameInfo(address: string) {
|
||||
}
|
||||
|
||||
export const getGroupAdmins = async (groupNumber: number) => {
|
||||
// const validApi = await findUsableApi();
|
||||
|
||||
const response = await fetch(
|
||||
`${getBaseApiReact()}/groups/members/${groupNumber}?limit=0&onlyAdmins=true`
|
||||
);
|
||||
const groupData = await response.json();
|
||||
let members: any = [];
|
||||
let membersAddresses = [];
|
||||
let both = [];
|
||||
const members: any = [];
|
||||
const membersAddresses = [];
|
||||
const both = [];
|
||||
|
||||
const getMemNames = groupData?.members?.map(async (member) => {
|
||||
if (member?.member) {
|
||||
@ -600,10 +598,11 @@ export const Group = ({
|
||||
}, [myAddress]);
|
||||
|
||||
const getGroupOwner = async (groupId) => {
|
||||
if (groupId == '0') return; // general group has id=0
|
||||
try {
|
||||
const url = `${getBaseApiReact()}/groups/${groupId}`;
|
||||
const response = await fetch(url);
|
||||
let data = await response.json();
|
||||
const data = await response.json();
|
||||
|
||||
const name = await getNameInfo(data?.owner);
|
||||
if (name) {
|
||||
@ -742,7 +741,7 @@ export const Group = ({
|
||||
data = await res.text();
|
||||
}
|
||||
|
||||
const decryptedKey: any = await decryptResource(data);
|
||||
const decryptedKey: any = await decryptResource(data, null);
|
||||
const dataint8Array = base64ToUint8Array(decryptedKey.data);
|
||||
const decryptedKeyToObject = uint8ArrayToObject(dataint8Array);
|
||||
|
||||
@ -877,6 +876,7 @@ export const Group = ({
|
||||
};
|
||||
|
||||
const getOwnerNameForGroup = async (owner: string, groupId: string) => {
|
||||
if (groupId == '0') return; // general group has id=0
|
||||
try {
|
||||
if (!owner) return;
|
||||
if (groupsOwnerNamesRef.current[groupId]) return;
|
||||
@ -899,7 +899,7 @@ export const Group = ({
|
||||
const url = `${getBaseApiReact()}/groups/member/${address}`;
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error('Cannot get group properties');
|
||||
let data = await response.json();
|
||||
const data = await response.json();
|
||||
const transformToObject = data.reduce((result, item) => {
|
||||
result[item.groupId] = item;
|
||||
return result;
|
||||
|
@ -244,6 +244,7 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => {
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{wallets?.length > 0 && (
|
||||
<List
|
||||
sx={{
|
||||
@ -442,20 +443,22 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})}
|
||||
</Button>
|
||||
|
||||
<LoadingButton
|
||||
loading={isLoadingEncryptSeed}
|
||||
autoFocus
|
||||
disabled={!seedValue || !seedName || !password}
|
||||
variant="contained"
|
||||
loading={isLoadingEncryptSeed}
|
||||
onClick={() => {
|
||||
if (!seedValue || !seedName || !password) return;
|
||||
onOk({ seedValue, seedName, password });
|
||||
}}
|
||||
autoFocus
|
||||
variant="contained"
|
||||
>
|
||||
{t('core:action.add', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})}
|
||||
</LoadingButton>
|
||||
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '14px',
|
||||
|
@ -117,7 +117,7 @@
|
||||
"digital_id": "su billetera es como su ID digital en Qortal, y es cómo iniciará sesión en la interfaz de usuario de Qortal. Sostiene su dirección pública y el nombre Qortal que eventualmente elegirá. Cada transacción que realice está vinculada a su ID, y aquí es donde administra todos sus Qort y otras criptomonedas comercializables en Qortal.",
|
||||
"existing_account": "¿Ya tienes una cuenta Qortal? Ingrese su frase de copia de seguridad secreta aquí para acceder a ella. Esta frase es una de las formas de recuperar su cuenta.",
|
||||
"key_encrypt_admin": "esta clave es cifrar el contenido relacionado con el administrador. Solo los administradores verían contenido encriptado con él.",
|
||||
"key_encrypt_group": "esta clave es cifrar contenido relacionado con el grupo. Este es el único utilizado en esta interfaz de usuario a partir de ahora. Todos los miembros del grupo podrán ver contenido encriptado con esta clave.",
|
||||
"key_encrypt_group": "esta clave es cifrar contenido relacionado con el grupo. Esta es el única utilizada en esta interfaz de usuario a partir de ahora. Todos los miembros del grupo podrán ver contenido encriptado con esta clave.",
|
||||
"new_account": "crear una cuenta significa crear una nueva billetera e ID digital para comenzar a usar Qortal. Una vez que haya hecho su cuenta, puede comenzar a hacer cosas como obtener algo de Qort, comprar un nombre y avatar, publicar videos y blogs, y mucho más.",
|
||||
"new_users": "¡Los nuevos usuarios comienzan aquí!",
|
||||
"safe_place": "¡Guarde su cuenta en un lugar donde la recordará!",
|
||||
|
@ -117,7 +117,7 @@
|
||||
"digital_id": "votre portefeuille est comme votre ID numérique sur Qortal, et c'est comment vous vous connectez à l'interface utilisateur Qortal. Il détient votre adresse publique et le nom Qortal que vous allez éventuellement choisir. Chaque transaction que vous effectuez est liée à votre identifiant, et c'est là que vous gérez tous vos Qort et autres crypto-monnaies négociables sur Qortal.",
|
||||
"existing_account": "vous avez déjà un compte Qortal? Entrez ici votre phrase de sauvegarde secrète pour y accéder. Cette phrase est l'une des façons de récupérer votre compte.",
|
||||
"key_encrypt_admin": "cette clé est de crypter le contenu lié à l'administrateur. Seuls les administrateurs verraient du contenu chiffré avec.",
|
||||
"key_encrypt_group": "cette clé est de chiffrer le contenu lié au groupe. C'est le seul utilisé dans cette interface utilisateur pour l'instant. Tous les membres du groupe pourront voir du contenu crypté avec cette clé.",
|
||||
"key_encrypt_group": "cette clé est de chiffrer le contenu lié au groupe. C'est la seule utilisée dans cette interface utilisateur pour l'instant. Tous les membres du groupe pourront voir du contenu crypté avec cette clé.",
|
||||
"new_account": "la création d'un compte signifie créer un nouvel portefeuille et un nouvel ID numérique pour commencer à utiliser Qortal. Une fois que vous avez créé votre compte, vous pouvez commencer à faire des choses comme obtenir du Qort, acheter un nom et un avatar, publier des vidéos et des blogs, et bien plus encore.",
|
||||
"new_users": "les nouveaux utilisateurs commencent ici!",
|
||||
"safe_place": "enregistrez votre compte dans un endroit où vous vous en souviendrez!",
|
||||
|
@ -95,7 +95,7 @@
|
||||
"your_accounts": "i tuoi conti salvati"
|
||||
},
|
||||
"success": {
|
||||
"reencrypted_secret_key": "chiave segreta recriptata con successo. Potrebbero essere necessari un paio di minuti per propagare le modifiche. Aggiorna il gruppo in 5 minuti."
|
||||
"reencrypted_secret_key": "chiave segreta recriptata con successo. Potrebbero essere necessari un paio di minuti per propagare le modifiche. Aggiorna il gruppo fra 5 minuti."
|
||||
}
|
||||
},
|
||||
"node": {
|
||||
@ -117,12 +117,12 @@
|
||||
"digital_id": "il tuo wallet è come il tuo ID digitale su Qortal ed e verrà usato per accedere a Qortal. Contiene il tuo indirizzo pubblico e il nome Qortal che alla fine sceglierai. Ogni transazione che fai è collegata al tuo ID, nel quale potrai gestire tutte le tue criptovalute Qort e altre criptovalute negoziabili su Qortal.",
|
||||
"existing_account": "hai già un account Qortal? Inserisci qui la tua frase di backup segreta per accedervi. Questa frase è uno dei modi per recuperare il tuo account.",
|
||||
"key_encrypt_admin": "questa chiave crittografa i contenuti relativi ad amministratore. Solo gli amministratori vedranno il contenuto crittografato.",
|
||||
"key_encrypt_group": "questa chiave crittografa i contenuti relativi al gruppo. Questo al momento è l'unico modo usato. Tutti i membri del gruppo saranno in grado di vedere i contenuti crittografati con questa chiave.",
|
||||
"key_encrypt_group": "questa chiave crittografa i contenuti relativi al gruppo. Per ora questa è l'unica utilizzata in quest'interfaccia grafica. Tutti i membri del gruppo saranno in grado di vedere i contenuti crittografati con questa chiave.",
|
||||
"new_account": "la creazione di un account consiste nella creazione di un wallet e di un ID digitale per iniziare a utilizzare Qortal. Una volta creato l'account, potrai iniziare a fare cose come ottenere dei Qort, acquistare un nome e un Avatar, pubblicare video e blog e molto altro.",
|
||||
"new_users": "i nuovi utenti iniziano qui!",
|
||||
"safe_place": "salva il tuo account in un posto da ricordare!",
|
||||
"view_seedphrase": "se si desidera visualizzare la seed phrase, fai clic sulla parola \"seed phrase\" in questo testo. Le seed phrase vengono utilizzate per generare la chiave privata per il tuo account Qortal. Per la sicurezza per impostazione predefinita, le seed phrase non vengono visualizzate se non specificamente scelte.",
|
||||
"wallet_secure": "mantieni al sicuro il tuo file di wallet."
|
||||
"wallet_secure": "mantieni al sicuro il tuo file del wallet."
|
||||
},
|
||||
"wallet": {
|
||||
"password_confirmation": "conferma la password del wallet",
|
||||
|
@ -253,9 +253,9 @@
|
||||
"no_minting_details": "impossibile visualizzare i dettagli di minire sul gateway",
|
||||
"no_notifications": "nessuna nuova notifica",
|
||||
"no_payments": "nessun pagamento",
|
||||
"no_pinned_changes": "attualmente non hai modifiche alle tue app bloccate",
|
||||
"no_pinned_changes": "per ora non ci sono modifiche alle app bloccate",
|
||||
"no_results": "nessun risultato",
|
||||
"one_app_per_name": "nota: attualmente, sono consentiti solo un'app e un sito Web per nome.",
|
||||
"one_app_per_name": "nota: per adesso sono consentiti solo un'app e un sito Web per nome.",
|
||||
"opened": "aperto",
|
||||
"overwrite_qdn": "sovrascrivi a QDN",
|
||||
"password_confirm": "si prega di confermare una password",
|
||||
|
@ -77,28 +77,28 @@
|
||||
"group_encrypted": "gruppo crittografato",
|
||||
"group_invited_you": "{{group}} ti ha invitato",
|
||||
"group_key_created": "creata la prima chiave di gruppo.",
|
||||
"group_member_list_changed": "l'elenco dei membri del gruppo è cambiato. Si prega di ricriptare nuovamente la chiave segreta.",
|
||||
"group_member_list_changed": "l'elenco dei membri del gruppo è cambiato. Si prega di recriptare nuovamente la chiave segreta.",
|
||||
"group_no_secret_key": "non esiste una chiave segreta di gruppo. Potresti essere il primo amministratore a pubblicarne una!",
|
||||
"group_secret_key_no_owner": "l'ultima chiave segreta del gruppo è stata pubblicata da un non proprietario. Per sicurezza come proprietario del gruppo si prega di ricriptare la chiave.",
|
||||
"group_secret_key_no_owner": "l'ultima chiave segreta del gruppo è stata pubblicata da un non proprietario. Per sicurezza, come proprietario del gruppo, si prega di recriptare la chiave.",
|
||||
"invalid_content": "contenuto non valido, mittente o timestamp nei dati di reazione",
|
||||
"invalid_data": "errore di caricamento del contenuto: dati non validi",
|
||||
"latest_promotion": "verrà mostrata solo l'ultima promozione della settimana per il tuo gruppo.",
|
||||
"loading_members": "caricamento dell'elenco dei membri con nomi ... Attendere.",
|
||||
"max_chars": "max 200 caratteri. Commissione",
|
||||
"manage_minting": "gestisci il minting",
|
||||
"minter_group": "al momento non fai parte del gruppo Minter",
|
||||
"minter_group": "per ora non fai parte del gruppo Minter",
|
||||
"mintership_app": "visita l'app Q-Mintership per chiedere di diventare un minter",
|
||||
"minting_account": "account di minting:",
|
||||
"minting_keys_per_node": "sono ammessi solo 2 chiavi di minting per nodo. Rimuoverne una se si desidera fare minting con questo account.",
|
||||
"minting_keys_per_node_different": "sono ammessi solo 2 chiavi di minting per nodo. Rimuovi uno se desideri aggiungere un account diverso.",
|
||||
"minting_keys_per_node": "sono ammesse solo 2 chiavi di minting per nodo. Rimuoverne una se si desidera fare minting con questo account.",
|
||||
"minting_keys_per_node_different": "sono ammesse solo 2 chiavi di minting per nodo. Rimuovine una se desideri aggiungere un account diverso.",
|
||||
"next_level": "blocchi mancanti al livello successivo:",
|
||||
"node_minting": "questo nodo sta coniando:",
|
||||
"node_minting_account": "account minting del nodo",
|
||||
"node_minting_key": "attualmente hai una chiave di minting per questo account collegata al nodo",
|
||||
"node_minting_key": "hai una chiave di minting per questo account collegata al nodo",
|
||||
"no_announcement": "nessun annuncio",
|
||||
"no_display": "niente da visualizzare",
|
||||
"no_selection": "nessun gruppo selezionato",
|
||||
"not_part_group": "non fai parte del gruppo crittografato di membri. Attendere che un amministratore ricripti le chiavi.",
|
||||
"not_part_group": "non fai parte del gruppo crittografato di membri. Attendere che un amministratore recripti le chiavi.",
|
||||
"only_encrypted": "verranno visualizzati solo messaggi non crittografati.",
|
||||
"only_private_groups": "verranno mostrati solo gruppi privati",
|
||||
"pending_join_requests": "{{ group }} ha {{ count }} richieste pendenti di adesione",
|
||||
|
@ -77,7 +77,7 @@ export const encryptDataGroup = ({
|
||||
userPublicKey,
|
||||
customSymmetricKey,
|
||||
}: any) => {
|
||||
let combinedPublicKeys = [...publicKeys, userPublicKey];
|
||||
const combinedPublicKeys = [...publicKeys, userPublicKey];
|
||||
const decodedPrivateKey = Base58.decode(privateKey);
|
||||
const publicKeysDuplicateFree = [...new Set(combinedPublicKeys)];
|
||||
const Uint8ArrayData = base64ToUint8Array(data64);
|
||||
@ -114,7 +114,7 @@ export const encryptDataGroup = ({
|
||||
const keyNonce = new Uint8Array(24);
|
||||
crypto.getRandomValues(keyNonce);
|
||||
// Encrypt the symmetric key for each recipient.
|
||||
let encryptedKeys = [];
|
||||
const encryptedKeys = [];
|
||||
publicKeysDuplicateFree.forEach((recipientPublicKey) => {
|
||||
const publicKeyUnit8Array = Base58.decode(recipientPublicKey);
|
||||
const convertedPrivateKey = ed2curve.convertSecretKey(decodedPrivateKey);
|
||||
@ -153,7 +153,7 @@ export const encryptDataGroup = ({
|
||||
encryptedKeysSize += key.length;
|
||||
});
|
||||
combinedDataSize += encryptedKeysSize;
|
||||
let combinedData = new Uint8Array(combinedDataSize);
|
||||
const combinedData = new Uint8Array(combinedDataSize);
|
||||
combinedData.set(strUint8Array);
|
||||
combinedData.set(nonce, strUint8Array.length);
|
||||
combinedData.set(keyNonce, strUint8Array.length + nonce.length);
|
||||
@ -244,9 +244,6 @@ export const encryptSingle = async ({
|
||||
encryptedData = nacl.secretbox(Uint8ArrayData, nonce, messageKey);
|
||||
encryptedDataBase64 = uint8ArrayToBase64(encryptedData);
|
||||
|
||||
// Convert the nonce to base64
|
||||
const nonceBase64 = uint8ArrayToBase64(nonce);
|
||||
|
||||
// Concatenate the highest key, type number, nonce, and encrypted data (new format)
|
||||
const highestKeyStr = highestKey.toString().padStart(10, '0'); // Fixed length of 10 digits
|
||||
|
||||
@ -281,7 +278,7 @@ export const encryptSingle = async ({
|
||||
};
|
||||
|
||||
export const decodeBase64ForUIChatMessages = (messages) => {
|
||||
let msgs = [];
|
||||
const msgs = [];
|
||||
for (const msg of messages) {
|
||||
try {
|
||||
const decoded = atob(msg?.data);
|
||||
@ -306,107 +303,114 @@ export const decryptSingle = async ({
|
||||
// First, decode the base64-encoded input (if skipDecodeBase64 is not set)
|
||||
const decodedData = skipDecodeBase64 ? data64 : atob(data64);
|
||||
|
||||
// Then, decode it again for the specific format (if double encoding is used)
|
||||
const decodeForNumber = atob(decodedData);
|
||||
if (secretKeyObject) {
|
||||
// Then, decode it again for the specific format (if double encoding is used)
|
||||
const decodeForNumber = atob(decodedData);
|
||||
|
||||
// Extract the key (assuming it's always the first 10 characters)
|
||||
const keyStr = decodeForNumber.slice(0, 10);
|
||||
// Extract the key (assuming it's always the first 10 characters)
|
||||
const keyStr = decodeForNumber.slice(0, 10);
|
||||
|
||||
// Convert the key string back to a number
|
||||
const highestKey = parseInt(keyStr, 10);
|
||||
// Convert the key string back to a number
|
||||
const highestKey = parseInt(keyStr, 10);
|
||||
|
||||
// Check if we have a valid secret key for the extracted highestKey
|
||||
if (!secretKeyObject[highestKey]) {
|
||||
throw new Error(
|
||||
i18n.t('auth:message.error.find_secret_key', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const secretKeyEntry = secretKeyObject[highestKey];
|
||||
|
||||
let typeNumberStr, nonceBase64, encryptedDataBase64;
|
||||
|
||||
// Determine if typeNumber exists by checking if the next 3 characters after keyStr are digits
|
||||
const possibleTypeNumberStr = decodeForNumber.slice(10, 13);
|
||||
const hasTypeNumber = /^\d{3}$/.test(possibleTypeNumberStr); // Check if next 3 characters are digits
|
||||
|
||||
if (secretKeyEntry.nonce) {
|
||||
// Old format: nonce is present in the secretKeyObject, so no type number exists
|
||||
nonceBase64 = secretKeyEntry.nonce;
|
||||
encryptedDataBase64 = decodeForNumber.slice(10); // The remaining part is the encrypted data
|
||||
} else {
|
||||
if (hasTypeNumber) {
|
||||
// const typeNumberStr = new TextDecoder().decode(typeNumberBytes);
|
||||
if (decodeForNumber.slice(10, 13) !== '001') {
|
||||
const decodedBinary = base64ToUint8Array(decodedData);
|
||||
const highestKeyBytes = decodedBinary.slice(0, 10); // if ASCII digits only
|
||||
const highestKeyStr = new TextDecoder().decode(highestKeyBytes);
|
||||
|
||||
const nonce = decodedBinary.slice(13, 13 + 24);
|
||||
const encryptedData = decodedBinary.slice(13 + 24);
|
||||
const highestKey = parseInt(highestKeyStr, 10);
|
||||
|
||||
const messageKey = base64ToUint8Array(
|
||||
secretKeyObject[+highestKey].messageKey
|
||||
);
|
||||
const decryptedBytes = nacl.secretbox.open(
|
||||
encryptedData,
|
||||
nonce,
|
||||
messageKey
|
||||
);
|
||||
|
||||
// Check if decryption was successful
|
||||
if (!decryptedBytes) {
|
||||
throw new Error(
|
||||
i18n.t('question:message.error.decryption_failed', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Convert the decrypted Uint8Array back to a Base64 string
|
||||
return uint8ArrayToBase64(decryptedBytes);
|
||||
}
|
||||
// New format: Extract type number and nonce
|
||||
typeNumberStr = possibleTypeNumberStr; // Extract type number
|
||||
nonceBase64 = decodeForNumber.slice(13, 45); // Extract nonce (next 32 characters after type number)
|
||||
encryptedDataBase64 = decodeForNumber.slice(45); // The remaining part is the encrypted data
|
||||
} else {
|
||||
// Old format without type number (nonce is embedded in the message, first 32 characters after keyStr)
|
||||
nonceBase64 = decodeForNumber.slice(10, 42); // First 32 characters for the nonce
|
||||
encryptedDataBase64 = decodeForNumber.slice(42); // The remaining part is the encrypted data
|
||||
// Check if we have a valid secret key for the extracted highestKey
|
||||
if (!secretKeyObject[highestKey]) {
|
||||
throw new Error(
|
||||
i18n.t('auth:message.error.find_secret_key', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert Base64 strings to Uint8Array
|
||||
const Uint8ArrayData = base64ToUint8Array(encryptedDataBase64);
|
||||
const nonce = base64ToUint8Array(nonceBase64);
|
||||
const messageKey = base64ToUint8Array(secretKeyEntry.messageKey);
|
||||
const secretKeyEntry = secretKeyObject[highestKey];
|
||||
|
||||
if (!(Uint8ArrayData instanceof Uint8Array)) {
|
||||
throw new Error(
|
||||
i18n.t('auth:message.error.invalid_uint8', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})
|
||||
let nonceBase64, encryptedDataBase64;
|
||||
|
||||
// Determine if typeNumber exists by checking if the next 3 characters after keyStr are digits
|
||||
const possibleTypeNumberStr = decodeForNumber.slice(10, 13);
|
||||
const hasTypeNumber = /^\d{3}$/.test(possibleTypeNumberStr); // Check if next 3 characters are digits
|
||||
|
||||
if (secretKeyEntry.nonce) {
|
||||
// Old format: nonce is present in the secretKeyObject, so no type number exists
|
||||
nonceBase64 = secretKeyEntry.nonce;
|
||||
encryptedDataBase64 = decodeForNumber.slice(10); // The remaining part is the encrypted data
|
||||
} else {
|
||||
if (hasTypeNumber) {
|
||||
// const typeNumberStr = new TextDecoder().decode(typeNumberBytes);
|
||||
if (decodeForNumber.slice(10, 13) !== '001') {
|
||||
const decodedBinary = base64ToUint8Array(decodedData);
|
||||
const highestKeyBytes = decodedBinary.slice(0, 10); // if ASCII digits only
|
||||
const highestKeyStr = new TextDecoder().decode(highestKeyBytes);
|
||||
|
||||
const nonce = decodedBinary.slice(13, 13 + 24);
|
||||
const encryptedData = decodedBinary.slice(13 + 24);
|
||||
const highestKey = parseInt(highestKeyStr, 10);
|
||||
|
||||
const messageKey = base64ToUint8Array(
|
||||
secretKeyObject[+highestKey].messageKey
|
||||
);
|
||||
const decryptedBytes = nacl.secretbox.open(
|
||||
encryptedData,
|
||||
nonce,
|
||||
messageKey
|
||||
);
|
||||
|
||||
// Check if decryption was successful
|
||||
if (!decryptedBytes) {
|
||||
throw new Error(
|
||||
i18n.t('question:message.error.decryption_failed', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Convert the decrypted Uint8Array back to a Base64 string
|
||||
return uint8ArrayToBase64(decryptedBytes);
|
||||
}
|
||||
// New format: Extract type number and nonce
|
||||
nonceBase64 = decodeForNumber.slice(13, 45); // Extract nonce (next 32 characters after type number)
|
||||
encryptedDataBase64 = decodeForNumber.slice(45); // The remaining part is the encrypted data
|
||||
} else {
|
||||
// Old format without type number (nonce is embedded in the message, first 32 characters after keyStr)
|
||||
nonceBase64 = decodeForNumber.slice(10, 42); // First 32 characters for the nonce
|
||||
encryptedDataBase64 = decodeForNumber.slice(42); // The remaining part is the encrypted data
|
||||
}
|
||||
}
|
||||
|
||||
// Convert Base64 strings to Uint8Array
|
||||
const Uint8ArrayData = base64ToUint8Array(encryptedDataBase64);
|
||||
const nonce = base64ToUint8Array(nonceBase64);
|
||||
const messageKey = base64ToUint8Array(secretKeyEntry.messageKey);
|
||||
|
||||
if (!(Uint8ArrayData instanceof Uint8Array)) {
|
||||
throw new Error(
|
||||
i18n.t('auth:message.error.invalid_uint8', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Decrypt the data using the nonce and messageKey
|
||||
const decryptedData = nacl.secretbox.open(
|
||||
Uint8ArrayData,
|
||||
nonce,
|
||||
messageKey
|
||||
);
|
||||
|
||||
// Check if decryption was successful
|
||||
if (!decryptedData) {
|
||||
throw new Error(
|
||||
i18n.t('question:message.error.decryption_failed', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Convert the decrypted Uint8Array back to a Base64 string
|
||||
return uint8ArrayToBase64(decryptedData);
|
||||
}
|
||||
|
||||
// Decrypt the data using the nonce and messageKey
|
||||
const decryptedData = nacl.secretbox.open(Uint8ArrayData, nonce, messageKey);
|
||||
|
||||
// Check if decryption was successful
|
||||
if (!decryptedData) {
|
||||
throw new Error(
|
||||
i18n.t('question:message.error.decryption_failed', {
|
||||
postProcess: 'capitalizeFirstChar',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Convert the decrypted Uint8Array back to a Base64 string
|
||||
return uint8ArrayToBase64(decryptedData);
|
||||
return;
|
||||
};
|
||||
|
||||
export const decryptGroupEncryptionWithSharingKey = async ({
|
||||
@ -424,14 +428,9 @@ export const decryptGroupEncryptionWithSharingKey = async ({
|
||||
// Extract the shared keyNonce
|
||||
const keyNonceStartPosition = nonceEndPosition;
|
||||
const keyNonceEndPosition = keyNonceStartPosition + 24; // Nonce is 24 bytes
|
||||
const keyNonce = allCombined.slice(
|
||||
keyNonceStartPosition,
|
||||
keyNonceEndPosition
|
||||
);
|
||||
// Extract the sender's public key
|
||||
const senderPublicKeyStartPosition = keyNonceEndPosition;
|
||||
const senderPublicKeyEndPosition = senderPublicKeyStartPosition + 32; // Public keys are 32 bytes
|
||||
|
||||
// Calculate count first
|
||||
const countStartPosition = allCombined.length - 4; // 4 bytes before the end, since count is stored in Uint32 (4 bytes)
|
||||
const countArray = allCombined.slice(
|
||||
@ -662,7 +661,6 @@ export function decryptDeprecatedSingle(uint8Array, publicKey, privateKey) {
|
||||
const str = 'qortalEncryptedData';
|
||||
const strEncoder = new TextEncoder();
|
||||
const strUint8Array = strEncoder.encode(str);
|
||||
const strData = combinedData.slice(0, strUint8Array.length);
|
||||
const nonce = combinedData.slice(
|
||||
strUint8Array.length,
|
||||
strUint8Array.length + 24
|
||||
|
@ -552,7 +552,7 @@ export const getUserAccount = async ({
|
||||
|
||||
export const encryptData = async (data, sender) => {
|
||||
let data64 = data.data64 || data.base64;
|
||||
let publicKeys = data.publicKeys || [];
|
||||
const publicKeys = data.publicKeys || [];
|
||||
if (data?.file || data?.blob) {
|
||||
data64 = await fileToBase64(data?.file || data?.blob);
|
||||
}
|
||||
@ -587,8 +587,8 @@ export const encryptData = async (data, sender) => {
|
||||
|
||||
export const encryptQortalGroupData = async (data, sender) => {
|
||||
let data64 = data?.data64 || data?.base64;
|
||||
let groupId = data?.groupId;
|
||||
let isAdmins = data?.isAdmins;
|
||||
const groupId = data?.groupId;
|
||||
const isAdmins = data?.isAdmins;
|
||||
if (!groupId) {
|
||||
throw new Error(
|
||||
i18n.t('question:message.generic.provide_group_id', {
|
||||
@ -613,7 +613,7 @@ export const encryptQortalGroupData = async (data, sender) => {
|
||||
groupSecretkeys[groupId] &&
|
||||
groupSecretkeys[groupId].secretKeyObject &&
|
||||
groupSecretkeys[groupId]?.timestamp &&
|
||||
Date.now() - groupSecretkeys[groupId]?.timestamp < 1200000
|
||||
Date.now() - groupSecretkeys[groupId]?.timestamp < 1200000 // TODO magic number
|
||||
) {
|
||||
secretKeyObject = groupSecretkeys[groupId].secretKeyObject;
|
||||
}
|
||||
@ -659,7 +659,7 @@ export const encryptQortalGroupData = async (data, sender) => {
|
||||
groupSecretkeys[`admins-${groupId}`] &&
|
||||
groupSecretkeys[`admins-${groupId}`].secretKeyObject &&
|
||||
groupSecretkeys[`admins-${groupId}`]?.timestamp &&
|
||||
Date.now() - groupSecretkeys[`admins-${groupId}`]?.timestamp < 1200000
|
||||
Date.now() - groupSecretkeys[`admins-${groupId}`]?.timestamp < 1200000 // TODO magic number
|
||||
) {
|
||||
secretKeyObject = groupSecretkeys[`admins-${groupId}`].secretKeyObject;
|
||||
}
|
||||
@ -717,9 +717,9 @@ export const encryptQortalGroupData = async (data, sender) => {
|
||||
};
|
||||
|
||||
export const decryptQortalGroupData = async (data, sender) => {
|
||||
let data64 = data?.data64 || data?.base64;
|
||||
let groupId = data?.groupId;
|
||||
let isAdmins = data?.isAdmins;
|
||||
const data64 = data?.data64 || data?.base64;
|
||||
const groupId = data?.groupId;
|
||||
const isAdmins = data?.isAdmins;
|
||||
if (!groupId) {
|
||||
throw new Error(
|
||||
i18n.t('question:message.generic.provide_group_id', {
|
||||
@ -742,7 +742,7 @@ export const decryptQortalGroupData = async (data, sender) => {
|
||||
groupSecretkeys[groupId] &&
|
||||
groupSecretkeys[groupId].secretKeyObject &&
|
||||
groupSecretkeys[groupId]?.timestamp &&
|
||||
Date.now() - groupSecretkeys[groupId]?.timestamp < 1200000
|
||||
Date.now() - groupSecretkeys[groupId]?.timestamp < 1200000 // TODO magic number
|
||||
) {
|
||||
secretKeyObject = groupSecretkeys[groupId].secretKeyObject;
|
||||
}
|
||||
@ -785,7 +785,7 @@ export const decryptQortalGroupData = async (data, sender) => {
|
||||
groupSecretkeys[`admins-${groupId}`] &&
|
||||
groupSecretkeys[`admins-${groupId}`].secretKeyObject &&
|
||||
groupSecretkeys[`admins-${groupId}`]?.timestamp &&
|
||||
Date.now() - groupSecretkeys[`admins-${groupId}`]?.timestamp < 1200000
|
||||
Date.now() - groupSecretkeys[`admins-${groupId}`]?.timestamp < 1200000 // TODO magic nummber
|
||||
) {
|
||||
secretKeyObject = groupSecretkeys[`admins-${groupId}`].secretKeyObject;
|
||||
}
|
||||
@ -843,7 +843,7 @@ export const decryptQortalGroupData = async (data, sender) => {
|
||||
|
||||
export const encryptDataWithSharingKey = async (data, sender) => {
|
||||
let data64 = data?.data64 || data?.base64;
|
||||
let publicKeys = data.publicKeys || [];
|
||||
const publicKeys = data.publicKeys || [];
|
||||
if (data?.file || data?.blob) {
|
||||
data64 = await fileToBase64(data?.file || data?.blob);
|
||||
}
|
||||
@ -899,6 +899,7 @@ export const decryptDataWithSharingKey = async (data, sender) => {
|
||||
data64EncryptedData: encryptedData,
|
||||
key,
|
||||
});
|
||||
|
||||
const base64ToObject = JSON.parse(atob(decryptedData));
|
||||
|
||||
if (!base64ToObject.data)
|
||||
|
@ -152,7 +152,7 @@ function setupMessageListenerQortalRequest() {
|
||||
appInfo,
|
||||
skipAuth,
|
||||
});
|
||||
event.source.postMessage(
|
||||
event.source!.postMessage(
|
||||
{
|
||||
requestId: request.requestId,
|
||||
action: request.action,
|
||||
@ -162,7 +162,7 @@ function setupMessageListenerQortalRequest() {
|
||||
event.origin
|
||||
);
|
||||
} catch (error) {
|
||||
event.source.postMessage(
|
||||
event.source!.postMessage(
|
||||
{
|
||||
requestId: request.requestId,
|
||||
action: request.action,
|
||||
@ -236,7 +236,7 @@ function setupMessageListenerQortalRequest() {
|
||||
request.payload,
|
||||
event.source
|
||||
);
|
||||
event.source.postMessage(
|
||||
event.source!.postMessage(
|
||||
{
|
||||
requestId: request.requestId,
|
||||
action: request.action,
|
||||
@ -246,7 +246,7 @@ function setupMessageListenerQortalRequest() {
|
||||
event.origin
|
||||
);
|
||||
} catch (error) {
|
||||
event.source.postMessage(
|
||||
event.source!.postMessage(
|
||||
{
|
||||
requestId: request.requestId,
|
||||
action: request.action,
|
||||
|
Loading…
x
Reference in New Issue
Block a user