mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-05-31 05:36:59 +00:00
276 lines
8.2 KiB
TypeScript
276 lines
8.2 KiB
TypeScript
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,
|
|
};
|
|
};
|