import { useContext, useState } from 'react'; import { executeEvent } from '../utils/events'; import { getBaseApiReact, MyContext } from '../App'; import { createEndpoint } from '../background'; import { settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom, } from '../atoms/global'; import { saveToLocalStorage } from '../components/Apps/AppsNavBarDesktop'; import { base64ToUint8Array } from '../qdn/encryption/group-encryption'; import { uint8ArrayToObject } from '../backgroundFunctions/encryption'; import { useSetAtom } from 'jotai'; import { useTranslation } from 'react-i18next'; export const useHandlePrivateApps = () => { const [status, setStatus] = useState(''); const { openSnackGlobal, setOpenSnackGlobal, infoSnackCustom, setInfoSnackCustom, } = useContext(MyContext); const setSortablePinnedApps = useSetAtom(sortablePinnedAppsAtom); const setSettingsLocalLastUpdated = useSetAtom(settingsLocalLastUpdatedAtom); const { t } = useTranslation(['auth', 'core', 'group']); const openApp = async ( privateAppProperties, addToPinnedApps, setLoadingStatePrivateApp ) => { try { if (setLoadingStatePrivateApp) { setLoadingStatePrivateApp( t('core:message.generic.downloading_decrypting_app', { postProcess: 'capitalizeFirstChar', }) ); } setOpenSnackGlobal(true); setInfoSnackCustom({ type: 'info', message: t('core:message.generic.fetching_data', { postProcess: 'capitalizeFirstChar', }), 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( t('core:message.generic.unable_download_private_app', { postProcess: 'capitalizeFirstChar', }) ); } throw new Error( t('core:message.error.fetch_app', { postProcess: 'capitalizeFirstChar', }) ); } data = await responseData.text(); if (data?.error) { if (setLoadingStatePrivateApp) { setLoadingStatePrivateApp( t('core:message.generic.unable_download_private_app', { postProcess: 'capitalizeFirstChar', }) ); } throw new Error( t('core:message.generic.unable_fetch_app', { postProcess: 'capitalizeFirstChar', }) ); } } catch (error) { if (setLoadingStatePrivateApp) { setLoadingStatePrivateApp( t('core:message.generic.unable_download_private_app', { postProcess: 'capitalizeFirstChar', }) ); } 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( t('core:message.generic.unable_decrypt_app', { postProcess: 'capitalizeFirstChar', }) ); } throw new Error(decryptedData?.error); } } catch (error) { if (setLoadingStatePrivateApp) { setLoadingStatePrivateApp( t('core:message.generic.unable_decrypt_app', { postProcess: 'capitalizeFirstChar', }) ); } throw error; } try { const convertToUint = base64ToUint8Array(decryptedData); const UintToObject = uint8ArrayToObject(convertToUint); if (decryptedData) { setInfoSnackCustom({ type: 'info', message: t('core:message.generic.building_app', { postProcess: 'capitalizeFirstChar', }), }); 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: t('core:message.generic.opened', { postProcess: 'capitalizeFirstChar', }), }); 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 || t('core:message.error.build_app', { postProcess: 'capitalizeFirstChar', }) }` ); } throw error; } } catch (error) { setInfoSnackCustom({ type: 'error', message: error?.message || t('core:message.error.fetch_app', { postProcess: 'capitalizeFirstChar', }), }); } }; return { openApp, status, }; };