mirror of
https://github.com/Qortal/qortal-mobile.git
synced 2025-03-27 15:55:55 +00:00
238 lines
7.0 KiB
TypeScript
238 lines
7.0 KiB
TypeScript
import React, { useContext, useState } from "react";
|
|
import { executeEvent } from "../../utils/events";
|
|
import { getBaseApiReact, MyContext } from "../../App";
|
|
import { createEndpoint } from "../../background";
|
|
import { useRecoilState, useSetRecoilState } from "recoil";
|
|
import {
|
|
settingsLocalLastUpdatedAtom,
|
|
sortablePinnedAppsAtom,
|
|
} from "../../atoms/global";
|
|
import { saveToLocalStorage } from "./AppsNavBarDesktop";
|
|
import { base64ToBlobUrl } from "../../utils/fileReading";
|
|
import { base64ToUint8Array } from "../../qdn/encryption/group-encryption";
|
|
import { uint8ArrayToObject } from "../../backgroundFunctions/encryption";
|
|
|
|
export const useHandlePrivateApps = () => {
|
|
const [status, setStatus] = useState("");
|
|
const {
|
|
openSnackGlobal,
|
|
setOpenSnackGlobal,
|
|
infoSnackCustom,
|
|
setInfoSnackCustom,
|
|
} = useContext(MyContext);
|
|
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(
|
|
sortablePinnedAppsAtom
|
|
);
|
|
const setSettingsLocalLastUpdated = useSetRecoilState(
|
|
settingsLocalLastUpdatedAtom
|
|
);
|
|
const openApp = async (
|
|
privateAppProperties,
|
|
addToPinnedApps,
|
|
setLoadingStatePrivateApp
|
|
) => {
|
|
try {
|
|
|
|
|
|
if(setLoadingStatePrivateApp){
|
|
setLoadingStatePrivateApp(`Downloading and decrypting private app.`);
|
|
|
|
}
|
|
setOpenSnackGlobal(true);
|
|
|
|
setInfoSnackCustom({
|
|
type: "info",
|
|
message: "Fetching app data",
|
|
duration: null
|
|
});
|
|
const urlData = `${getBaseApiReact()}/arbitrary/${
|
|
privateAppProperties?.service
|
|
}/${privateAppProperties?.name}/${
|
|
privateAppProperties?.identifier
|
|
}?encoding=base64`;
|
|
let data;
|
|
try {
|
|
const responseData = await fetch(urlData, {
|
|
method: "GET",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
});
|
|
|
|
if(!responseData?.ok){
|
|
if(setLoadingStatePrivateApp){
|
|
setLoadingStatePrivateApp("Error! Unable to download private app.");
|
|
}
|
|
|
|
throw new Error("Unable to fetch app");
|
|
}
|
|
|
|
data = await responseData.text();
|
|
if (data?.error) {
|
|
if(setLoadingStatePrivateApp){
|
|
|
|
setLoadingStatePrivateApp("Error! Unable to download private app.");
|
|
}
|
|
throw new Error("Unable to fetch app");
|
|
}
|
|
} catch (error) {
|
|
if(setLoadingStatePrivateApp){
|
|
|
|
setLoadingStatePrivateApp("Error! Unable to download private app.");
|
|
}
|
|
throw error;
|
|
}
|
|
|
|
let decryptedData;
|
|
// eslint-disable-next-line no-useless-catch
|
|
try {
|
|
decryptedData = await window.sendMessage(
|
|
"DECRYPT_QORTAL_GROUP_DATA",
|
|
|
|
{
|
|
base64: data,
|
|
groupId: privateAppProperties?.groupId,
|
|
}
|
|
);
|
|
if (decryptedData?.error) {
|
|
if(setLoadingStatePrivateApp){
|
|
|
|
setLoadingStatePrivateApp("Error! Unable to decrypt private app.");
|
|
}
|
|
throw new Error(decryptedData?.error);
|
|
}
|
|
} catch (error) {
|
|
if(setLoadingStatePrivateApp){
|
|
|
|
setLoadingStatePrivateApp("Error! Unable to decrypt private app.");
|
|
}
|
|
throw error;
|
|
}
|
|
|
|
try {
|
|
const convertToUint = base64ToUint8Array(decryptedData);
|
|
const UintToObject = uint8ArrayToObject(convertToUint);
|
|
|
|
if (decryptedData) {
|
|
setInfoSnackCustom({
|
|
type: "info",
|
|
message: "Building app",
|
|
});
|
|
const endpoint = await createEndpoint(
|
|
`/arbitrary/APP/${privateAppProperties?.name}/zip?preview=true`
|
|
);
|
|
const response = await fetch(endpoint, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "text/plain",
|
|
},
|
|
body: UintToObject?.app,
|
|
});
|
|
const previewPath = await response.text();
|
|
const refreshfunc = async (tabId, privateAppProperties) => {
|
|
const checkIfPreviewLinkStillWorksUrl = await createEndpoint(
|
|
`/render/hash/HmtnZpcRPwisMfprUXuBp27N2xtv5cDiQjqGZo8tbZS?secret=E39WTiG4qBq3MFcMPeRZabtQuzyfHg9ZuR5SgY7nW1YH`
|
|
);
|
|
const res = await fetch(checkIfPreviewLinkStillWorksUrl);
|
|
if (res.ok) {
|
|
executeEvent("refreshApp", {
|
|
tabId: tabId,
|
|
});
|
|
} else {
|
|
const endpoint = await createEndpoint(
|
|
`/arbitrary/APP/${privateAppProperties?.name}/zip?preview=true`
|
|
);
|
|
const response = await fetch(endpoint, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "text/plain",
|
|
},
|
|
body: UintToObject?.app,
|
|
});
|
|
const previewPath = await response.text();
|
|
executeEvent("updateAppUrl", {
|
|
tabId: tabId,
|
|
url: await createEndpoint(previewPath),
|
|
});
|
|
|
|
setTimeout(() => {
|
|
executeEvent("refreshApp", {
|
|
tabId: tabId,
|
|
});
|
|
}, 300);
|
|
}
|
|
};
|
|
|
|
const appName = UintToObject?.name;
|
|
const logo = UintToObject?.logo
|
|
? `data:image/png;base64,${UintToObject?.logo}`
|
|
: null;
|
|
|
|
const dataBody = {
|
|
url: await createEndpoint(previewPath),
|
|
isPreview: true,
|
|
isPrivate: true,
|
|
privateAppProperties: { ...privateAppProperties, logo, appName },
|
|
filePath: "",
|
|
refreshFunc: (tabId) => {
|
|
refreshfunc(tabId, privateAppProperties);
|
|
},
|
|
};
|
|
executeEvent("addTab", {
|
|
data: dataBody,
|
|
});
|
|
setInfoSnackCustom({
|
|
type: "success",
|
|
message: "Opened",
|
|
});
|
|
if(setLoadingStatePrivateApp){
|
|
|
|
setLoadingStatePrivateApp(``);
|
|
}
|
|
if (addToPinnedApps) {
|
|
setSortablePinnedApps((prev) => {
|
|
const updatedApps = [
|
|
...prev,
|
|
{
|
|
isPrivate: true,
|
|
isPreview: true,
|
|
privateAppProperties: {
|
|
...privateAppProperties,
|
|
logo,
|
|
appName,
|
|
},
|
|
},
|
|
];
|
|
|
|
saveToLocalStorage(
|
|
"ext_saved_settings",
|
|
"sortablePinnedApps",
|
|
updatedApps
|
|
);
|
|
return updatedApps;
|
|
});
|
|
setSettingsLocalLastUpdated(Date.now());
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if(setLoadingStatePrivateApp){
|
|
|
|
setLoadingStatePrivateApp(`Error! ${error?.message || 'Unable to build private app.'}`);
|
|
}
|
|
throw error
|
|
}
|
|
}
|
|
catch (error) {
|
|
setInfoSnackCustom({
|
|
type: "error",
|
|
message: error?.message || "Unable to fetch app",
|
|
});
|
|
}
|
|
|
|
};
|
|
return {
|
|
openApp,
|
|
status,
|
|
};
|
|
};
|