import DeleteIcon from "@mui/icons-material/Delete"; import DownloadIcon from "@mui/icons-material/Download"; import RestoreIcon from "@mui/icons-material/Restore"; import { Box, Paper, IconButton, Divider, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TablePagination, } from "@mui/material"; import { Typography } from "@mui/material"; import { save } from "@tauri-apps/plugin-dialog"; import { useLockFn } from "ahooks"; import { Dayjs } from "dayjs"; import { SVGProps, memo } from "react"; import { useTranslation } from "react-i18next"; import { restartApp } from "@/services/cmds"; import { showNotice } from "@/services/noticeService"; export type BackupFile = { platform: string; backup_time: Dayjs; allow_apply: boolean; filename: string; }; export const DEFAULT_ROWS_PER_PAGE = 5; type ConfirmFn = (message?: string) => boolean | Promise; // Normalizes synchronous and async confirm implementations. const confirmAsync = async (message: string): Promise => { const confirmFn = window.confirm as unknown as ConfirmFn; return await confirmFn.call(window, message); }; interface BackupTableViewerProps { datasource: BackupFile[]; page: number; onPageChange: ( event: React.MouseEvent | null, page: number, ) => void; total: number; onRefresh: () => Promise; onDelete: (filename: string) => Promise; onRestore: (filename: string) => Promise; onExport?: (filename: string, destination: string) => Promise; } export const BackupTableViewer = memo( ({ datasource, page, onPageChange, total, onRefresh, onDelete, onRestore, onExport, }: BackupTableViewerProps) => { const { t } = useTranslation(); const handleDelete = useLockFn(async (filename: string) => { await onDelete(filename); await onRefresh(); }); const handleRestore = useLockFn(async (filename: string) => { await onRestore(filename).then(() => { showNotice.success("settings.modals.backup.messages.restoreSuccess"); }); await restartApp(); }); const handleExport = useLockFn(async (filename: string) => { if (!onExport) { return; } try { const savePath = await save({ defaultPath: filename, }); if (!savePath || Array.isArray(savePath)) { return; } await onExport(filename, savePath); showNotice.success( "settings.modals.backup.messages.localBackupExported", ); } catch (error) { console.error(error); showNotice.error( "settings.modals.backup.messages.localBackupExportFailed", ); } }); return ( {t("settings.modals.backup.table.filename")} {t("settings.modals.backup.table.backupTime")} {t("settings.modals.backup.table.actions")} {datasource.length > 0 ? ( datasource.map((file) => { const rowKey = `${file.platform}-${file.filename}-${file.backup_time.valueOf()}`; return ( {file.platform === "windows" ? ( ) : file.platform === "linux" ? ( ) : ( )} {file.filename} {file.backup_time.fromNow()} {onExport && ( <> { e.preventDefault(); await handleExport(file.filename); }} > )} { e.preventDefault(); const confirmed = await confirmAsync( t( "settings.modals.backup.messages.confirmDelete", ), ); if (confirmed) { await handleDelete(file.filename); } }} > { e.preventDefault(); const confirmed = await confirmAsync( t( "settings.modals.backup.messages.confirmRestore", ), ); if (confirmed) { await handleRestore(file.filename); } }} > ); }) ) : ( {t("settings.modals.backup.table.noBackups")} )}
); }, ); function LinuxIcon(props: SVGProps) { return ( ); } function WindowsIcon(props: SVGProps) { return ( ); } function MacIcon(props: SVGProps) { return ( ); }