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, }; };