From a54360cc69c0425acfd4c0b33b603abc68121508 Mon Sep 17 00:00:00 2001 From: africa1207 <651124360@qq.com> Date: Sun, 13 Apr 2025 21:52:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96webdav=E5=A4=87?= =?UTF-8?q?=E4=BB=BD=E6=96=87=E4=BB=B6=E6=81=A2=E5=A4=8D=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20(#4699)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 优化webdav备份文件恢复管理功能 * fix: 恢复和删除操作更改为文字而非图标 * feat: 统一坚果云与webdav备份恢复功能 --- .vscode/settings.json | 10 +- packages/shared/IpcChannel.ts | 1 + src/main/ipc.ts | 1 + src/main/services/BackupManager.ts | 11 + src/main/services/WebDav.ts | 16 + src/preload/index.d.ts | 1 + src/preload/index.ts | 4 +- .../src/components/WebdavBackupManager.tsx | 283 ++++++++++++++++++ src/renderer/src/i18n/locales/en-us.json | 19 ++ src/renderer/src/i18n/locales/ja-jp.json | 19 ++ src/renderer/src/i18n/locales/ru-ru.json | 19 ++ src/renderer/src/i18n/locales/zh-cn.json | 19 ++ src/renderer/src/i18n/locales/zh-tw.json | 19 ++ .../DataSettings/NutstoreSettings.tsx | 57 ++-- .../settings/DataSettings/WebDavSettings.tsx | 50 ++-- 15 files changed, 466 insertions(+), 63 deletions(-) create mode 100644 src/renderer/src/components/WebdavBackupManager.tsx diff --git a/.vscode/settings.json b/.vscode/settings.json index 1b0d190d..bb788977 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -31,5 +31,13 @@ "[markdown]": { "files.trimTrailingWhitespace": false }, - "i18n-ally.localesPaths": ["src/renderer/src/i18n"] + "i18n-ally.localesPaths": ["src/renderer/src/i18n/locales"], + "i18n-ally.enabledFrameworks": ["react-i18next", "i18next"], + "i18n-ally.keystyle": "nested", // 翻译路径格式 + "i18n-ally.sortKeys": true, // 排序 + "i18n-ally.namespace": true, // 开启命名空间 + "i18n-ally.enabledParsers": ["ts", "js", "json"], // 解析语言 + "i18n-ally.sourceLanguage": "en-us", // 翻译源语言 + "i18n-ally.displayLanguage": "zh-cn", + "i18n-ally.fullReloadOnChanged": true // 界面显示语言 } diff --git a/packages/shared/IpcChannel.ts b/packages/shared/IpcChannel.ts index 176f5a36..29433a2d 100644 --- a/packages/shared/IpcChannel.ts +++ b/packages/shared/IpcChannel.ts @@ -120,6 +120,7 @@ export enum IpcChannel { Backup_ListWebdavFiles = 'backup:listWebdavFiles', Backup_CheckConnection = 'backup:checkConnection', Backup_CreateDirectory = 'backup:createDirectory', + Backup_DeleteWebdavFile = 'backup:deleteWebdavFile', // zip Zip_Compress = 'zip:compress', diff --git a/src/main/ipc.ts b/src/main/ipc.ts index d5dd4936..ec3aec58 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -182,6 +182,7 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { ipcMain.handle(IpcChannel.Backup_ListWebdavFiles, backupManager.listWebdavFiles) ipcMain.handle(IpcChannel.Backup_CheckConnection, backupManager.checkConnection) ipcMain.handle(IpcChannel.Backup_CreateDirectory, backupManager.createDirectory) + ipcMain.handle(IpcChannel.Backup_DeleteWebdavFile, backupManager.deleteWebdavFile) // file ipcMain.handle(IpcChannel.File_Open, fileManager.open) diff --git a/src/main/services/BackupManager.ts b/src/main/services/BackupManager.ts index 136ffbce..f29c6920 100644 --- a/src/main/services/BackupManager.ts +++ b/src/main/services/BackupManager.ts @@ -22,6 +22,7 @@ class BackupManager { this.backupToWebdav = this.backupToWebdav.bind(this) this.restoreFromWebdav = this.restoreFromWebdav.bind(this) this.listWebdavFiles = this.listWebdavFiles.bind(this) + this.deleteWebdavFile = this.deleteWebdavFile.bind(this) } private async setWritableRecursive(dirPath: string): Promise { @@ -309,6 +310,16 @@ class BackupManager { const webdavClient = new WebDav(webdavConfig) return await webdavClient.createDirectory(path, options) } + + async deleteWebdavFile(_: Electron.IpcMainInvokeEvent, fileName: string, webdavConfig: WebDavConfig) { + try { + const webdavClient = new WebDav(webdavConfig) + return await webdavClient.deleteFile(fileName) + } catch (error: any) { + Logger.error('Failed to delete WebDAV file:', error) + throw new Error(error.message || 'Failed to delete backup file') + } + } } export default BackupManager diff --git a/src/main/services/WebDav.ts b/src/main/services/WebDav.ts index 356ebeba..e78dfdee 100644 --- a/src/main/services/WebDav.ts +++ b/src/main/services/WebDav.ts @@ -26,6 +26,7 @@ export default class WebDav { this.putFileContents = this.putFileContents.bind(this) this.getFileContents = this.getFileContents.bind(this) this.createDirectory = this.createDirectory.bind(this) + this.deleteFile = this.deleteFile.bind(this) } public putFileContents = async ( @@ -98,4 +99,19 @@ export default class WebDav { throw error } } + + public deleteFile = async (filename: string) => { + if (!this.instance) { + throw new Error('WebDAV client not initialized') + } + + const remoteFilePath = `${this.webdavPath}/${filename}` + + try { + return await this.instance.deleteFile(remoteFilePath) + } catch (error) { + Logger.error('[WebDAV] Error deleting file on WebDAV:', error) + throw error + } + } } diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts index 0ebbc48f..18bb3b00 100644 --- a/src/preload/index.d.ts +++ b/src/preload/index.d.ts @@ -46,6 +46,7 @@ declare global { listWebdavFiles: (webdavConfig: WebDavConfig) => Promise checkConnection: (webdavConfig: WebDavConfig) => Promise createDirectory: (webdavConfig: WebDavConfig, path: string, options?: CreateDirectoryOptions) => Promise + deleteWebdavFile: (fileName: string, webdavConfig: WebDavConfig) => Promise } file: { select: (options?: OpenDialogOptions) => Promise diff --git a/src/preload/index.ts b/src/preload/index.ts index 664acd9c..882a15b7 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -41,7 +41,9 @@ const api = { checkConnection: (webdavConfig: WebDavConfig) => ipcRenderer.invoke(IpcChannel.Backup_CheckConnection, webdavConfig), createDirectory: (webdavConfig: WebDavConfig, path: string, options?: CreateDirectoryOptions) => - ipcRenderer.invoke(IpcChannel.Backup_CreateDirectory, webdavConfig, path, options) + ipcRenderer.invoke(IpcChannel.Backup_CreateDirectory, webdavConfig, path, options), + deleteWebdavFile: (fileName: string, webdavConfig: WebDavConfig) => + ipcRenderer.invoke(IpcChannel.Backup_DeleteWebdavFile, fileName, webdavConfig) }, file: { select: (options?: OpenDialogOptions) => ipcRenderer.invoke(IpcChannel.File_Select, options), diff --git a/src/renderer/src/components/WebdavBackupManager.tsx b/src/renderer/src/components/WebdavBackupManager.tsx new file mode 100644 index 00000000..32532579 --- /dev/null +++ b/src/renderer/src/components/WebdavBackupManager.tsx @@ -0,0 +1,283 @@ +import { DeleteOutlined, ExclamationCircleOutlined, ReloadOutlined } from '@ant-design/icons' +import { restoreFromWebdav } from '@renderer/services/BackupService' +import { formatFileSize } from '@renderer/utils' +import { Button, message, Modal, Table, Tooltip } from 'antd' +import dayjs from 'dayjs' +import { useCallback, useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' + +interface BackupFile { + fileName: string + modifiedTime: string + size: number +} + +interface WebdavConfig { + webdavHost: string + webdavUser: string + webdavPass: string + webdavPath: string +} + +interface WebdavBackupManagerProps { + visible: boolean + onClose: () => void + webdavConfig: { + webdavHost?: string + webdavUser?: string + webdavPass?: string + webdavPath?: string + } + restoreMethod?: (fileName: string) => Promise +} + +export function WebdavBackupManager({ visible, onClose, webdavConfig, restoreMethod }: WebdavBackupManagerProps) { + const { t } = useTranslation() + const [backupFiles, setBackupFiles] = useState([]) + const [loading, setLoading] = useState(false) + const [selectedRowKeys, setSelectedRowKeys] = useState([]) + const [deleting, setDeleting] = useState(false) + const [restoring, setRestoring] = useState(false) + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 5, + total: 0 + }) + + const { webdavHost, webdavUser, webdavPass, webdavPath } = webdavConfig + + const fetchBackupFiles = useCallback(async () => { + if (!webdavHost || !webdavUser || !webdavPass || !webdavPath) { + message.error(t('message.error.invalid.webdav')) + return + } + + setLoading(true) + try { + const files = await window.api.backup.listWebdavFiles({ + webdavHost, + webdavUser, + webdavPass, + webdavPath + } as WebdavConfig) + setBackupFiles(files) + setPagination((prev) => ({ + ...prev, + total: files.length + })) + } catch (error: any) { + message.error(`${t('settings.data.webdav.backup.manager.fetch.error')}: ${error.message}`) + } finally { + setLoading(false) + } + }, [webdavHost, webdavUser, webdavPass, webdavPath, t]) + + useEffect(() => { + if (visible) { + fetchBackupFiles() + setSelectedRowKeys([]) + setPagination((prev) => ({ + ...prev, + current: 1 + })) + } + }, [visible, fetchBackupFiles]) + + const handleTableChange = (pagination: any) => { + setPagination(pagination) + } + + const handleDeleteSelected = async () => { + if (selectedRowKeys.length === 0) { + message.warning(t('settings.data.webdav.backup.manager.select.files.delete')) + return + } + + if (!webdavHost || !webdavUser || !webdavPass || !webdavPath) { + message.error(t('message.error.invalid.webdav')) + return + } + + Modal.confirm({ + title: t('settings.data.webdav.backup.manager.delete.confirm.title'), + icon: , + content: t('settings.data.webdav.backup.manager.delete.confirm.multiple', { count: selectedRowKeys.length }), + okText: t('common.confirm'), + cancelText: t('common.cancel'), + onOk: async () => { + setDeleting(true) + try { + // 依次删除选中的文件 + for (const key of selectedRowKeys) { + await window.api.backup.deleteWebdavFile(key.toString(), { + webdavHost, + webdavUser, + webdavPass, + webdavPath + } as WebdavConfig) + } + message.success( + t('settings.data.webdav.backup.manager.delete.success.multiple', { count: selectedRowKeys.length }) + ) + setSelectedRowKeys([]) + await fetchBackupFiles() + } catch (error: any) { + message.error(`${t('settings.data.webdav.backup.manager.delete.error')}: ${error.message}`) + } finally { + setDeleting(false) + } + } + }) + } + + const handleDeleteSingle = async (fileName: string) => { + if (!webdavHost || !webdavUser || !webdavPass || !webdavPath) { + message.error(t('message.error.invalid.webdav')) + return + } + + Modal.confirm({ + title: t('settings.data.webdav.backup.manager.delete.confirm.title'), + icon: , + content: t('settings.data.webdav.backup.manager.delete.confirm.single', { fileName }), + okText: t('common.confirm'), + cancelText: t('common.cancel'), + onOk: async () => { + setDeleting(true) + try { + await window.api.backup.deleteWebdavFile(fileName, { + webdavHost, + webdavUser, + webdavPass, + webdavPath + } as WebdavConfig) + message.success(t('settings.data.webdav.backup.manager.delete.success.single')) + await fetchBackupFiles() + } catch (error: any) { + message.error(`${t('settings.data.webdav.backup.manager.delete.error')}: ${error.message}`) + } finally { + setDeleting(false) + } + } + }) + } + + const handleRestore = async (fileName: string) => { + if (!webdavHost || !webdavUser || !webdavPass || !webdavPath) { + message.error(t('message.error.invalid.webdav')) + return + } + + Modal.confirm({ + title: t('settings.data.webdav.restore.confirm.title'), + icon: , + content: t('settings.data.webdav.restore.confirm.content'), + okText: t('common.confirm'), + cancelText: t('common.cancel'), + onOk: async () => { + setRestoring(true) + try { + await (restoreMethod || restoreFromWebdav)(fileName) + message.success(t('settings.data.webdav.backup.manager.restore.success')) + onClose() // 关闭模态框 + } catch (error: any) { + message.error(`${t('settings.data.webdav.backup.manager.restore.error')}: ${error.message}`) + } finally { + setRestoring(false) + } + } + }) + } + + const columns = [ + { + title: t('settings.data.webdav.backup.manager.columns.fileName'), + dataIndex: 'fileName', + key: 'fileName', + ellipsis: { + showTitle: false + }, + render: (fileName: string) => ( + + {fileName} + + ) + }, + { + title: t('settings.data.webdav.backup.manager.columns.modifiedTime'), + dataIndex: 'modifiedTime', + key: 'modifiedTime', + width: 180, + render: (time: string) => dayjs(time).format('YYYY-MM-DD HH:mm:ss') + }, + { + title: t('settings.data.webdav.backup.manager.columns.size'), + dataIndex: 'size', + key: 'size', + width: 120, + render: (size: number) => formatFileSize(size) + }, + { + title: t('settings.data.webdav.backup.manager.columns.actions'), + key: 'action', + width: 160, + render: (_: any, record: BackupFile) => ( + <> + + + + ) + } + ] + + const rowSelection = { + selectedRowKeys, + onChange: (selectedRowKeys: React.Key[]) => { + setSelectedRowKeys(selectedRowKeys) + } + } + + return ( + } onClick={fetchBackupFiles} disabled={loading}> + {t('settings.data.webdav.backup.manager.refresh')} + , + , + + ]}> + + + ) +} diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 83b64321..51c0c4e1 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -879,6 +879,25 @@ "backup.button": "Backup to WebDAV", "backup.modal.filename.placeholder": "Please enter backup filename", "backup.modal.title": "Backup to WebDAV", + "backup.manager.title": "Backup Data Management", + "backup.manager.refresh": "Refresh", + "backup.manager.delete.selected": "Delete Selected", + "backup.manager.delete.text": "Delete", + "backup.manager.restore.text": "Restore", + "backup.manager.restore.success": "Restore successful, application will refresh shortly", + "backup.manager.restore.error": "Restore failed", + "backup.manager.delete.confirm.title": "Confirm Delete", + "backup.manager.delete.confirm.single": "Are you sure you want to delete backup file \"{{fileName}}\"? This action cannot be undone.", + "backup.manager.delete.confirm.multiple": "Are you sure you want to delete {{count}} selected backup files? This action cannot be undone.", + "backup.manager.delete.success.single": "Deleted successfully", + "backup.manager.delete.success.multiple": "Successfully deleted {{count}} backup files", + "backup.manager.delete.error": "Delete failed", + "backup.manager.fetch.error": "Failed to get backup files", + "backup.manager.select.files.delete": "Please select backup files to delete", + "backup.manager.columns.fileName": "Filename", + "backup.manager.columns.modifiedTime": "Modified Time", + "backup.manager.columns.size": "Size", + "backup.manager.columns.actions": "Actions", "host": "WebDAV Host", "host.placeholder": "http://localhost:8080", "hour_interval_one": "{{count}} hour", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index 3c04c690..cda00b69 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -879,6 +879,25 @@ "backup.button": "WebDAVにバックアップ", "backup.modal.filename.placeholder": "バックアップファイル名を入力してください", "backup.modal.title": "WebDAV にバックアップ", + "backup.manager.title": "バックアップデータ管理", + "backup.manager.refresh": "更新", + "backup.manager.delete.selected": "選択したものを ", + "backup.manager.delete.text": "削除", + "backup.manager.restore.text": "復元", + "backup.manager.restore.success": "復元が成功しました、アプリケーションは間もなく更新されます", + "backup.manager.restore.error": "復元に失敗しました", + "backup.manager.delete.confirm.title": "削除の確認", + "backup.manager.delete.confirm.single": "バックアップファイル \"{{fileName}}\" を削除してもよろしいですか?この操作は元に戻せません。", + "backup.manager.delete.confirm.multiple": "選択した {{count}} 個のバックアップファイルを削除してもよろしいですか?この操作は元に戻せません。", + "backup.manager.delete.success.single": "削除が成功しました", + "backup.manager.delete.success.multiple": "{{count}} 個のバックアップファイルを削除しました", + "backup.manager.delete.error": "削除に失敗しました", + "backup.manager.fetch.error": "バックアップファイルの取得に失敗しました", + "backup.manager.select.files.delete": "削除するバックアップファイルを選択してください", + "backup.manager.columns.fileName": "ファイル名", + "backup.manager.columns.modifiedTime": "更新日時", + "backup.manager.columns.size": "サイズ", + "backup.manager.columns.actions": "操作", "host": "WebDAVホスト", "host.placeholder": "http://localhost:8080", "hour_interval_one": "{{count}} 時間", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index beabbd0b..bfb734ab 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -879,6 +879,25 @@ "backup.button": "Резервное копирование на WebDAV", "backup.modal.filename.placeholder": "Введите имя файла резервной копии", "backup.modal.title": "Резервное копирование на WebDAV", + "backup.manager.title": "Управление резервными копиями", + "backup.manager.refresh": "Обновить", + "backup.manager.delete.selected": "Удалить выбранные", + "backup.manager.delete.text": "Удалить", + "backup.manager.restore.text": "Восстановить", + "backup.manager.restore.success": "Восстановление прошло успешно, приложение скоро обновится", + "backup.manager.restore.error": "Ошибка восстановления", + "backup.manager.delete.confirm.title": "Подтверждение удаления", + "backup.manager.delete.confirm.single": "Вы уверены, что хотите удалить резервную копию \"{{fileName}}\"? Это действие нельзя отменить.", + "backup.manager.delete.confirm.multiple": "Вы уверены, что хотите удалить {{count}} выбранных резервных копий? Это действие нельзя отменить.", + "backup.manager.delete.success.single": "Успешно удалено", + "backup.manager.delete.success.multiple": "Успешно удалено {{count}} резервных копий", + "backup.manager.delete.error": "Ошибка удаления", + "backup.manager.fetch.error": "Ошибка получения файлов резервных копий", + "backup.manager.select.files.delete": "Выберите файлы резервных копий для удаления", + "backup.manager.columns.fileName": "Имя файла", + "backup.manager.columns.modifiedTime": "Время изменения", + "backup.manager.columns.size": "Размер", + "backup.manager.columns.actions": "Действия", "host": "Хост WebDAV", "host.placeholder": "http://localhost:8080", "hour_interval_one": "{{count}} час", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 4071368e..c6d5eb2d 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -881,6 +881,25 @@ "backup.button": "备份到 WebDAV", "backup.modal.filename.placeholder": "请输入备份文件名", "backup.modal.title": "备份到 WebDAV", + "backup.manager.title": "备份数据管理", + "backup.manager.refresh": "刷新", + "backup.manager.delete.selected": "删除选中", + "backup.manager.delete.text": "删除", + "backup.manager.restore.text": "恢复", + "backup.manager.restore.success": "恢复成功,应用将在几秒后刷新", + "backup.manager.restore.error": "恢复失败", + "backup.manager.delete.confirm.title": "确认删除", + "backup.manager.delete.confirm.single": "确定要删除备份文件 \"{{fileName}}\" 吗?此操作不可恢复。", + "backup.manager.delete.confirm.multiple": "确定要删除选中的 {{count}} 个备份文件吗?此操作不可恢复。", + "backup.manager.delete.success.single": "删除成功", + "backup.manager.delete.success.multiple": "成功删除 {{count}} 个备份文件", + "backup.manager.delete.error": "删除失败", + "backup.manager.fetch.error": "获取备份文件失败", + "backup.manager.select.files.delete": "请选择要删除的备份文件", + "backup.manager.columns.fileName": "文件名", + "backup.manager.columns.modifiedTime": "修改时间", + "backup.manager.columns.size": "大小", + "backup.manager.columns.actions": "操作", "host": "WebDAV 地址", "host.placeholder": "http://localhost:8080", "hour_interval_one": "{{count}} 小时", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 0700d760..21e07e07 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -879,6 +879,25 @@ "backup.button": "備份到 WebDAV", "backup.modal.filename.placeholder": "請輸入備份文件名", "backup.modal.title": "備份到 WebDAV", + "backup.manager.title": "備份數據管理", + "backup.manager.refresh": "刷新", + "backup.manager.delete.selected": "刪除選中", + "backup.manager.delete.text": "刪除", + "backup.manager.restore.text": "恢復", + "backup.manager.restore.success": "恢復成功,應用將在幾秒後刷新", + "backup.manager.restore.error": "恢復失敗", + "backup.manager.delete.confirm.title": "確認刪除", + "backup.manager.delete.confirm.single": "確定要刪除備份文件 \"{{fileName}}\" 嗎?此操作不可恢復。", + "backup.manager.delete.confirm.multiple": "確定要刪除選中的 {{count}} 個備份文件嗎?此操作不可恢復。", + "backup.manager.delete.success.single": "刪除成功", + "backup.manager.delete.success.multiple": "成功刪除 {{count}} 個備份文件", + "backup.manager.delete.error": "刪除失敗", + "backup.manager.fetch.error": "獲取備份文件失敗", + "backup.manager.select.files.delete": "請選擇要刪除的備份文件", + "backup.manager.columns.fileName": "文件名", + "backup.manager.columns.modifiedTime": "修改時間", + "backup.manager.columns.size": "大小", + "backup.manager.columns.actions": "操作", "host": "WebDAV 主機位址", "host.placeholder": "http://localhost:8080", "hour_interval_one": "{{count}} 小時", diff --git a/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx b/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx index 72e41c3f..8ef34323 100644 --- a/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx @@ -1,12 +1,8 @@ import { CheckOutlined, FolderOutlined, LoadingOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons' import { HStack } from '@renderer/components/Layout' import NutstorePathPopup from '@renderer/components/Popups/NutsorePathPopup' -import { - useWebdavBackupModal, - useWebdavRestoreModal, - WebdavBackupModal, - WebdavRestoreModal -} from '@renderer/components/WebdavModals' +import { WebdavBackupManager } from '@renderer/components/WebdavBackupManager' +import { useWebdavBackupModal, WebdavBackupModal } from '@renderer/components/WebdavModals' import { useTheme } from '@renderer/context/ThemeProvider' import { useNutstoreSSO } from '@renderer/hooks/useNutstoreSSO' import { @@ -54,6 +50,8 @@ const NutstoreSettings: FC = () => { const nutstoreSSOHandler = useNutstoreSSO() + const [backupManagerVisible, setBackupManagerVisible] = useState(false) + const handleClickNutstoreSSO = useCallback(async () => { const ssoUrl = await window.api.nutstore.getSSOUrl() window.open(ssoUrl, '_blank') @@ -118,24 +116,6 @@ const NutstoreSettings: FC = () => { backupMethod: backupToNutstore }) - const { - isRestoreModalVisible, - handleRestore, - handleCancel: handleCancelRestore, - restoring, - selectedFile, - setSelectedFile, - loadingFiles, - backupFiles, - showRestoreModal - } = useWebdavRestoreModal({ - restoreMethod: restoreFromNutstore, - webdavHost: NUTSTORE_HOST, - webdavUser: nutstoreUsername, - webdavPass: nutstorePass, - webdavPath: storagePath - }) - const onSyncIntervalChange = (value: number) => { setSyncInterval(value) dispatch(setNutstoreSyncInterval(value)) @@ -205,6 +185,14 @@ const NutstoreSettings: FC = () => { const isLogin = nutstoreToken && nutstoreUsername + const showBackupManager = () => { + setBackupManagerVisible(true) + } + + const closeBackupManager = () => { + setBackupManagerVisible(false) + } + return ( {t('settings.data.nutstore.title')} @@ -269,7 +257,7 @@ const NutstoreSettings: FC = () => { - @@ -311,15 +299,16 @@ const NutstoreSettings: FC = () => { setCustomFileName={setCustomFileName} /> - diff --git a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx index a59389d7..795e5522 100644 --- a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx @@ -1,11 +1,7 @@ import { FolderOpenOutlined, SaveOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons' import { HStack } from '@renderer/components/Layout' -import { - useWebdavBackupModal, - useWebdavRestoreModal, - WebdavBackupModal, - WebdavRestoreModal -} from '@renderer/components/WebdavModals' +import { WebdavBackupManager } from '@renderer/components/WebdavBackupManager' +import { useWebdavBackupModal, WebdavBackupModal } from '@renderer/components/WebdavModals' import { useTheme } from '@renderer/context/ThemeProvider' import { useSettings } from '@renderer/hooks/useSettings' import { startAutoSync, stopAutoSync } from '@renderer/services/BackupService' @@ -38,6 +34,7 @@ const WebDavSettings: FC = () => { const [webdavUser, setWebdavUser] = useState(webDAVUser) const [webdavPass, setWebdavPass] = useState(webDAVPass) const [webdavPath, setWebdavPath] = useState(webDAVPath) + const [backupManagerVisible, setBackupManagerVisible] = useState(false) const [syncInterval, setSyncInterval] = useState(webDAVSyncInterval) @@ -89,17 +86,13 @@ const WebDavSettings: FC = () => { const { isModalVisible, handleBackup, handleCancel, backuping, customFileName, setCustomFileName, showBackupModal } = useWebdavBackupModal() - const { - isRestoreModalVisible, - handleRestore, - handleCancel: handleCancelRestore, - restoring, - selectedFile, - setSelectedFile, - loadingFiles, - backupFiles, - showRestoreModal - } = useWebdavRestoreModal({ webdavHost, webdavUser, webdavPass, webdavPath }) + const showBackupManager = () => { + setBackupManagerVisible(true) + } + + const closeBackupManager = () => { + setBackupManagerVisible(false) + } return ( @@ -156,7 +149,10 @@ const WebDavSettings: FC = () => { - @@ -196,15 +192,15 @@ const WebDavSettings: FC = () => { setCustomFileName={setCustomFileName} /> -