Skip to content

Commit 78603a2

Browse files
committed
refactor(backup): enhance backup functionality with direct backup and legacy backup support (#13030)
### What this PR does This PR introduces several enhancements to the backup functionality: 1. **Direct Backup**: Implements efficient backup methods that copy IndexedDB and Local Storage directories directly, avoiding JSON serialization for better performance 2. **Legacy Backup Rename**: Renames "LAN Transfer Backup" to "Legacy Backup" for clearer terminology 3. **Component Refactoring**: Splits the large DataSettings.tsx into smaller components 4. **New Icons**: Adds Joplin and Siyuan icon components ### Before this PR: - Backup only supported JSON-based serialization - "LAN Transfer Backup" terminology was used - All data settings were in a single large component ### After this PR: - Supports both direct (file copy) and JSON backup formats - Uses "Legacy Backup" terminology for the former LAN Transfer feature - Data settings are modularized with separate components ### Why we need it and why was done in this way The tradeoffs were made: - Direct backup is faster but may not work across different app versions - Legacy backup (JSON-based) ensures compatibility but is slower ### Breaking changes None. ### Special notes for your reviewer - The DataSettings.tsx was refactored into multiple files - please review the component structure - Direct backup format includes metadata for version compatibility - **Testing status**: macOS backup and restore tested. Windows and Linux testing pending. ### Checklist - [x] PR: Expressive enough for future contributors - [x] Code: Simple and human-readable - [x] Refactor: Code is cleaner than before - [x] Upgrade: Impact considered - [x] Documentation: Not required for this backend/feature change ### Release note ```release-note - Add direct backup mode, significantly improving backup and restore speed ```
1 parent 8dd42eb commit 78603a2

File tree

29 files changed

+1815
-1156
lines changed

29 files changed

+1815
-1156
lines changed

packages/shared/IpcChannel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ export enum IpcChannel {
246246
Backup_DeleteS3File = 'backup:deleteS3File',
247247
Backup_CheckS3Connection = 'backup:checkS3Connection',
248248
Backup_CreateLanTransferBackup = 'backup:createLanTransferBackup',
249-
Backup_DeleteTempBackup = 'backup:deleteTempBackup',
249+
Backup_DeleteLanTransferBackup = 'backup:deleteLanTransferBackup',
250250

251251
// zip
252252
Zip_Compress = 'zip:compress',

src/main/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,12 @@ if (!app.requestSingleInstanceLock()) {
149149
app.dock?.hide()
150150
}
151151

152+
// Check for backup restore marker and complete restoration (highest priority, before window creation)
153+
const { BackupManager } = await import('./services/BackupManager')
154+
await BackupManager.handleStartupRestore()
155+
152156
const mainWindow = windowService.createMainWindow()
157+
153158
new TrayService()
154159

155160
// Setup macOS application menu

src/main/ipc.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ import { themeService } from './services/ThemeService'
9292
import VertexAIService from './services/VertexAIService'
9393
import { setOpenLinkExternal } from './services/WebviewService'
9494
import { windowService } from './services/WindowService'
95-
import { calculateDirectorySize, getDataPath, getResourcePath } from './utils'
95+
import { calculateDirectorySize, getResourcePath } from './utils'
9696
import { decrypt, encrypt } from './utils/aes'
9797
import {
9898
getCacheDir,
@@ -104,7 +104,6 @@ import {
104104
untildify
105105
} from './utils/file'
106106
import { updateAppDataConfig } from './utils/init'
107-
import { closeAllDataConnections } from './utils/lifecycle'
108107
import { getCpuName, getDeviceType, getHostname } from './utils/system'
109108
import { compress, decompress } from './utils/zip'
110109

@@ -495,15 +494,7 @@ export async function registerIpc(mainWindow: BrowserWindow, app: Electron.App)
495494
})
496495

497496
// Reset all data (factory reset)
498-
// Best-effort: close handles then delete. Failures are logged but not thrown,
499-
// because the caller must always proceed to relaunchApp() — process exit
500-
// releases any remaining handles, and services auto-recreate on next start.
501-
ipcMain.handle(IpcChannel.App_ResetData, async () => {
502-
await closeAllDataConnections()
503-
await fs.promises.rm(getDataPath(), { recursive: true, force: true }).catch((e) => {
504-
logger.warn('Failed to remove Data directory (will be cleaned up on restart)', e as Error)
505-
})
506-
})
497+
ipcMain.handle(IpcChannel.App_ResetData, () => backupManager.resetData())
507498

508499
// check for update
509500
ipcMain.handle(IpcChannel.App_CheckForUpdate, async () => {
@@ -610,7 +601,7 @@ export async function registerIpc(mainWindow: BrowserWindow, app: Electron.App)
610601
ipcMain.handle(IpcChannel.Backup_DeleteS3File, backupManager.deleteS3File.bind(backupManager))
611602
ipcMain.handle(IpcChannel.Backup_CheckS3Connection, backupManager.checkS3Connection.bind(backupManager))
612603
ipcMain.handle(IpcChannel.Backup_CreateLanTransferBackup, backupManager.createLanTransferBackup.bind(backupManager))
613-
ipcMain.handle(IpcChannel.Backup_DeleteTempBackup, backupManager.deleteTempBackup.bind(backupManager))
604+
ipcMain.handle(IpcChannel.Backup_DeleteLanTransferBackup, backupManager.deleteLanTransferBackup.bind(backupManager))
614605

615606
// file
616607
ipcMain.handle(IpcChannel.File_Open, fileManager.open.bind(fileManager))

0 commit comments

Comments
 (0)