From c38a6cdfbfdb1b87424e449804ca45de72cebf7a Mon Sep 17 00:00:00 2001 From: Doekin <105162544+Doekin@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:25:08 +0800 Subject: [PATCH] feat(restoreFromWebdav): make credentials and path optional (#6922) * feat(BackupService): add feedback messages for backup operations * feat(WebDAV): Allow optional username, password, and path for unauthenticated access --- src/main/services/WebDav.ts | 11 ++++++----- .../src/components/WebdavBackupManager.tsx | 14 +++++++------- src/renderer/src/components/WebdavModals.tsx | 6 +++--- .../pages/settings/DataSettings/WebDavSettings.tsx | 5 +---- src/renderer/src/services/BackupService.ts | 2 ++ src/renderer/src/types/index.ts | 6 +++--- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main/services/WebDav.ts b/src/main/services/WebDav.ts index ad1a127b3a..fae0e2da38 100644 --- a/src/main/services/WebDav.ts +++ b/src/main/services/WebDav.ts @@ -1,7 +1,8 @@ import { WebDavConfig } from '@types' import Logger from 'electron-log' -import Stream from 'stream' import https from 'https' +import path from 'path' +import Stream from 'stream' import { BufferLike, createClient, @@ -15,7 +16,7 @@ export default class WebDav { private webdavPath: string constructor(params: WebDavConfig) { - this.webdavPath = params.webdavPath + this.webdavPath = params.webdavPath || '/' this.instance = createClient(params.webdavHost, { username: params.webdavUser, @@ -51,7 +52,7 @@ export default class WebDav { throw error } - const remoteFilePath = `${this.webdavPath}/${filename}` + const remoteFilePath = path.posix.join(this.webdavPath, filename) try { return await this.instance.putFileContents(remoteFilePath, data, options) @@ -66,7 +67,7 @@ export default class WebDav { throw new Error('WebDAV client not initialized') } - const remoteFilePath = `${this.webdavPath}/${filename}` + const remoteFilePath = path.posix.join(this.webdavPath, filename) try { return await this.instance.getFileContents(remoteFilePath, options) @@ -120,7 +121,7 @@ export default class WebDav { throw new Error('WebDAV client not initialized') } - const remoteFilePath = `${this.webdavPath}/${filename}` + const remoteFilePath = path.posix.join(this.webdavPath, filename) try { return await this.instance.deleteFile(remoteFilePath) diff --git a/src/renderer/src/components/WebdavBackupManager.tsx b/src/renderer/src/components/WebdavBackupManager.tsx index 1c589736b4..a434e3c63d 100644 --- a/src/renderer/src/components/WebdavBackupManager.tsx +++ b/src/renderer/src/components/WebdavBackupManager.tsx @@ -14,9 +14,9 @@ interface BackupFile { interface WebdavConfig { webdavHost: string - webdavUser: string - webdavPass: string - webdavPath: string + webdavUser?: string + webdavPass?: string + webdavPath?: string } interface WebdavBackupManagerProps { @@ -47,7 +47,7 @@ export function WebdavBackupManager({ visible, onClose, webdavConfig, restoreMet const { webdavHost, webdavUser, webdavPass, webdavPath } = webdavConfig const fetchBackupFiles = useCallback(async () => { - if (!webdavHost || !webdavUser || !webdavPass || !webdavPath) { + if (!webdavHost) { message.error(t('message.error.invalid.webdav')) return } @@ -93,7 +93,7 @@ export function WebdavBackupManager({ visible, onClose, webdavConfig, restoreMet return } - if (!webdavHost || !webdavUser || !webdavPass || !webdavPath) { + if (!webdavHost) { message.error(t('message.error.invalid.webdav')) return } @@ -132,7 +132,7 @@ export function WebdavBackupManager({ visible, onClose, webdavConfig, restoreMet } const handleDeleteSingle = async (fileName: string) => { - if (!webdavHost || !webdavUser || !webdavPass || !webdavPath) { + if (!webdavHost) { message.error(t('message.error.invalid.webdav')) return } @@ -165,7 +165,7 @@ export function WebdavBackupManager({ visible, onClose, webdavConfig, restoreMet } const handleRestore = async (fileName: string) => { - if (!webdavHost || !webdavUser || !webdavPass || !webdavPath) { + if (!webdavHost) { message.error(t('message.error.invalid.webdav')) return } diff --git a/src/renderer/src/components/WebdavModals.tsx b/src/renderer/src/components/WebdavModals.tsx index 2dc8f1d3b6..a96c96fde8 100644 --- a/src/renderer/src/components/WebdavModals.tsx +++ b/src/renderer/src/components/WebdavModals.tsx @@ -123,7 +123,7 @@ export function useWebdavRestoreModal({ const [backupFiles, setBackupFiles] = useState([]) const showRestoreModal = useCallback(async () => { - if (!webdavHost || !webdavUser || !webdavPass || !webdavPath) { + if (!webdavHost) { window.message.error({ content: t('message.error.invalid.webdav'), key: 'webdav-error' }) return } @@ -146,7 +146,7 @@ export function useWebdavRestoreModal({ }, [webdavHost, webdavUser, webdavPass, webdavPath, t]) const handleRestore = useCallback(async () => { - if (!selectedFile || !webdavHost || !webdavUser || !webdavPass || !webdavPath) { + if (!selectedFile || !webdavHost) { window.message.error({ content: !selectedFile ? t('message.error.no.file.selected') : t('message.error.invalid.webdav'), key: 'restore-error' @@ -170,7 +170,7 @@ export function useWebdavRestoreModal({ } } }) - }, [selectedFile, webdavHost, webdavUser, webdavPass, webdavPath, t, restoreMethod]) + }, [selectedFile, webdavHost, t, restoreMethod]) const handleCancel = () => { setIsRestoreModalVisible(false) diff --git a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx index 104fa5cbd8..8e2a7e5aa2 100644 --- a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx @@ -165,10 +165,7 @@ const WebDavSettings: FC = () => { - diff --git a/src/renderer/src/services/BackupService.ts b/src/renderer/src/services/BackupService.ts index 3f1c3f85fe..3d78b2752a 100644 --- a/src/renderer/src/services/BackupService.ts +++ b/src/renderer/src/services/BackupService.ts @@ -137,6 +137,7 @@ export async function backupToWebdav({ timestamp: Date.now(), source: 'backup' }) + showMessage && window.message.success({ content: i18n.t('message.backup.success'), key: 'backup' }) // 清理旧备份文件 if (webdavMaxBackups > 0) { @@ -202,6 +203,7 @@ export async function backupToWebdav({ source: 'backup' }) store.dispatch(setWebDAVSyncState({ lastSyncError: error.message })) + showMessage && window.message.error({ content: i18n.t('message.backup.failed'), key: 'backup' }) console.error('[Backup] backupToWebdav: Error uploading file to WebDAV:', error) throw error } finally { diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index 28ac924248..a57b599adc 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -347,9 +347,9 @@ export type CodeStyleVarious = 'auto' | string export type WebDavConfig = { webdavHost: string - webdavUser: string - webdavPass: string - webdavPath: string + webdavUser?: string + webdavPass?: string + webdavPath?: string fileName?: string skipBackupFile?: boolean }