import { useState } from 'react'; import { toast } from 'react-toastify'; import DownloadIcon from '@mui/icons-material/GetApp'; import { Box, Button, Divider, Link, Typography } from '@mui/material'; import * as SystemApi from 'api/system'; import { API, getCustomizations, getEntities, getSchedule, getSettings } from 'api/app'; import { getDevVersion, getStableVersion } from 'api/system'; // import { useRequest } from 'alova/client' // TODO replace when Alova 3 is released import { useRequest } from 'alova'; import type { APIcall } from 'app/main/types'; import { FormLoader, SectionContent, SingleUpload, useLayoutTitle } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; import RestartMonitor from '../status/RestartMonitor'; const UploadDownload = () => { const { LL } = useI18nContext(); const [restarting, setRestarting] = useState(); const [md5, setMd5] = useState(); const { send: sendSettings, onSuccess: onSuccessGetSettings } = useRequest( getSettings(), { immediate: false } ); const { send: sendCustomizations, onSuccess: onSuccessGetCustomizations } = useRequest(getCustomizations(), { immediate: false }); const { send: sendEntities, onSuccess: onSuccessGetEntities } = useRequest( getEntities(), { immediate: false } ); const { send: sendSchedule, onSuccess: onSuccessGetSchedule } = useRequest( getSchedule(), { immediate: false } ); const { send: getAPI, onSuccess: onGetAPI } = useRequest( (data: APIcall) => API(data), { immediate: false } ); // Alova 3 code... // const { // loading: isUploading, // uploading: progress, // send: sendUpload, // abort: cancelUpload // } = useRequest(SystemApi.uploadFile, { // immediate: false // }).onSuccess(({ data }) => { // if (data) { // setMd5(data.md5); // toast.success(LL.UPLOAD() + ' MD5 ' + LL.SUCCESSFUL()); // } else { // setRestarting(true); // } // }); const { loading: isUploading, uploading: progress, send: sendUpload, onSuccess: onSuccessUpload, abort: cancelUpload } = useRequest(SystemApi.uploadFile, { immediate: false }); onSuccessUpload(({ data }) => { if (data) { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument setMd5(data.md5); toast.success(LL.UPLOAD() + ' MD5 ' + LL.SUCCESSFUL()); } else { setRestarting(true); } }); onSuccessGetSettings((event) => { saveFile(event.data, 'settings.json'); }); onSuccessGetCustomizations((event) => { saveFile(event.data, 'customizations.json'); }); onSuccessGetEntities((event) => { saveFile(event.data, 'entities.json'); }); onSuccessGetSchedule((event) => { saveFile(event.data, 'schedule.json'); }); onGetAPI((event) => { saveFile( event.data, event.sendArgs[0].device + '_' + event.sendArgs[0].entity + '.txt' ); }); // TODO Alova 3 code... /* const { send: sendSettings } = useRequest(getSettings(), { immediate: false }).onSuccess((event) => { saveFile(event.data, 'settings.json'); }); const { send: sendCustomizations } = useRequest(getCustomizations(), { immediate: false }).onSuccess((event) => { saveFile(event.data, 'customizations.json'); }); const { send: sendEntities } = useRequest(getEntities(), { immediate: false }).onSuccess((event) => { saveFile(event.data, 'entities.json'); }); const { send: sendSchedule } = useRequest(getSchedule(), { immediate: false }).onSuccess((event) => { saveFile(event.data, 'schedule.json'); }); const { send: getAPI } = useRequest((data: APIcall) => API(data), { immediate: false }).onSuccess((event) => { saveFile( event.data, String(event.args[0].device) + '_' + String(event.args[0].entity) + '.txt' ); }); */ const { data: data, send: loadData, error } = useRequest(SystemApi.readHardwareStatus); // called immediately to get the latest version, on page load const { data: latestVersion } = useRequest(getStableVersion); const { data: latestDevVersion } = useRequest(getDevVersion); const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/'; const STABLE_RELNOTES_URL = 'https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md'; const DEV_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/latest/'; const DEV_RELNOTES_URL = 'https://github.com/emsesp/EMS-ESP32/blob/dev/CHANGELOG_LATEST.md'; const getBinURL = (v: string) => 'EMS-ESP-' + v.replaceAll('.', '_') + '-' + getPlatform().replaceAll('-', '_') + '.bin'; const getPlatform = () => { if (data.flash_chip_size === 16384 && data.esp_platform !== 'ESP32-S3') { return data.esp_platform + '-16M'; } return data.esp_platform; }; const startUpload = async (files: File[]) => { await sendUpload(files[0]).catch((error: Error) => { if (error.message === 'The user aborted a request') { toast.warning(LL.UPLOAD() + ' ' + LL.ABORTED()); } else if (error.message === 'Network Error') { toast.warning('Invalid file extension or incompatible bin file'); } else { toast.error(error.message); } }); }; const saveFile = (json: unknown, endpoint: string) => { const anchor = document.createElement('a'); anchor.href = URL.createObjectURL( new Blob([JSON.stringify(json, null, 2)], { type: 'text/plain' }) ); anchor.download = 'emsesp_' + endpoint; anchor.click(); URL.revokeObjectURL(anchor.href); toast.info(LL.DOWNLOAD_SUCCESSFUL()); }; const downloadSettings = async () => { await sendSettings().catch((error: Error) => { toast.error(error.message); }); }; const downloadCustomizations = async () => { await sendCustomizations().catch((error: Error) => { toast.error(error.message); }); }; const downloadEntities = async () => { await sendEntities().catch((error: Error) => { toast.error(error.message); }); }; const downloadSchedule = async () => { await sendSchedule().catch((error: Error) => { toast.error(error.message); }); }; const callAPI = async (device: string, entity: string) => { await getAPI({ device, entity, id: 0 }).catch((error: Error) => { toast.error(error.message); }); }; useLayoutTitle(LL.UPLOAD_DOWNLOAD()); const content = () => { if (!data) { return ; } return ( <> {LL.EMS_ESP_VER()} {LL.VERSION_ON() + ' '} {data.emsesp_version} ({getPlatform()}) {latestVersion && ( {LL.THE_LATEST()} {LL.OFFICIAL()} {LL.RELEASE_IS()}  {latestVersion}  ( {LL.RELEASE_NOTES()} ) ( {LL.DOWNLOAD(1)} ) )} {latestDevVersion && ( {LL.THE_LATEST()} {LL.DEVELOPMENT()} {LL.RELEASE_IS()}   {latestDevVersion}  ( {LL.RELEASE_NOTES()} ) ( {LL.DOWNLOAD(1)} ) )} {LL.UPLOAD()} {LL.UPLOAD_TEXT()}

{LL.RESTART_TEXT(1)}.
{md5 && ( {'MD5: ' + md5} )} {!isUploading && ( <> {LL.DOWNLOAD(0)} {LL.HELP_INFORMATION_4()} {LL.DOWNLOAD_SETTINGS_TEXT()} {LL.DOWNLOAD_CUSTOMIZATION_TEXT()} {LL.DOWNLOAD_SCHEDULE_TEXT()} )} ); }; return ( {restarting ? : content()} ); }; export default UploadDownload;