feat(desktop): move dictionary entries in and out as files
Users could only rebuild their spoken-word dictionary entry by entry. Import and export now round-trip the whole list, reporting duplicate and invalid entries per row instead of failing the batch, so a dictionary survives a reinstall or a move to another machine.
This commit is contained in:
parent
7953706142
commit
911c9f0229
5 changed files with 625 additions and 15 deletions
|
|
@ -1,6 +1,6 @@
|
|||
// src/main/ipc/dictionary-handlers.ts
|
||||
|
||||
import { ipcMain } from 'electron'
|
||||
import { ipcMain, dialog } from 'electron'
|
||||
import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
|
||||
import { ipcSuccess, ipcError, ErrorCode, D3ROError } from '@d3ro/core/errors'
|
||||
import { getDictionaryService } from '../services/DictionaryService'
|
||||
|
|
@ -9,7 +9,9 @@ import type {
|
|||
DictionaryAddParams,
|
||||
DictionaryUpdateParams,
|
||||
DictionaryDeleteParams,
|
||||
DictionarySearchParams
|
||||
DictionarySearchParams,
|
||||
DictionaryImportParams,
|
||||
DictionaryExportParams
|
||||
} from '@d3ro/core/types'
|
||||
|
||||
export function registerDictionaryHandlers(): void {
|
||||
|
|
@ -74,4 +76,43 @@ export function registerDictionaryHandlers(): void {
|
|||
return ipcError(ErrorCode.DBQueryFailed, `Failed to search dictionary: ${message}`)
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle(IPC_CHANNELS.DICTIONARY.IMPORT, async (_event, params: DictionaryImportParams) => {
|
||||
try {
|
||||
let filePath = params.filePath
|
||||
if (!filePath) {
|
||||
const picked = await dialog.showOpenDialog({
|
||||
properties: ['openFile'],
|
||||
filters: [
|
||||
params.format === 'csv'
|
||||
? { name: 'CSV', extensions: ['csv'] }
|
||||
: { name: 'JSON', extensions: ['json'] }
|
||||
]
|
||||
})
|
||||
if (picked.canceled || picked.filePaths.length === 0) {
|
||||
return ipcSuccess({ imported: 0, skipped: 0, errors: 0 })
|
||||
}
|
||||
filePath = picked.filePaths[0]
|
||||
}
|
||||
return ipcSuccess(getDictionaryService().importDictionary({ ...params, filePath }))
|
||||
} catch (error) {
|
||||
if (error instanceof D3ROError) {
|
||||
return ipcError(error.code, error.message)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
return ipcError(ErrorCode.DictionaryImportFailed, `Failed to import dictionary: ${message}`)
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle(IPC_CHANNELS.DICTIONARY.EXPORT, async (_event, params: DictionaryExportParams) => {
|
||||
try {
|
||||
return ipcSuccess(await getDictionaryService().exportDictionary(params))
|
||||
} catch (error) {
|
||||
if (error instanceof D3ROError) {
|
||||
return ipcError(error.code, error.message)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
return ipcError(ErrorCode.DictionaryExportFailed, `Failed to export dictionary: ${message}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue