feat(#9): export/import состояния — backup в JSON и восстановление
This commit is contained in:
@@ -4,8 +4,10 @@ import {
|
||||
systemPreferences,
|
||||
BrowserWindow,
|
||||
app,
|
||||
dialog,
|
||||
shell
|
||||
} from 'electron'
|
||||
import { readFileSync, writeFileSync } from 'node:fs'
|
||||
import { IPC } from '@shared/ipc'
|
||||
import type { Exercise, GameId, Settings } from '@shared/types'
|
||||
import {
|
||||
@@ -14,9 +16,11 @@ import {
|
||||
clearHistory,
|
||||
deleteChallenge,
|
||||
deleteExercise,
|
||||
exportState,
|
||||
getHistory,
|
||||
getState,
|
||||
getStateForRenderer,
|
||||
importState,
|
||||
markDone,
|
||||
setGameEnabled,
|
||||
skip,
|
||||
@@ -304,4 +308,47 @@ export function registerIpc(): void {
|
||||
ipcMain.handle(IPC.clearHistory, (_e, beforeTs?: number) =>
|
||||
clearHistory(beforeTs)
|
||||
)
|
||||
|
||||
// Export / Import. Используем native save/open dialogs Electron'а —
|
||||
// renderer не получает прямого доступа к ФС.
|
||||
ipcMain.handle(IPC.exportState, async (event) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender) ?? undefined
|
||||
const stamp = new Date()
|
||||
.toISOString()
|
||||
.replace(/[:T]/g, '-')
|
||||
.slice(0, 16)
|
||||
const defaultPath = `laude-backup-${stamp}.json`
|
||||
const result = await dialog.showSaveDialog(win!, {
|
||||
title: 'Сохранить резервную копию',
|
||||
defaultPath,
|
||||
filters: [{ name: 'JSON', extensions: ['json'] }]
|
||||
})
|
||||
if (result.canceled || !result.filePath) return { ok: false, path: null }
|
||||
try {
|
||||
writeFileSync(result.filePath, exportState(), 'utf-8')
|
||||
return { ok: true, path: result.filePath }
|
||||
} catch (e) {
|
||||
return { ok: false, path: null, error: String(e) }
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle(IPC.importState, async (event) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender) ?? undefined
|
||||
const result = await dialog.showOpenDialog(win!, {
|
||||
title: 'Восстановить из резервной копии',
|
||||
properties: ['openFile'],
|
||||
filters: [{ name: 'JSON', extensions: ['json'] }]
|
||||
})
|
||||
if (result.canceled || result.filePaths.length === 0) {
|
||||
return { ok: false }
|
||||
}
|
||||
try {
|
||||
const raw = readFileSync(result.filePaths[0], 'utf-8')
|
||||
const ok = importState(raw)
|
||||
if (ok) broadcastState()
|
||||
return { ok }
|
||||
} catch (e) {
|
||||
return { ok: false, error: String(e) }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user