import { Button, Modal, ModalProps } from "@renderer/components"; import { useContext, useEffect, useMemo, useState } from "react"; import { cloudSyncContext, gameDetailsContext } from "@renderer/context"; import * as styles from "./cloud-sync-modal.css"; import { formatBytes } from "@shared"; import { format } from "date-fns"; import { ClockIcon, DeviceDesktopIcon, HistoryIcon, InfoIcon, SyncIcon, TrashIcon, UploadIcon, } from "@primer/octicons-react"; import { useToast } from "@renderer/hooks"; import { useTranslation } from "react-i18next"; import { AxiosProgressEvent } from "axios"; import { formatDownloadProgress } from "@renderer/helpers"; import { SPACING_UNIT } from "@renderer/theme.css"; export interface CloudSyncModalProps extends Omit {} export function CloudSyncModal({ visible, onClose }: CloudSyncModalProps) { const [deletingArtifact, setDeletingArtifact] = useState(false); const [backupDownloadProgress, setBackupDownloadProgress] = useState(null); const { t } = useTranslation("game_details"); const { artifacts, backupPreview, uploadingBackup, restoringBackup, loadingPreview, uploadSaveGame, downloadGameArtifact, deleteGameArtifact, setShowCloudSyncFilesModal, } = useContext(cloudSyncContext); const { objectId, shop, gameTitle, lastDownloadedOption } = useContext(gameDetailsContext); const { showSuccessToast, showErrorToast } = useToast(); const handleDeleteArtifactClick = async (gameArtifactId: string) => { setDeletingArtifact(true); try { await deleteGameArtifact(gameArtifactId); showSuccessToast(t("backup_deleted")); } catch (err) { showErrorToast("backup_deletion_failed"); } finally { setDeletingArtifact(false); } }; useEffect(() => { const removeBackupDownloadProgressListener = window.electron.onBackupDownloadProgress( objectId!, shop, (progressEvent) => { setBackupDownloadProgress(progressEvent); } ); return () => { removeBackupDownloadProgressListener(); }; }, [backupPreview, objectId, shop]); const handleBackupInstallClick = async (artifactId: string) => { setBackupDownloadProgress(null); downloadGameArtifact(artifactId); }; const backupStateLabel = useMemo(() => { if (uploadingBackup) { return ( {t("uploading_backup")} ); } if (restoringBackup) { return ( {t("restoring_backup", { progress: formatDownloadProgress( backupDownloadProgress?.progress ?? 0 ), })} ); } if (loadingPreview) { return ( {t("loading_save_preview")} ); } if (artifacts.length >= 2) { return t("max_number_of_artifacts_reached"); } if (!backupPreview) { return t("no_backup_preview"); } return t("no_backups"); }, [ uploadingBackup, backupDownloadProgress?.progress, backupPreview, restoringBackup, loadingPreview, artifacts, t, ]); const disableActions = uploadingBackup || restoringBackup || deletingArtifact; return (

{gameTitle}

{backupStateLabel}

{t("backups")}

{artifacts.length} / 2
{artifacts.length > 0 ? (
    {artifacts.map((artifact, index) => (
  • {t("backup_title", { number: index + 1 })}

    {formatBytes(artifact.artifactLengthInBytes)}
    {artifact.hostname} {artifact.downloadOptionTitle ?? t("no_download_option_info")} {format(artifact.createdAt, "dd/MM/yyyy HH:mm:ss")}
  • ))}
) : (

{t("no_backups_created")}

)}
); }