changed qortalrequest messaging

This commit is contained in:
PhilReact 2024-10-30 09:37:23 +02:00
parent 4f91924947
commit eb8049c12d
11 changed files with 674 additions and 652 deletions

9
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@capacitor/android": "^6.1.2", "@capacitor/android": "^6.1.2",
"@capacitor/browser": "^6.0.3",
"@capacitor/cli": "^6.1.2", "@capacitor/cli": "^6.1.2",
"@capacitor/core": "^6.1.2", "@capacitor/core": "^6.1.2",
"@chatscope/chat-ui-kit-react": "^2.0.3", "@chatscope/chat-ui-kit-react": "^2.0.3",
@ -398,6 +399,14 @@
"@capacitor/core": "^6.1.0" "@capacitor/core": "^6.1.0"
} }
}, },
"node_modules/@capacitor/browser": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@capacitor/browser/-/browser-6.0.3.tgz",
"integrity": "sha512-V5/ViE+fy3rW+6w0L2du4747/hivBcI/5OGOKi01U9YdFvOWbiiGL+qetq1QdkANEqvYd4yoCeXZL2GyGySn5g==",
"peerDependencies": {
"@capacitor/core": "^6.0.0"
}
},
"node_modules/@capacitor/cli": { "node_modules/@capacitor/cli": {
"version": "6.1.2", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-6.1.2.tgz", "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-6.1.2.tgz",

View File

@ -13,6 +13,7 @@
}, },
"dependencies": { "dependencies": {
"@capacitor/android": "^6.1.2", "@capacitor/android": "^6.1.2",
"@capacitor/browser": "^6.0.3",
"@capacitor/cli": "^6.1.2", "@capacitor/cli": "^6.1.2",
"@capacitor/core": "^6.1.2", "@capacitor/core": "^6.1.2",
"@chatscope/chat-ui-kit-react": "^2.0.3", "@chatscope/chat-ui-kit-react": "^2.0.3",

View File

@ -6,7 +6,7 @@ import {
useRef, useRef,
useState, useState,
} from "react"; } from "react";
import { Browser } from "@capacitor/browser";
import "./App.css"; import "./App.css";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import { import {
@ -102,9 +102,20 @@ import { MainAvatar } from "./components/MainAvatar";
import { useRetrieveDataLocalStorage } from "./useRetrieveDataLocalStorage"; import { useRetrieveDataLocalStorage } from "./useRetrieveDataLocalStorage";
import { useQortalGetSaveSettings } from "./useQortalGetSaveSettings"; import { useQortalGetSaveSettings } from "./useQortalGetSaveSettings";
import { useRecoilState, useResetRecoilState, useSetRecoilState } from "recoil"; import { useRecoilState, useResetRecoilState, useSetRecoilState } from "recoil";
import { canSaveSettingToQdnAtom, fullScreenAtom, hasSettingsChangedAtom, oldPinnedAppsAtom, settingsLocalLastUpdatedAtom, settingsQDNLastUpdatedAtom, sortablePinnedAppsAtom } from "./atoms/global"; import {
canSaveSettingToQdnAtom,
fullScreenAtom,
hasSettingsChangedAtom,
oldPinnedAppsAtom,
settingsLocalLastUpdatedAtom,
settingsQDNLastUpdatedAtom,
sortablePinnedAppsAtom,
} from "./atoms/global";
import { useAppFullScreen } from "./useAppFullscreen"; import { useAppFullScreen } from "./useAppFullscreen";
import { NotAuthenticated } from "./ExtStates/NotAuthenticated"; import { NotAuthenticated } from "./ExtStates/NotAuthenticated";
import { openIndexedDB, showSaveFilePicker } from "./components/Apps/useQortalMessageListener";
import { fileToBase64 } from "./utils/fileReading";
import { handleGetFileFromIndexedDB } from "./utils/indexedDB";
type extStates = type extStates =
@ -205,18 +216,21 @@ export const clearAllQueues = () => {
export const pauseAllQueues = () => { export const pauseAllQueues = () => {
controlAllQueues("pause"); controlAllQueues("pause");
window.sendMessage("pauseAllQueues", {}) window.sendMessage("pauseAllQueues", {}).catch((error) => {
.catch((error) => { console.error(
console.error("Failed to pause all queues:", error.message || "An error occurred"); "Failed to pause all queues:",
error.message || "An error occurred"
);
}); });
}; };
export const resumeAllQueues = () => { export const resumeAllQueues = () => {
controlAllQueues("resume"); controlAllQueues("resume");
window.sendMessage("resumeAllQueues", {}).catch((error) => { window.sendMessage("resumeAllQueues", {}).catch((error) => {
console.error("Failed to resume all queues:", error.message || "An error occurred"); console.error(
"Failed to resume all queues:",
error.message || "An error occurred"
);
}); });
}; };
export const MyContext = createContext<MyContextInterface>(defaultValues); export const MyContext = createContext<MyContextInterface>(defaultValues);
@ -255,15 +269,17 @@ export const getBaseApiReactSocket = (customApi?: string) => {
} }
if (globalApiKey) { if (globalApiKey) {
return `${getProtocol(globalApiKey?.url) === 'http' ? 'ws://': 'wss://'}${cleanUrl(globalApiKey?.url)}` return `${
getProtocol(globalApiKey?.url) === "http" ? "ws://" : "wss://"
}${cleanUrl(globalApiKey?.url)}`;
} else { } else {
return groupApiSocket; return groupApiSocket;
} }
}; };
export const isMainWindow = true export const isMainWindow = true;
function App() { function App() {
const [extState, setExtstate] = useState<extStates>("not-authenticated"); const [extState, setExtstate] = useState<extStates>("not-authenticated");
const [desktopViewMode, setDesktopViewMode] = useState('home') const [desktopViewMode, setDesktopViewMode] = useState("home");
const [backupjson, setBackupjson] = useState<any>(null); const [backupjson, setBackupjson] = useState<any>(null);
const [rawWallet, setRawWallet] = useState<any>(null); const [rawWallet, setRawWallet] = useState<any>(null);
@ -286,9 +302,7 @@ function App() {
const [walletToBeDownloaded, setWalletToBeDownloaded] = useState<any>(null); const [walletToBeDownloaded, setWalletToBeDownloaded] = useState<any>(null);
const [walletToBeDownloadedPassword, setWalletToBeDownloadedPassword] = const [walletToBeDownloadedPassword, setWalletToBeDownloadedPassword] =
useState<string>(""); useState<string>("");
const [isMain, setIsMain] = useState<boolean>( const [isMain, setIsMain] = useState<boolean>(true);
true
);
const isMainRef = useRef(false); const isMainRef = useRef(false);
const [authenticatePassword, setAuthenticatePassword] = useState<string>(""); const [authenticatePassword, setAuthenticatePassword] = useState<string>("");
const [sendqortState, setSendqortState] = useState<any>(null); const [sendqortState, setSendqortState] = useState<any>(null);
@ -304,11 +318,19 @@ function App() {
const [txList, setTxList] = useState([]); const [txList, setTxList] = useState([]);
const [memberGroups, setMemberGroups] = useState([]); const [memberGroups, setMemberGroups] = useState([]);
const [isFocused, setIsFocused] = useState(true); const [isFocused, setIsFocused] = useState(true);
const [hasSettingsChanged, setHasSettingsChanged] = useRecoilState(hasSettingsChangedAtom) const [hasSettingsChanged, setHasSettingsChanged] = useRecoilState(
hasSettingsChangedAtom
);
const holdRefExtState = useRef<extStates>("not-authenticated"); const holdRefExtState = useRef<extStates>("not-authenticated");
const isFocusedRef = useRef<boolean>(true); const isFocusedRef = useRef<boolean>(true);
const { isShow, onCancel, onOk, show, message } = useModal(); const { isShow, onCancel, onOk, show, message } = useModal();
const { isShow: isShowUnsavedChanges, onCancel: onCancelUnsavedChanges, onOk: onOkUnsavedChanges, show: showUnsavedChanges, message: messageUnsavedChanges } = useModal(); const {
isShow: isShowUnsavedChanges,
onCancel: onCancelUnsavedChanges,
onOk: onOkUnsavedChanges,
show: showUnsavedChanges,
message: messageUnsavedChanges,
} = useModal();
const { const {
onCancel: onCancelQortalRequest, onCancel: onCancelQortalRequest,
@ -339,15 +361,12 @@ function App() {
const [rootHeight, setRootHeight] = useState("100%"); const [rootHeight, setRootHeight] = useState("100%");
const [isSettingsOpen, setIsSettingsOpen] = useState(false); const [isSettingsOpen, setIsSettingsOpen] = useState(false);
const qortalRequestCheckbox1Ref = useRef(null); const qortalRequestCheckbox1Ref = useRef(null);
useRetrieveDataLocalStorage() useRetrieveDataLocalStorage();
useQortalGetSaveSettings(userInfo?.name) useQortalGetSaveSettings(userInfo?.name);
const [fullScreen, setFullScreen] = useRecoilState(fullScreenAtom); const [fullScreen, setFullScreen] = useRecoilState(fullScreenAtom);
const { toggleFullScreen } = useAppFullScreen(setFullScreen); const { toggleFullScreen } = useAppFullScreen(setFullScreen);
useEffect(() => { useEffect(() => {
// Attach a global event listener for double-click // Attach a global event listener for double-click
const handleDoubleClick = () => { const handleDoubleClick = () => {
@ -355,18 +374,29 @@ function App() {
}; };
// Add the event listener to the root HTML document // Add the event listener to the root HTML document
document.documentElement.addEventListener('dblclick', handleDoubleClick); document.documentElement.addEventListener("dblclick", handleDoubleClick);
// Clean up the event listener on unmount // Clean up the event listener on unmount
return () => { return () => {
document.documentElement.removeEventListener('dblclick', handleDoubleClick); document.documentElement.removeEventListener(
"dblclick",
handleDoubleClick
);
}; };
}, [toggleFullScreen]); }, [toggleFullScreen]);
//resets for recoil //resets for recoil
const resetAtomSortablePinnedAppsAtom = useResetRecoilState(sortablePinnedAppsAtom); const resetAtomSortablePinnedAppsAtom = useResetRecoilState(
const resetAtomCanSaveSettingToQdnAtom = useResetRecoilState(canSaveSettingToQdnAtom); sortablePinnedAppsAtom
const resetAtomSettingsQDNLastUpdatedAtom = useResetRecoilState(settingsQDNLastUpdatedAtom); );
const resetAtomSettingsLocalLastUpdatedAtom = useResetRecoilState(settingsLocalLastUpdatedAtom); const resetAtomCanSaveSettingToQdnAtom = useResetRecoilState(
canSaveSettingToQdnAtom
);
const resetAtomSettingsQDNLastUpdatedAtom = useResetRecoilState(
settingsQDNLastUpdatedAtom
);
const resetAtomSettingsLocalLastUpdatedAtom = useResetRecoilState(
settingsLocalLastUpdatedAtom
);
const resetAtomOldPinnedAppsAtom = useResetRecoilState(oldPinnedAppsAtom); const resetAtomOldPinnedAppsAtom = useResetRecoilState(oldPinnedAppsAtom);
const resetAllRecoil = () => { const resetAllRecoil = () => {
@ -403,9 +433,10 @@ function App() {
}, []); }, []);
const handleSetGlobalApikey = (key) => { const handleSetGlobalApikey = (key) => {
globalApiKey = key; globalApiKey = key;
} };
useEffect(() => { useEffect(() => {
window.sendMessage("getApiKey") window
.sendMessage("getApiKey")
.then((response) => { .then((response) => {
if (response) { if (response) {
handleSetGlobalApikey(response); handleSetGlobalApikey(response);
@ -413,9 +444,11 @@ function App() {
} }
}) })
.catch((error) => { .catch((error) => {
console.error("Failed to get API key:", error?.message || "An error occurred"); console.error(
"Failed to get API key:",
error?.message || "An error occurred"
);
}); });
}, []); }, []);
useEffect(() => { useEffect(() => {
if (extState) { if (extState) {
@ -427,8 +460,6 @@ function App() {
isFocusedRef.current = isFocused; isFocusedRef.current = isFocused;
}, [isFocused]); }, [isFocused]);
// const checkIfUserHasLocalNode = useCallback(async () => { // const checkIfUserHasLocalNode = useCallback(async () => {
// try { // try {
// const url = `http://127.0.0.1:12391/admin/status`; // const url = `http://127.0.0.1:12391/admin/status`;
@ -528,11 +559,10 @@ function App() {
}; };
}; };
const getBalanceFunc = () => { const getBalanceFunc = () => {
setQortBalanceLoading(true); setQortBalanceLoading(true);
window.sendMessage("balance") window
.sendMessage("balance")
.then((response) => { .then((response) => {
if (!response?.error && !isNaN(+response)) { if (!response?.error && !isNaN(+response)) {
setBalance(response); setBalance(response);
@ -543,11 +573,11 @@ function App() {
console.error("Failed to get balance:", error); console.error("Failed to get balance:", error);
setQortBalanceLoading(false); setQortBalanceLoading(false);
}); });
}; };
const getLtcBalanceFunc = () => { const getLtcBalanceFunc = () => {
setLtcBalanceLoading(true); setLtcBalanceLoading(true);
window.sendMessage("ltcBalance") window
.sendMessage("ltcBalance")
.then((response) => { .then((response) => {
if (!response?.error && !isNaN(+response)) { if (!response?.error && !isNaN(+response)) {
setLtcBalance(response); setLtcBalance(response);
@ -558,7 +588,6 @@ function App() {
console.error("Failed to get LTC balance:", error); console.error("Failed to get LTC balance:", error);
setLtcBalanceLoading(false); setLtcBalanceLoading(false);
}); });
}; };
const sendCoinFunc = () => { const sendCoinFunc = () => {
setSendPaymentError(""); setSendPaymentError("");
@ -576,7 +605,8 @@ function App() {
return; return;
} }
setIsLoading(true); setIsLoading(true);
window.sendMessage("sendCoin", { window
.sendMessage("sendCoin", {
amount: Number(paymentAmount), amount: Number(paymentAmount),
receiver: paymentTo.trim(), receiver: paymentTo.trim(),
password: paymentPassword, password: paymentPassword,
@ -594,7 +624,6 @@ function App() {
console.error("Failed to send coin:", error); console.error("Failed to send coin:", error);
setIsLoading(false); setIsLoading(false);
}); });
}; };
const clearAllStates = () => { const clearAllStates = () => {
@ -602,44 +631,47 @@ function App() {
setRequestAuthentication(null); setRequestAuthentication(null);
}; };
const qortalRequestPermisson = async (message, sender, sendResponse) => { const qortalRequestPermissonFromExtension = async (message, event) => {
if (message.action === "QORTAL_REQUEST_PERMISSION" && !isMainWindow) { if (message.action === "QORTAL_REQUEST_PERMISSION") {
try { try {
console.log("QORTAL_REQUEST_PERMISSION2", event, message);
await showQortalRequest(message?.payload);
if (qortalRequestCheckbox1Ref.current) {
sendResponse({
accepted: true,
checkbox1: qortalRequestCheckbox1Ref.current,
});
return;
}
sendResponse({ accepted: true });
} catch (error) {
sendResponse({ accepted: false });
} finally {
window.close();
}
}
};
const qortalRequestPermissonFromExtension = async (message, sender, sendResponse) => {
if (message.action === "QORTAL_REQUEST_PERMISSION" && isMainWindow) {
try {
await showQortalRequestExtension(message?.payload); await showQortalRequestExtension(message?.payload);
console.log("event100", event);
if (qortalRequestCheckbox1Ref.current) { if (qortalRequestCheckbox1Ref.current) {
event.source.postMessage(
sendResponse({ {
action: "QORTAL_REQUEST_PERMISSION_RESPONSE",
requestId: message?.requestId,
result: {
accepted: true, accepted: true,
checkbox1: qortalRequestCheckbox1Ref.current, checkbox1: qortalRequestCheckbox1Ref.current,
}); },
},
event.origin
);
return; return;
} }
sendResponse({ accepted: true }); event.source.postMessage(
{
action: "QORTAL_REQUEST_PERMISSION_RESPONSE",
requestId: message?.requestId,
result: {
accepted: true,
},
},
event.origin
);
} catch (error) { } catch (error) {
sendResponse({ accepted: false }); event.source.postMessage(
{
action: "QORTAL_REQUEST_PERMISSION_RESPONSE",
requestId: message?.requestId,
result: {
accepted: false,
},
},
event.origin
);
} }
} }
}; };
@ -647,15 +679,15 @@ function App() {
useEffect(() => { useEffect(() => {
// Handler function for incoming messages // Handler function for incoming messages
const messageHandler = (event) => { const messageHandler = (event) => {
console.log("messageHandler", event);
const message = event.data; const message = event.data;
if (message?.action === "CHECK_FOCUS") { if (message?.action === "CHECK_FOCUS") {
event.source.postMessage(
event.source.postMessage({ action: "CHECK_FOCUS_RESPONSE", isFocused: isFocusedRef.current }, event.origin); { action: "CHECK_FOCUS_RESPONSE", isFocused: isFocusedRef.current },
event.origin
} else if ( );
message.action === "NOTIFICATION_OPEN_DIRECT" } else if (message.action === "NOTIFICATION_OPEN_DIRECT") {
) {
executeEvent("openDirectMessage", { executeEvent("openDirectMessage", {
from: message.payload.from, from: message.payload.from,
}); });
@ -677,9 +709,17 @@ function App() {
executeEvent("openThreadNewPost", { executeEvent("openThreadNewPost", {
data: message.payload.data, data: message.payload.data,
}); });
} else if (
message.action === "QORTAL_REQUEST_PERMISSION" &&
message?.isFromExtension
) {
qortalRequestPermissonFromExtension(message, event);
} else if(message?.action === 'SHOW_SAVE_FILE_PICKER'){
showSaveFilePicker(message?.payload)
} else if(message?.action === 'getFileFromIndexedDB'){
handleGetFileFromIndexedDB(event);
} }
}; };
// Attach the event listener // Attach the event listener
@ -691,8 +731,6 @@ function App() {
}; };
}, []); }, []);
//param = isDecline //param = isDecline
const confirmPayment = (isDecline: boolean) => { const confirmPayment = (isDecline: boolean) => {
// REMOVED FOR MOBILE APP // REMOVED FOR MOBILE APP
@ -700,7 +738,6 @@ function App() {
const confirmBuyOrder = (isDecline: boolean) => { const confirmBuyOrder = (isDecline: boolean) => {
// REMOVED FOR MOBILE APP // REMOVED FOR MOBILE APP
}; };
const responseToConnectionRequest = ( const responseToConnectionRequest = (
isOkay: boolean, isOkay: boolean,
@ -710,14 +747,14 @@ function App() {
// REMOVED FOR MOBILE APP // REMOVED FOR MOBILE APP
}; };
useEffect(() => { useEffect(() => {
try { try {
setIsLoading(true); setIsLoading(true);
window.sendMessage("getWalletInfo") window
.sendMessage("getWalletInfo")
.then((response) => { .then((response) => {
console.log('getwalll', response) console.log("getwalll", response);
if (response && response?.walletInfo) { if (response && response?.walletInfo) {
setRawWallet(response?.walletInfo); setRawWallet(response?.walletInfo);
if ( if (
@ -748,7 +785,8 @@ function App() {
}, 10000); }, 10000);
}); });
} }
window.sendMessage("userInfo") window
.sendMessage("userInfo")
.then((response) => { .then((response) => {
if (response && !response.error) { if (response && !response.error) {
setUserInfo(response); setUserInfo(response);
@ -844,7 +882,8 @@ function App() {
crypto.kdfThreads, crypto.kdfThreads,
() => {} () => {}
); );
window.sendMessage("decryptWallet", { window
.sendMessage("decryptWallet", {
password: walletToBeDownloadedPassword, password: walletToBeDownloadedPassword,
wallet, wallet,
}) })
@ -856,7 +895,8 @@ function App() {
qortAddress: wallet.address0, qortAddress: wallet.address0,
}); });
window.sendMessage("userInfo") window
.sendMessage("userInfo")
.then((response2) => { .then((response2) => {
setIsLoading(false); setIsLoading(false);
if (response2 && !response2.error) { if (response2 && !response2.error) {
@ -878,7 +918,6 @@ function App() {
setIsLoading(false); setIsLoading(false);
console.error("Failed to decrypt wallet:", error); console.error("Failed to decrypt wallet:", error);
}); });
} catch (error: any) { } catch (error: any) {
setWalletToBeDownloadedError(error?.message); setWalletToBeDownloadedError(error?.message);
setIsLoading(false); setIsLoading(false);
@ -888,9 +927,13 @@ function App() {
const logoutFunc = async () => { const logoutFunc = async () => {
try { try {
if (hasSettingsChanged) { if (hasSettingsChanged) {
await showUnsavedChanges({message: 'Your settings have changed. If you logout you will lose your changes. Click on the save button in the header to keep your changed settings.'}) await showUnsavedChanges({
message:
"Your settings have changed. If you logout you will lose your changes. Click on the save button in the header to keep your changed settings.",
});
} }
window.sendMessage("logout", {}) window
.sendMessage("logout", {})
.then((response) => { .then((response) => {
if (response) { if (response) {
resetAllStates(); resetAllStates();
@ -898,9 +941,11 @@ function App() {
} }
}) })
.catch((error) => { .catch((error) => {
console.error("Failed to log out:", error.message || "An error occurred"); console.error(
"Failed to log out:",
error.message || "An error occurred"
);
}); });
} catch (error) {} } catch (error) {}
}; };
@ -944,7 +989,7 @@ function App() {
setHasLocalNode(false); setHasLocalNode(false);
setTxList([]); setTxList([]);
setMemberGroups([]); setMemberGroups([]);
resetAllRecoil() resetAllRecoil();
}; };
function roundUpToDecimals(number, decimals = 8) { function roundUpToDecimals(number, decimals = 8) {
@ -961,18 +1006,20 @@ function App() {
res(); res();
}, 250); }, 250);
}); });
window.sendMessage("decryptWallet", { window
.sendMessage("decryptWallet", {
password: authenticatePassword, password: authenticatePassword,
wallet: rawWallet, wallet: rawWallet,
}) })
.then((response) => { .then((response) => {
console.log('response2', response) console.log("response2", response);
if (response && !response.error) { if (response && !response.error) {
setAuthenticatePassword(""); setAuthenticatePassword("");
setExtstate("authenticated"); setExtstate("authenticated");
setWalletToBeDecryptedError(""); setWalletToBeDecryptedError("");
window.sendMessage("userInfo") window
.sendMessage("userInfo")
.then((response) => { .then((response) => {
setIsLoading(false); setIsLoading(false);
if (response && !response.error) { if (response && !response.error) {
@ -986,7 +1033,8 @@ function App() {
getBalanceFunc(); getBalanceFunc();
window.sendMessage("getWalletInfo") window
.sendMessage("getWalletInfo")
.then((response) => { .then((response) => {
if (response && response.walletInfo) { if (response && response.walletInfo) {
setRawWallet(response.walletInfo); setRawWallet(response.walletInfo);
@ -1004,7 +1052,6 @@ function App() {
setIsLoading(false); setIsLoading(false);
console.error("Failed to decrypt wallet:", error); console.error("Failed to decrypt wallet:", error);
}); });
} catch (error) { } catch (error) {
setWalletToBeDecryptedError("Unable to authenticate. Wrong password"); setWalletToBeDecryptedError("Unable to authenticate. Wrong password");
} }
@ -1054,13 +1101,13 @@ function App() {
const handleFocus = () => { const handleFocus = () => {
setIsFocused(true); setIsFocused(true);
if (isMobile) { if (isMobile) {
window.sendMessage("clearAllNotifications", {}) window.sendMessage("clearAllNotifications", {}).catch((error) => {
.catch((error) => { console.error(
console.error("Failed to clear notifications:", error.message || "An error occurred"); "Failed to clear notifications:",
error.message || "An error occurred"
);
}); });
} }
}; };
// Handler for when the window loses focus // Handler for when the window loses focus
@ -1077,11 +1124,12 @@ function App() {
if (document.visibilityState === "visible") { if (document.visibilityState === "visible") {
setIsFocused(true); setIsFocused(true);
if (isMobile) { if (isMobile) {
window.sendMessage("clearAllNotifications", {}) window.sendMessage("clearAllNotifications", {}).catch((error) => {
.catch((error) => { console.error(
console.error("Failed to clear notifications:", error.message || "An error occurred"); "Failed to clear notifications:",
error.message || "An error occurred"
);
}); });
} }
} else { } else {
setIsFocused(false); setIsFocused(false);
@ -1123,7 +1171,8 @@ function App() {
}); });
setIsLoadingRegisterName(true); setIsLoadingRegisterName(true);
new Promise((res, rej) => { new Promise((res, rej) => {
window.sendMessage("registerName", { window
.sendMessage("registerName", {
name: registerNameValue, name: registerNameValue,
}) })
.then((response) => { .then((response) => {
@ -1132,7 +1181,8 @@ function App() {
setIsLoadingRegisterName(false); setIsLoadingRegisterName(false);
setInfoSnack({ setInfoSnack({
type: "success", type: "success",
message: "Successfully registered. It may take a couple of minutes for the changes to propagate", message:
"Successfully registered. It may take a couple of minutes for the changes to propagate",
}); });
setOpenRegisterName(false); setOpenRegisterName(false);
setRegisterNameValue(""); setRegisterNameValue("");
@ -1164,7 +1214,6 @@ function App() {
setOpenSnack(true); setOpenSnack(true);
rej(error); rej(error);
}); });
}); });
} catch (error) { } catch (error) {
if (error?.message) { if (error?.message) {
@ -1355,8 +1404,8 @@ function App() {
marginTop: "10px", marginTop: "10px",
textDecoration: "underline", textDecoration: "underline",
}} }}
onClick={() => { onClick={async () => {
// TODO await Browser.open({ url: "https://www.qort.trade" });
}} }}
> >
Get QORT at qort.trade Get QORT at qort.trade
@ -1438,15 +1487,22 @@ function App() {
<AppContainer <AppContainer
sx={{ sx={{
height: isMobile ? "100%" : "100vh", height: isMobile ? "100%" : "100vh",
backgroundImage: desktopViewMode === 'apps' && 'url("appsBg.svg")', backgroundImage: desktopViewMode === "apps" && 'url("appsBg.svg")',
backgroundSize: desktopViewMode === 'apps' && 'cover', backgroundSize: desktopViewMode === "apps" && "cover",
backgroundPosition: desktopViewMode === 'apps' && 'center', backgroundPosition: desktopViewMode === "apps" && "center",
backgroundRepeat: desktopViewMode === 'apps' && 'no-repeat', backgroundRepeat: desktopViewMode === "apps" && "no-repeat",
}} }}
> >
{extState === "not-authenticated" && ( {extState === "not-authenticated" && (
<NotAuthenticated getRootProps={getRootProps} getInputProps={getInputProps} setExtstate={setExtstate} apiKey={apiKey} globalApiKey={globalApiKey} setApiKey={setApiKey} handleSetGlobalApikey={handleSetGlobalApikey}/> <NotAuthenticated
getRootProps={getRootProps}
getInputProps={getInputProps}
setExtstate={setExtstate}
apiKey={apiKey}
globalApiKey={globalApiKey}
setApiKey={setApiKey}
handleSetGlobalApikey={handleSetGlobalApikey}
/>
)} )}
{/* {extState !== "not-authenticated" && ( {/* {extState !== "not-authenticated" && (
<button onClick={logoutFunc}>logout</button> <button onClick={logoutFunc}>logout</button>
@ -1487,7 +1543,7 @@ function App() {
desktopViewMode={desktopViewMode} desktopViewMode={desktopViewMode}
setDesktopViewMode={setDesktopViewMode} setDesktopViewMode={setDesktopViewMode}
/> />
{(!isMobile && desktopViewMode !== 'apps') && renderProfile()} {!isMobile && desktopViewMode !== "apps" && renderProfile()}
</Box> </Box>
<Box <Box
@ -1742,10 +1798,11 @@ function App() {
maxWidth: "90%", maxWidth: "90%",
}} }}
> >
{'Fee: '}{messageQortalRequest?.fee}{' QORT'} {"Fee: "}
{messageQortalRequest?.fee}
{" QORT"}
</TextP> </TextP>
<Spacer height="15px" /> <Spacer height="15px" />
</> </>
)} )}
{messageQortalRequest?.checkbox1 && ( {messageQortalRequest?.checkbox1 && (
@ -2524,23 +2581,25 @@ function App() {
colors={["#004777", "#F7B801", "#A30000", "#A30000"]} colors={["#004777", "#F7B801", "#A30000", "#A30000"]}
colorsTime={[7, 5, 2, 0]} colorsTime={[7, 5, 2, 0]}
onComplete={() => { onComplete={() => {
onCancelQortalRequestExtension() onCancelQortalRequestExtension();
}} }}
size={50} size={50}
strokeWidth={5} strokeWidth={5}
> >
{({ remainingTime }) => <TextP>{remainingTime}</TextP>} {({ remainingTime }) => <TextP>{remainingTime}</TextP>}
</CountdownCircleTimer> </CountdownCircleTimer>
<Box sx={{ <Box
display: 'flex', sx={{
padding: '20px', display: "flex",
flexDirection: 'column', padding: "20px",
alignItems: 'center', flexDirection: "column",
justifyContent: 'flex-start', alignItems: "center",
minHeight: '400px', justifyContent: "flex-start",
maxHeight: '90vh', minHeight: "400px",
overflow: 'auto' maxHeight: "90vh",
}}> overflow: "auto",
}}
>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -2626,7 +2685,9 @@ function App() {
{messageQortalRequestExtension?.html && ( {messageQortalRequestExtension?.html && (
<div <div
dangerouslySetInnerHTML={{ __html: messageQortalRequestExtension?.html }} dangerouslySetInnerHTML={{
__html: messageQortalRequestExtension?.html,
}}
/> />
)} )}
<Spacer height="15px" /> <Spacer height="15px" />
@ -2656,10 +2717,11 @@ function App() {
maxWidth: "90%", maxWidth: "90%",
}} }}
> >
{'Fee: '}{messageQortalRequestExtension?.fee}{' QORT'} {"Fee: "}
{messageQortalRequestExtension?.fee}
{" QORT"}
</TextP> </TextP>
<Spacer height="15px" /> <Spacer height="15px" />
</> </>
)} )}
{messageQortalRequestExtension?.checkbox1 && ( {messageQortalRequestExtension?.checkbox1 && (
@ -2680,7 +2742,9 @@ function App() {
edge="start" edge="start"
tabIndex={-1} tabIndex={-1}
disableRipple disableRipple
defaultChecked={messageQortalRequestExtension?.checkbox1?.value} defaultChecked={
messageQortalRequestExtension?.checkbox1?.value
}
sx={{ sx={{
"&.Mui-checked": { "&.Mui-checked": {
color: "white", // Customize the color when checked color: "white", // Customize the color when checked

View File

@ -1,6 +1,6 @@
// @ts-nocheck // @ts-nocheck
// TODO // TODO
// import "./qortalRequests"; import "./qortalRequests";
import { isArray } from "lodash"; import { isArray } from "lodash";
import { import {
decryptGroupEncryption, decryptGroupEncryption,
@ -2878,7 +2878,6 @@ async function getChatHeadsDirect() {
throw new Error("No Chatheads saved"); throw new Error("No Chatheads saved");
} }
} }
// TODO: listener
function setupMessageListener() { function setupMessageListener() {
window.addEventListener("message", async (event) => { window.addEventListener("message", async (event) => {

View File

@ -3,6 +3,8 @@ import FileSaver from 'file-saver';
import { executeEvent } from '../../utils/events'; import { executeEvent } from '../../utils/events';
import { useSetRecoilState } from 'recoil'; import { useSetRecoilState } from 'recoil';
import { navigationControllerAtom } from '../../atoms/global'; import { navigationControllerAtom } from '../../atoms/global';
class Semaphore { class Semaphore {
constructor(count) { constructor(count) {
this.count = count this.count = count
@ -58,7 +60,7 @@ const fileToBase64 = (file) => new Promise(async (resolve, reject) => {
} }
}) })
function openIndexedDB() { export function openIndexedDB() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const request = indexedDB.open("fileStorageDB", 1); const request = indexedDB.open("fileStorageDB", 1);
@ -79,58 +81,7 @@ function openIndexedDB() {
}); });
} }
async function handleGetFileFromIndexedDB(fileId, sendResponse) {
try {
const db = await openIndexedDB();
const transaction = db.transaction(["files"], "readonly");
const objectStore = transaction.objectStore("files");
const getRequest = objectStore.get(fileId);
getRequest.onsuccess = async function (event) {
if (getRequest.result) {
const file = getRequest.result.data;
try {
const base64String = await fileToBase64(file);
// Create a new transaction to delete the file
const deleteTransaction = db.transaction(["files"], "readwrite");
const deleteObjectStore = deleteTransaction.objectStore("files");
const deleteRequest = deleteObjectStore.delete(fileId);
deleteRequest.onsuccess = function () {
try {
sendResponse({ result: base64String });
} catch (error) {
console.log('error', error)
}
};
deleteRequest.onerror = function () {
console.error(`Error deleting file with ID ${fileId} from IndexedDB`);
sendResponse({ result: null, error: "Failed to delete file from IndexedDB" });
};
} catch (error) {
console.error("Error converting file to Base64:", error);
sendResponse({ result: null, error: "Failed to convert file to Base64" });
}
} else {
console.error(`File with ID ${fileId} not found in IndexedDB`);
sendResponse({ result: null, error: "File not found in IndexedDB" });
}
};
getRequest.onerror = function () {
console.error(`Error retrieving file with ID ${fileId} from IndexedDB`);
sendResponse({ result: null, error: "Error retrieving file from IndexedDB" });
};
} catch (error) {
console.error("Error opening IndexedDB:", error);
sendResponse({ result: null, error: "Error opening IndexedDB" });
}
}
const UIQortalRequests = [ const UIQortalRequests = [
'GET_USER_ACCOUNT', 'DECRYPT_DATA', 'SEND_COIN', 'GET_LIST_ITEMS', 'GET_USER_ACCOUNT', 'DECRYPT_DATA', 'SEND_COIN', 'GET_LIST_ITEMS',
@ -215,7 +166,7 @@ const UIQortalRequests = [
} }
} }
const showSaveFilePicker = async (data) => { export const showSaveFilePicker = async (data) => {
let blob let blob
let fileName let fileName
try { try {
@ -368,7 +319,7 @@ isDOMContentLoaded: false
if (event?.data?.requestedHandler !== 'UI') return; if (event?.data?.requestedHandler !== 'UI') return;
const sendMessageToRuntime = (message, eventPort) => { const sendMessageToRuntime = (message, eventPort) => {
window.sendMessage(message.action, message, 60000, message.isFromExtension) window.sendMessage(message.action, message.payload, 60000, message.isExtension)
.then((response) => { .then((response) => {
if (response.error) { if (response.error) {
eventPort.postMessage({ eventPort.postMessage({
@ -402,6 +353,7 @@ isDOMContentLoaded: false
) { ) {
let data; let data;
try { try {
console.log('storeFilesInIndexedDB', structuredClone(event.data))
data = await storeFilesInIndexedDB(event.data); data = await storeFilesInIndexedDB(event.data);
} catch (error) { } catch (error) {
console.error('Error storing files in IndexedDB:', error); console.error('Error storing files in IndexedDB:', error);
@ -458,6 +410,8 @@ isDOMContentLoaded: false
} }, '*' } }, '*'
); );
} }
}; };
// Add the listener for messages coming from the frameWindow // Add the listener for messages coming from the frameWindow
@ -471,17 +425,7 @@ isDOMContentLoaded: false
}, []); // Empty dependency array to run once when the component mounts }, []); // Empty dependency array to run once when the component mounts
// TODO
// chrome.runtime?.onMessage.addListener( function (message, sender, sendResponse) {
// if(message.action === "SHOW_SAVE_FILE_PICKER"){
// showSaveFilePicker(message?.data)
// }
// else if (message.action === "getFileFromIndexedDB") {
// handleGetFileFromIndexedDB(message.fileId, sendResponse);
// return true; // Keep the message channel open for async response
// }
// });
return {path, history, resetHistory, changeCurrentIndex} return {path, history, resetHistory, changeCurrentIndex}
}; };

View File

@ -1,6 +1,7 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import DOMPurify from 'dompurify'; import DOMPurify from 'dompurify';
import './styles.css'; // Ensure this CSS file is imported import './styles.css'; // Ensure this CSS file is imported
import { Browser } from '@capacitor/browser';
export const MessageDisplay = ({ htmlContent , isReply}) => { export const MessageDisplay = ({ htmlContent , isReply}) => {
@ -28,25 +29,15 @@ export const MessageDisplay = ({ htmlContent , isReply}) => {
}); });
// Function to handle link clicks // Function to handle link clicks
const handleClick = (e) => { const handleClick = async (e) => {
e.preventDefault(); e.preventDefault();
// Ensure we are targeting an <a> element // Ensure we are targeting an <a> element
const target = e.target.closest('a'); const target = e.target.closest('a');
if (target) { if (target) {
const href = target.getAttribute('href'); const href = target.getAttribute('href');
// TODO await Browser.open({ url: href });
// if (chrome && chrome.tabs) {
// chrome.tabs.create({ url: href }, (tab) => {
// if (chrome.runtime.lastError) {
// console.error('Error opening tab:', chrome.runtime.lastError);
// } else {
// console.log('Tab opened successfully:', tab);
// }
// });
// } else {
// console.error('chrome.tabs API is not available.');
// }
} else { } else {
console.error('No <a> tag found or href is null.'); console.error('No <a> tag found or href is null.');
} }

View File

@ -9,6 +9,7 @@ import { Home, Groups, Message, ShowChart } from "@mui/icons-material";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import BottomLogo from "../../assets/svgs/BottomLogo5.svg"; import BottomLogo from "../../assets/svgs/BottomLogo5.svg";
import LogoSelected from "../../assets/svgs/LogoSelected.svg"; import LogoSelected from "../../assets/svgs/LogoSelected.svg";
import { Browser } from '@capacitor/browser';
import { CustomSvg } from "../../common/CustomSvg"; import { CustomSvg } from "../../common/CustomSvg";
import { WalletIcon } from "../../assets/Icons/WalletIcon"; import { WalletIcon } from "../../assets/Icons/WalletIcon";
@ -183,10 +184,10 @@ export const MobileFooter = ({
}} }}
/> />
<BottomNavigationAction <BottomNavigationAction
onClick={() => { onClick={async () => {
// TODO await Browser.open({ url: 'https://www.qort.trade' });
// chrome.tabs.create({ url: "https://www.qort.trade"});
}} }}
icon={ icon={
<IconWrapper label="Trading" color="rgba(250, 250, 250, 0.5)"> <IconWrapper label="Trading" color="rgba(250, 250, 250, 0.5)">
<TradingIcon color="rgba(250, 250, 250, 0.5)" /> <TradingIcon color="rgba(250, 250, 250, 0.5)" />

View File

@ -24,13 +24,13 @@ window.addEventListener("message", (event) => {
} }
}); });
export const sendMessageBackground = (action, data = {}, timeout = 60000, isFromExtension) => { export const sendMessageBackground = (action, data = {}, timeout = 60000, isExtension) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const requestId = generateRequestId(); // Unique ID for each request const requestId = generateRequestId(); // Unique ID for each request
callbackMap.set(requestId, { resolve, reject }); // Store both resolve and reject callbacks callbackMap.set(requestId, { resolve, reject }); // Store both resolve and reject callbacks
// Send the message with `backgroundMessage` type // Send the message with `backgroundMessage` type
window.postMessage({ type: "backgroundMessage", action, requestId, payload: data, isFromExtension }, "*"); window.postMessage({ type: "backgroundMessage", action, requestId, payload: data, isExtension }, "*");
// Set up a timeout to automatically reject if no response is received // Set up a timeout to automatically reject if no response is received
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {

View File

@ -1,5 +1,5 @@
import { addForeignServer, addListItems, createPoll, decryptData, deleteListItems, deployAt, encryptData, getCrossChainServerInfo, getDaySummary, getForeignFee, getListItems, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getWalletBalance, joinGroup, publishMultipleQDNResources, publishQDNResource, removeForeignServer, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, updateForeignFee, voteOnPoll } from "./qortalRequests/get"; import { addForeignServer, addListItems, createPoll, decryptData, deleteListItems, deployAt, encryptData, getCrossChainServerInfo, getDaySummary, getForeignFee, getListItems, getServerConnectionHistory, getTxActivitySummary, getUserAccount, getUserWallet, getUserWalletInfo, getWalletBalance, joinGroup, publishMultipleQDNResources, publishQDNResource, removeForeignServer, saveFile, sendChatMessage, sendCoin, setCurrentForeignServer, updateForeignFee, voteOnPoll } from "./qortalRequests/get";
import { storeData } from "./utils/chromeStorage"; import { getData, storeData } from "./utils/chromeStorage";
@ -28,7 +28,7 @@ function setLocalStorage(key, data) {
qortalRequestPermissions[key] = value; qortalRequestPermissions[key] = value;
// Save the updated object back to storage // Save the updated object back to storage
await setLocalStorage({ qortalRequestPermissions }); await setLocalStorage('qortalRequestPermissions', qortalRequestPermissions );
console.log('Permission set for', key); console.log('Permission set for', key);
} catch (error) { } catch (error) {
@ -53,7 +53,7 @@ function setLocalStorage(key, data) {
// TODO: GET_FRIENDS_LIST // TODO: GET_FRIENDS_LIST
// NOT SURE IF TO IMPLEMENT: LINK_TO_QDN_RESOURCE, QDN_RESOURCE_DISPLAYED, SET_TAB_NOTIFICATIONS // NOT SURE IF TO IMPLEMENT: LINK_TO_QDN_RESOURCE, QDN_RESOURCE_DISPLAYED, SET_TAB_NOTIFICATIONS
function setupMessageListener() { function setupMessageListenerQortalRequest() {
window.addEventListener("message", async (event) => { window.addEventListener("message", async (event) => {
const request = event.data; const request = event.data;
@ -87,6 +87,7 @@ function setLocalStorage(key, data) {
case "ENCRYPT_DATA": { case "ENCRYPT_DATA": {
try { try {
console.log('ENCRYPTDATA', request)
const res = await encryptData(request.payload, event.source); const res = await encryptData(request.payload, event.source);
event.source.postMessage({ event.source.postMessage({
requestId: request.requestId, requestId: request.requestId,
@ -98,7 +99,7 @@ function setLocalStorage(key, data) {
event.source.postMessage({ event.source.postMessage({
requestId: request.requestId, requestId: request.requestId,
action: request.action, action: request.action,
error: error.message, error: error?.message,
type: "backgroundMessageResponse", type: "backgroundMessageResponse",
}, event.origin); }, event.origin);
} }
@ -368,6 +369,7 @@ function setLocalStorage(key, data) {
case "GET_WALLET_BALANCE": { case "GET_WALLET_BALANCE": {
try { try {
const res = await getWalletBalance(request.payload, false, isFromExtension); const res = await getWalletBalance(request.payload, false, isFromExtension);
console.log('ressss', res)
event.source.postMessage({ event.source.postMessage({
requestId: request.requestId, requestId: request.requestId,
action: request.action, action: request.action,
@ -612,5 +614,5 @@ function setLocalStorage(key, data) {
} }
// Initialize the message listener // Initialize the message listener
setupMessageListener(); setupMessageListenerQortalRequest();

View File

@ -180,174 +180,101 @@ const _voteOnPoll = async ({pollName, optionIndex, optionName}, isFromExtension)
} }
}; };
function getFileFromContentScript(fileId, sender) { // Map to store resolvers and rejectors by requestId
const fileRequestResolvers = new Map();
const handleFileMessage = (event) => {
const { action, requestId, result, error } = event.data;
if (action === "getFileFromIndexedDBResponse" && fileRequestResolvers.has(requestId)) {
const { resolve, reject } = fileRequestResolvers.get(requestId);
fileRequestResolvers.delete(requestId); // Clean up after resolving
if (result) {
resolve(result);
} else {
reject(error || "Failed to retrieve file");
}
}
};
window.addEventListener("message", handleFileMessage);
function getFileFromContentScript(fileId) {
console.log('handleGetFileFromIndexedDB', fileId)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
chrome.tabs.sendMessage( const requestId = `getFile_${fileId}_${Date.now()}`;
sender.tab.id, console.log('handleGetFileFromIndexedDB', requestId)
{ action: "getFileFromIndexedDB", fileId: fileId },
(response) => { fileRequestResolvers.set(requestId, { resolve, reject }); // Store resolvers by requestId
if (response && response.result) { console.log('handleGetFileFromIndexedDB', 'passed')
resolve(response.result);
} else { // Send the request message
reject(response?.error || "Failed to retrieve file"); window.postMessage(
} { action: "getFileFromIndexedDB", fileId, requestId },
} "*"
); );
}); console.log('handleGetFileFromIndexedDB', 'after', window.origin)
}
function sendToSaveFilePicker(data, sender) {
chrome.tabs.sendMessage(sender.tab.id, { // Timeout to handle no response scenario
action: "SHOW_SAVE_FILE_PICKER",
data,
});
}
async function responseFromExtension() {
return new Promise((resolve) => {
// Send message to the content script to check focus
chrome.runtime.sendMessage({ action: "QORTAL_REQUEST_PERMISSION", payloa }, (response) => {
if (chrome.runtime.lastError) {
resolve(false); // Error occurred, assume not focused
} else {
resolve(response); // Resolve based on the response
}
});
});
}
async function getUserPermission(payload: any, isFromExtension?: boolean) {
function waitForWindowReady(windowId) {
return new Promise((resolve) => {
const checkInterval = setInterval(() => {
chrome.windows.get(windowId, (win) => {
if (chrome.runtime.lastError) {
clearInterval(checkInterval); // Stop polling if there's an error
resolve(false);
} else if (win.state === "normal" || win.state === "maximized") {
clearInterval(checkInterval); // Window is ready
resolve(true);
}
});
}, 100); // Check every 100ms
});
}
if(isFromExtension){
return new Promise((resolve) => {
// Set a timeout for 1 second
const timeout = setTimeout(() => {
resolve(false);
}, 30000);
// Send message to the content script to check focus
chrome.runtime.sendMessage(
{ action: "QORTAL_REQUEST_PERMISSION", payload, isFromExtension },
(response) => {
if (response === undefined) return;
clearTimeout(timeout); // Clear the timeout if we get a response
if (chrome.runtime.lastError) {
resolve(false); // Error occurred, assume not focused
} else {
resolve(response); // Resolve based on the response
}
}
);
});
}
await new Promise((res) => {
const popupUrl = chrome.runtime.getURL("index.html?secondary=true");
chrome.windows.getAll(
{ populate: true, windowTypes: ["popup"] },
(windows) => {
// Attempt to find an existing popup window that has a tab with the correct URL
const existingPopup = windows.find(
(w) =>
w.tabs &&
w.tabs.some((tab) => tab.url && tab.url.startsWith(popupUrl))
);
if (existingPopup) {
// If the popup exists but is minimized or not focused, focus it
chrome.windows.update(existingPopup.id, {
focused: true,
state: "normal",
});
res(null);
} else {
// No existing popup found, create a new one
chrome.system.display.getInfo((displays) => {
// Assuming the primary display is the first one (adjust logic as needed)
const primaryDisplay = displays[0];
const screenWidth = primaryDisplay.bounds.width;
const windowHeight = 500; // Your window height
const windowWidth = 400; // Your window width
// Calculate left position for the window to appear on the right of the screen
const leftPosition = screenWidth - windowWidth;
// Calculate top position for the window, adjust as desired
const topPosition =
(primaryDisplay.bounds.height - windowHeight) / 2;
chrome.windows.create(
{
url: popupUrl,
type: "popup",
width: windowWidth,
height: windowHeight,
left: leftPosition,
top: 0,
},
async (newWindow) => {
removeDuplicateWindow(popupUrl);
await waitForWindowReady(newWindow.id);
res(null);
}
);
});
}
}
);
});
await new Promise((res) => {
setTimeout(() => { setTimeout(() => {
chrome.runtime.sendMessage({ if (fileRequestResolvers.has(requestId)) {
action: "SET_COUNTDOWN", fileRequestResolvers.get(requestId).reject("Request timed out");
payload: 30, fileRequestResolvers.delete(requestId); // Clean up on timeout
}); }
res(true); }, 10000); // 10-second timeout
}, 1000);
}); });
}
function sendToSaveFilePicker(data) {
window.postMessage({
action: "SHOW_SAVE_FILE_PICKER",
payload: data,
}, "*");
}
const responseResolvers = new Map();
const handleMessage = (event) => {
const { action, requestId, result } = event.data;
console.log("Received message:", event);
// Check if this is the expected response action and if we have a stored resolver
if (action === "QORTAL_REQUEST_PERMISSION_RESPONSE" && responseResolvers.has(requestId)) {
// Resolve the stored promise with the result
responseResolvers.get(requestId)(result || false);
responseResolvers.delete(requestId); // Clean up after resolving
}
};
window.addEventListener("message", handleMessage);
async function getUserPermission(payload, isFromExtension) {
return new Promise((resolve) => { return new Promise((resolve) => {
// Set a timeout for 1 second const requestId = `qortalRequest_${Date.now()}`;
const timeout = setTimeout(() => { responseResolvers.set(requestId, resolve); // Store resolver by requestId
resolve(false);
}, 30000);
// Send message to the content script to check focus // Send the request message
chrome.runtime.sendMessage( window.postMessage(
{ action: "QORTAL_REQUEST_PERMISSION", payload }, { action: "QORTAL_REQUEST_PERMISSION", payload, requestId, isFromExtension },
(response) => { "*"
if (response === undefined) return;
clearTimeout(timeout); // Clear the timeout if we get a response
if (chrome.runtime.lastError) {
resolve(false); // Error occurred, assume not focused
} else {
resolve(response); // Resolve based on the response
}
}
); );
// Optional timeout to handle no response scenario
setTimeout(() => {
if (responseResolvers.has(requestId)) {
responseResolvers.get(requestId)(false); // Resolve with `false` if no response
responseResolvers.delete(requestId);
}
}, 30000); // 30-second timeout
}); });
} }
export const getUserAccount = async () => { export const getUserAccount = async () => {
try { try {
const wallet = await getSaveWallet(); const wallet = await getSaveWallet();
@ -366,7 +293,7 @@ export const encryptData = async (data, sender) => {
let data64 = data.data64; let data64 = data.data64;
let publicKeys = data.publicKeys || []; let publicKeys = data.publicKeys || [];
if (data.fileId) { if (data.fileId) {
data64 = await getFileFromContentScript(data.fileId, sender); data64 = await getFileFromContentScript(data.fileId);
} }
if (!data64) { if (!data64) {
throw new Error("Please include data to encrypt"); throw new Error("Please include data to encrypt");
@ -633,7 +560,7 @@ export const publishQDNResource = async (data: any, sender, isFromExtension) =>
throw new Error("Only encrypted data can go into private services"); throw new Error("Only encrypted data can go into private services");
} }
if (data.fileId) { if (data.fileId) {
data64 = await getFileFromContentScript(data.fileId, sender); data64 = await getFileFromContentScript(data.fileId);
} }
if (data.encrypt) { if (data.encrypt) {
try { try {
@ -669,7 +596,7 @@ export const publishQDNResource = async (data: any, sender, isFromExtension) =>
const { accepted } = resPermission; const { accepted } = resPermission;
if (accepted) { if (accepted) {
if (data.fileId && !data.encrypt) { if (data.fileId && !data.encrypt) {
data64 = await getFileFromContentScript(data.fileId, sender); data64 = await getFileFromContentScript(data.fileId);
} }
try { try {
const resPublish = await publishData({ const resPublish = await publishData({
@ -853,7 +780,7 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten
continue; continue;
} }
if (resource.fileId) { if (resource.fileId) {
data64 = await getFileFromContentScript(resource.fileId, sender); data64 = await getFileFromContentScript(resource.fileId);
} }
if (data.encrypt) { if (data.encrypt) {
try { try {
@ -1108,7 +1035,8 @@ export const sendChatMessage = async (data, isFromExtension) => {
isEncrypted: 1, isEncrypted: 1,
isText: 1, isText: 1,
}); });
const path = chrome.runtime.getURL("memory-pow.wasm.full"); const path = `${import.meta.env.BASE_URL}memory-pow.wasm.full`;
const { nonce, chatBytesArray } = await computePow({ const { nonce, chatBytesArray } = await computePow({
chatBytes: tx.chatBytes, chatBytes: tx.chatBytes,
@ -1154,7 +1082,8 @@ export const sendChatMessage = async (data, isFromExtension) => {
// if (!hasEnoughBalance) { // if (!hasEnoughBalance) {
// throw new Error("Must have at least 4 QORT to send a chat message"); // throw new Error("Must have at least 4 QORT to send a chat message");
// } // }
const path = chrome.runtime.getURL("memory-pow.wasm.full"); const path = `${import.meta.env.BASE_URL}memory-pow.wasm.full`;
const { nonce, chatBytesArray } = await computePow({ const { nonce, chatBytesArray } = await computePow({
chatBytes: tx.chatBytes, chatBytes: tx.chatBytes,
@ -1277,8 +1206,7 @@ export const saveFile = async (data, sender, isFromExtension) => {
blob, blob,
fileId, fileId,
fileHandleOptions, fileHandleOptions,
}, }
sender
); );
return true; return true;
} else { } else {

83
src/utils/indexedDB.ts Normal file
View File

@ -0,0 +1,83 @@
export async function handleGetFileFromIndexedDB(event) {
try {
const { fileId, requestId } = event.data;
const db = await openIndexedDB();
const transaction = db.transaction(["files"], "readonly");
const objectStore = transaction.objectStore("files");
const getRequest = objectStore.get(fileId);
getRequest.onsuccess = async function (event) {
if (getRequest.result) {
const file = getRequest.result.data;
try {
const base64String = await fileToBase64(file);
// Create a new transaction to delete the file
const deleteTransaction = db.transaction(["files"], "readwrite");
const deleteObjectStore = deleteTransaction.objectStore("files");
const deleteRequest = deleteObjectStore.delete(fileId);
deleteRequest.onsuccess = function () {
try {
window.postMessage(
{ action: "getFileFromIndexedDBResponse", requestId, result: base64String },
"*"
);
} catch (error) {
console.log('error', error)
}
};
deleteRequest.onerror = function () {
console.error(`Error deleting file with ID ${fileId} from IndexedDB`);
};
} catch (error) {
console.error("Error converting file to Base64:", error);
event.ports[0].postMessage({
result: null,
error: "Failed to convert file to Base64",
});
window.postMessage(
{ action: "getFileFromIndexedDBResponse", requestId, result: null,
error: "Failed to convert file to Base64"
},
"*"
);
}
} else {
console.error(`File with ID ${fileId} not found in IndexedDB`);
window.postMessage(
{ action: "getFileFromIndexedDBResponse", requestId, result: null,
error: 'File not found in IndexedDB'
},
"*"
);
}
};
getRequest.onerror = function () {
console.error(`Error retrieving file with ID ${fileId} from IndexedDB`);
event.source.postMessage(
{ action: "getFileFromIndexedDBResponse", requestId, result: null,
error: 'Error retrieving file from IndexedDB'
},
event.origin
);
};
} catch (error) {
const { requestId } = event.data;
console.error("Error opening IndexedDB:", error);
event.source.postMessage(
{ action: "getFileFromIndexedDBResponse", requestId, result: null,
error: 'Error opening IndexedDB'
},
event.origin
);
}
}