a4412793f4
Introduce pack-bootstrap chunk, ZipArchive-based PackService with progress IPC, book registry import helpers, and IT-PACK-01 / IT-ALL-02 integration tests. Co-authored-by: Cursor <cursoragent@cursor.com>
82 lines
2.7 KiB
TypeScript
82 lines
2.7 KiB
TypeScript
import { dialog, ipcMain } from 'electron'
|
|
import { IPC } from '../../../shared/ipc-channels'
|
|
import type { PackImportStrategy } from '../../../shared/novel-pack'
|
|
import { PackService } from '../../services/pack.service'
|
|
import type { BookRegistryService } from '../../services/book-registry'
|
|
import type { GlobalSettingsService } from '../../services/global-settings'
|
|
import { wrap } from '../result'
|
|
|
|
let packService: PackService | null = null
|
|
|
|
function svc(registry: BookRegistryService, settings: GlobalSettingsService): PackService {
|
|
if (!packService) {
|
|
packService = new PackService(registry, settings, registry.getUserDataDir())
|
|
}
|
|
return packService
|
|
}
|
|
|
|
export function registerPackHandlers(
|
|
registry: BookRegistryService,
|
|
settings: GlobalSettingsService
|
|
): void {
|
|
const service = () => svc(registry, settings)
|
|
|
|
ipcMain.handle(
|
|
IPC.PACK_EXPORT_BOOK,
|
|
(_e, { bookId, destPath }: { bookId: string; destPath: string }) =>
|
|
wrap(() => service().exportBook(bookId, destPath))
|
|
)
|
|
|
|
ipcMain.handle(IPC.PACK_IMPORT_BOOK, (_e, { filePath }: { filePath: string }) =>
|
|
wrap(() => service().importBook(filePath))
|
|
)
|
|
|
|
ipcMain.handle(IPC.PACK_EXPORT_ALL, (_e, { destPath }: { destPath: string }) =>
|
|
wrap(() => service().exportAll(destPath))
|
|
)
|
|
|
|
ipcMain.handle(
|
|
IPC.PACK_IMPORT_ALL,
|
|
(_e, { filePath, strategy }: { filePath: string; strategy: PackImportStrategy }) =>
|
|
wrap(() => service().importAll(filePath, strategy))
|
|
)
|
|
|
|
ipcMain.handle(IPC.PACK_ESTIMATE_EXPORT_ALL, () =>
|
|
wrap(() => ({
|
|
bytes: service().estimateExportAllBytes(),
|
|
needsConfirm: service().needsExportAllConfirm()
|
|
}))
|
|
)
|
|
|
|
ipcMain.handle(IPC.PACK_NEEDS_CONFIRM, () =>
|
|
wrap(() => service().needsExportAllConfirm())
|
|
)
|
|
|
|
ipcMain.handle(IPC.PACK_CANCEL, () =>
|
|
wrap(() => {
|
|
service().cancel()
|
|
})
|
|
)
|
|
|
|
ipcMain.handle(IPC.PACK_PICK_FILE, (_e, { mode }: { mode: 'novel' | 'novel-all' | 'save-novel' | 'save-all' }) =>
|
|
wrap(async () => {
|
|
if (mode === 'save-novel' || mode === 'save-all') {
|
|
const ext = mode === 'save-all' ? 'novel-all' : 'novel'
|
|
const { canceled, filePath } = await dialog.showSaveDialog({
|
|
filters: [{ name: 'Bilin Pack', extensions: [ext] }],
|
|
defaultPath: mode === 'save-all' ? 'bilin-backup.novel-all' : 'book.novel'
|
|
})
|
|
if (canceled || !filePath) return null
|
|
return filePath
|
|
}
|
|
const extensions = mode === 'novel-all' ? ['novel-all'] : ['novel', 'novel-all']
|
|
const { canceled, filePaths } = await dialog.showOpenDialog({
|
|
properties: ['openFile'],
|
|
filters: [{ name: 'Bilin Pack', extensions }]
|
|
})
|
|
if (canceled || filePaths.length === 0) return null
|
|
return filePaths[0]
|
|
})
|
|
)
|
|
}
|