Files
bilin/src/main/ipc/handlers/book.handler.ts
T
bing fe127ec3ed feat: ship v1.2.0 Wave 1 foundation with book settings, chapter management, and focus mode
Deliver schema v9, book/chapter IPC extensions, BookSettingsTab, chapter meta/tags,
AI session menu, focus mode and TTS, template context enrich, and Wave 1 E2E coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-08 15:22:58 +08:00

61 lines
2.1 KiB
TypeScript

import { ipcMain, dialog, app } from 'electron'
import { copyFileSync, mkdirSync } from 'fs'
import { extname, join } from 'path'
import { IPC } from '../../../shared/ipc-channels'
import type { CreateBookParams, UpdateBookMetaParams } from '../../../shared/types'
import { BookRegistryService } from '../../services/book-registry'
import type { WritingSessionService } from '../../services/writing-session.service'
import { wrap } from '../result'
let previousBookId: string | null = null
export function registerBookHandlers(
registry: BookRegistryService,
writingSessions?: WritingSessionService
): void {
ipcMain.handle(IPC.BOOK_LIST, () => wrap(() => registry.list()))
ipcMain.handle(IPC.BOOK_CREATE, (_event, params: CreateBookParams) =>
wrap(() => registry.create(params))
)
ipcMain.handle(IPC.BOOK_DELETE, (_event, { bookId }: { bookId: string }) =>
wrap(() => {
registry.delete(bookId)
})
)
ipcMain.handle(IPC.BOOK_OPEN, (_event, { bookId }: { bookId: string }) =>
wrap(() => {
if (writingSessions && previousBookId && previousBookId !== bookId) {
writingSessions.endActive(previousBookId)
}
previousBookId = bookId
return registry.open(bookId)
})
)
ipcMain.handle(
IPC.BOOK_UPDATE_META,
(_event, { bookId, ...patch }: { bookId: string } & UpdateBookMetaParams) =>
wrap(() => registry.updateMeta(bookId, patch))
)
ipcMain.handle(IPC.BOOK_PICK_COVER, (_event, { bookId }: { bookId: string }) =>
wrap(async () => {
const { canceled, filePaths } = await dialog.showOpenDialog({
filters: [{ name: 'Images', extensions: ['jpg', 'jpeg', 'png', 'webp'] }],
properties: ['openFile']
})
if (canceled || !filePaths[0]) return null
const src = filePaths[0]
const ext = extname(src).toLowerCase() || '.jpg'
const coversDir = join(app.getPath('userData'), 'covers')
mkdirSync(coversDir, { recursive: true })
const dest = join(coversDir, `${bookId}${ext}`)
copyFileSync(src, dest)
return registry.updateMeta(bookId, { coverPath: dest })
})
)
}