mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-03 21:52:11 +08:00
600b0b52f4
* chore(deps): update npm dependencies * Refactor components to use function syntax instead of forwardRef for better type handling and clarity. Updated imports and adjusted prop types accordingly across multiple viewer components including TrafficGraph, ProfileViewer, BackupViewer, ClashCoreViewer, ControllerViewer, DnsViewer, LiteModeViewer, NetworkInterfaceViewer, ThemeViewer, TunViewer, UpdateViewer, and WebUIViewer. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com>
129 lines
3.6 KiB
TypeScript
129 lines
3.6 KiB
TypeScript
import { Box, Divider, Paper } from "@mui/material";
|
|
import dayjs from "dayjs";
|
|
import customParseFormat from "dayjs/plugin/customParseFormat";
|
|
import type { Ref } from "react";
|
|
import { useCallback, useImperativeHandle, useMemo, useState } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
import { BaseDialog, BaseLoadingOverlay, DialogRef } from "@/components/base";
|
|
import { listWebDavBackup } from "@/services/cmds";
|
|
|
|
import { BackupConfigViewer } from "./backup-config-viewer";
|
|
import {
|
|
BackupFile,
|
|
BackupTableViewer,
|
|
DEFAULT_ROWS_PER_PAGE,
|
|
} from "./backup-table-viewer";
|
|
dayjs.extend(customParseFormat);
|
|
|
|
const DATE_FORMAT = "YYYY-MM-DD_HH-mm-ss";
|
|
const FILENAME_PATTERN = /\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}/;
|
|
|
|
export function BackupViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
|
const { t } = useTranslation();
|
|
const [open, setOpen] = useState(false);
|
|
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [backupFiles, setBackupFiles] = useState<BackupFile[]>([]);
|
|
const [total, setTotal] = useState(0);
|
|
const [page, setPage] = useState(0);
|
|
|
|
useImperativeHandle(ref, () => ({
|
|
open: () => {
|
|
setOpen(true);
|
|
},
|
|
close: () => setOpen(false),
|
|
}));
|
|
|
|
// Handle page change
|
|
const handleChangePage = useCallback(
|
|
(_: React.MouseEvent<HTMLButtonElement> | null, page: number) => {
|
|
setPage(page);
|
|
},
|
|
[],
|
|
);
|
|
|
|
const fetchAndSetBackupFiles = async () => {
|
|
try {
|
|
setIsLoading(true);
|
|
const files = await getAllBackupFiles();
|
|
setBackupFiles(files);
|
|
setTotal(files.length);
|
|
} catch (error) {
|
|
setBackupFiles([]);
|
|
setTotal(0);
|
|
console.error(error);
|
|
// Notice.error(t("Failed to fetch backup files"));
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const getAllBackupFiles = async () => {
|
|
const files = await listWebDavBackup();
|
|
return files
|
|
.map((file) => {
|
|
const platform = file.filename.split("-")[0];
|
|
const fileBackupTimeStr = file.filename.match(FILENAME_PATTERN)!;
|
|
|
|
if (fileBackupTimeStr === null) {
|
|
return null;
|
|
}
|
|
|
|
const backupTime = dayjs(fileBackupTimeStr[0], DATE_FORMAT);
|
|
const allowApply = true;
|
|
return {
|
|
...file,
|
|
platform,
|
|
backup_time: backupTime,
|
|
allow_apply: allowApply,
|
|
} as BackupFile;
|
|
})
|
|
.filter((item) => item !== null)
|
|
.sort((a, b) => (a.backup_time.isAfter(b.backup_time) ? -1 : 1));
|
|
};
|
|
|
|
const dataSource = useMemo<BackupFile[]>(
|
|
() =>
|
|
backupFiles.slice(
|
|
page * DEFAULT_ROWS_PER_PAGE,
|
|
page * DEFAULT_ROWS_PER_PAGE + DEFAULT_ROWS_PER_PAGE,
|
|
),
|
|
[backupFiles, page],
|
|
);
|
|
|
|
return (
|
|
<BaseDialog
|
|
open={open}
|
|
title={t("Backup Setting")}
|
|
// contentSx={{ width: 600, maxHeight: 800 }}
|
|
okBtn={t("")}
|
|
cancelBtn={t("Close")}
|
|
onClose={() => setOpen(false)}
|
|
onCancel={() => setOpen(false)}
|
|
disableOk
|
|
>
|
|
<Box>
|
|
<BaseLoadingOverlay isLoading={isLoading} />
|
|
<Paper elevation={2} sx={{ padding: 2 }}>
|
|
<BackupConfigViewer
|
|
setLoading={setIsLoading}
|
|
onBackupSuccess={fetchAndSetBackupFiles}
|
|
onSaveSuccess={fetchAndSetBackupFiles}
|
|
onRefresh={fetchAndSetBackupFiles}
|
|
onInit={fetchAndSetBackupFiles}
|
|
/>
|
|
<Divider sx={{ marginY: 2 }} />
|
|
<BackupTableViewer
|
|
datasource={dataSource}
|
|
page={page}
|
|
onPageChange={handleChangePage}
|
|
total={total}
|
|
onRefresh={fetchAndSetBackupFiles}
|
|
/>
|
|
</Paper>
|
|
</Box>
|
|
</BaseDialog>
|
|
);
|
|
}
|