fix(LocalBackup): streamline local backup relative directory handling (#8595)

* fix(LocalBackup): streamline local backup directory handling

- Added a new state to manage the resolved local backup directory in LocalBackupSettings.
- Updated the LocalBackupManager component to use the resolved directory instead of the raw input.
- Enhanced the backupToLocal and restoreFromLocal functions to resolve the local backup directory path before use, improving reliability.

* refactor(Backup): remove setLocalBackupDir functionality

- Removed the setLocalBackupDir method and its associated IPC channel handling from the BackupManager and IpcChannel.
- Updated LocalBackupSettings to eliminate direct calls to setLocalBackupDir, instead resolving the local backup directory path directly.
- Cleaned up related code in the BackupService to streamline local backup operations.

* format code
This commit is contained in:
beyondkmp 2025-07-28 21:57:04 +08:00 committed by GitHub
parent 57065a1831
commit 18521c93b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 23 additions and 24 deletions

View File

@ -177,7 +177,6 @@ export enum IpcChannel {
Backup_RestoreFromLocalBackup = 'backup:restoreFromLocalBackup',
Backup_ListLocalBackupFiles = 'backup:listLocalBackupFiles',
Backup_DeleteLocalBackupFile = 'backup:deleteLocalBackupFile',
Backup_SetLocalBackupDir = 'backup:setLocalBackupDir',
Backup_BackupToS3 = 'backup:backupToS3',
Backup_RestoreFromS3 = 'backup:restoreFromS3',
Backup_ListS3Files = 'backup:listS3Files',

View File

@ -409,7 +409,6 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
ipcMain.handle(IpcChannel.Backup_RestoreFromLocalBackup, backupManager.restoreFromLocalBackup.bind(backupManager))
ipcMain.handle(IpcChannel.Backup_ListLocalBackupFiles, backupManager.listLocalBackupFiles.bind(backupManager))
ipcMain.handle(IpcChannel.Backup_DeleteLocalBackupFile, backupManager.deleteLocalBackupFile.bind(backupManager))
ipcMain.handle(IpcChannel.Backup_SetLocalBackupDir, backupManager.setLocalBackupDir.bind(backupManager))
ipcMain.handle(IpcChannel.Backup_BackupToS3, backupManager.backupToS3.bind(backupManager))
ipcMain.handle(IpcChannel.Backup_RestoreFromS3, backupManager.restoreFromS3.bind(backupManager))
ipcMain.handle(IpcChannel.Backup_ListS3Files, backupManager.listS3Files.bind(backupManager))

View File

@ -33,7 +33,6 @@ class BackupManager {
this.deleteLocalBackupFile = this.deleteLocalBackupFile.bind(this)
this.backupToLocalDir = this.backupToLocalDir.bind(this)
this.restoreFromLocalBackup = this.restoreFromLocalBackup.bind(this)
this.setLocalBackupDir = this.setLocalBackupDir.bind(this)
this.backupToS3 = this.backupToS3.bind(this)
this.restoreFromS3 = this.restoreFromS3.bind(this)
this.listS3Files = this.listS3Files.bind(this)
@ -599,17 +598,6 @@ class BackupManager {
}
}
async setLocalBackupDir(_: Electron.IpcMainInvokeEvent, dirPath: string) {
try {
// Check if directory exists
await fs.ensureDir(dirPath)
return true
} catch (error) {
logger.error('[BackupManager] Set local backup directory failed:', error as Error)
throw error
}
}
async restoreFromS3(_: Electron.IpcMainInvokeEvent, s3Config: S3Config) {
const filename = s3Config.fileName || 'cherry-studio.backup.zip'

View File

@ -120,7 +120,6 @@ const api = {
ipcRenderer.invoke(IpcChannel.Backup_ListLocalBackupFiles, localBackupDir),
deleteLocalBackupFile: (fileName: string, localBackupDir?: string) =>
ipcRenderer.invoke(IpcChannel.Backup_DeleteLocalBackupFile, fileName, localBackupDir),
setLocalBackupDir: (dirPath: string) => ipcRenderer.invoke(IpcChannel.Backup_SetLocalBackupDir, dirPath),
checkWebdavConnection: (webdavConfig: WebDavConfig) =>
ipcRenderer.invoke(IpcChannel.Backup_CheckConnection, webdavConfig),

View File

@ -31,7 +31,6 @@ export function LocalBackupManager({ visible, onClose, localBackupDir, restoreMe
pageSize: 5,
total: 0
})
const fetchBackupFiles = useCallback(async () => {
if (!localBackupDir) {
return

View File

@ -36,6 +36,7 @@ const LocalBackupSettings: React.FC = () => {
} = useSettings()
const [localBackupDir, setLocalBackupDir] = useState<string | undefined>(localBackupDirSetting)
const [resolvedLocalBackupDir, setResolvedLocalBackupDir] = useState<string | undefined>(undefined)
const [localBackupSkipBackupFile, setLocalBackupSkipBackupFile] = useState<boolean>(localBackupSkipBackupFileSetting)
const [backupManagerVisible, setBackupManagerVisible] = useState(false)
@ -48,6 +49,12 @@ const LocalBackupSettings: React.FC = () => {
window.api.getAppInfo().then(setAppInfo)
}, [])
useEffect(() => {
if (localBackupDirSetting) {
window.api.resolvePath(localBackupDirSetting).then(setResolvedLocalBackupDir)
}
}, [localBackupDirSetting])
const { theme } = useTheme()
const { t } = useTranslation()
@ -110,8 +117,7 @@ const LocalBackupSettings: React.FC = () => {
if (await checkLocalBackupDirValid(value)) {
setLocalBackupDir(value)
dispatch(_setLocalBackupDir(value))
// Create directory if it doesn't exist and set it in the backend
await window.api.backup.setLocalBackupDir(value)
setResolvedLocalBackupDir(await window.api.resolvePath(value))
dispatch(setLocalBackupAutoSync(true))
startAutoSync(true, 'local')
@ -183,7 +189,7 @@ const LocalBackupSettings: React.FC = () => {
}
const { isModalVisible, handleBackup, handleCancel, backuping, customFileName, setCustomFileName, showBackupModal } =
useLocalBackupModal(localBackupDir)
useLocalBackupModal(resolvedLocalBackupDir)
const showBackupManager = () => {
setBackupManagerVisible(true)
@ -298,7 +304,7 @@ const LocalBackupSettings: React.FC = () => {
<LocalBackupManager
visible={backupManagerVisible}
onClose={closeBackupManager}
localBackupDir={localBackupDir}
localBackupDir={resolvedLocalBackupDir}
/>
</>
</SettingGroup>

View File

@ -902,7 +902,11 @@ export async function backupToLocal({
showMessage = false,
customFileName = '',
autoBackupProcess = false
}: { showMessage?: boolean; customFileName?: string; autoBackupProcess?: boolean } = {}) {
}: {
showMessage?: boolean
customFileName?: string
autoBackupProcess?: boolean
} = {}) {
const notificationService = NotificationService.getInstance()
if (isManualBackupRunning) {
logger.verbose('Manual backup already in progress')
@ -917,7 +921,12 @@ export async function backupToLocal({
store.dispatch(setLocalBackupSyncState({ syncing: true, lastSyncError: null }))
const { localBackupDir, localBackupMaxBackups, localBackupSkipBackupFile } = store.getState().settings
const {
localBackupDir: localBackupDirSetting,
localBackupMaxBackups,
localBackupSkipBackupFile
} = store.getState().settings
const localBackupDir = await window.api.resolvePath(localBackupDirSetting)
let deviceType = 'unknown'
let hostname = 'unknown'
try {
@ -1039,9 +1048,9 @@ export async function backupToLocal({
}
export async function restoreFromLocal(fileName: string) {
const { localBackupDir } = store.getState().settings
try {
const { localBackupDir: localBackupDirSetting } = store.getState().settings
const localBackupDir = await window.api.resolvePath(localBackupDirSetting)
const restoreData = await window.api.backup.restoreFromLocalBackup(fileName, localBackupDir)
const data = JSON.parse(restoreData)
await handleData(data)