feat: deliver P2 v0.2.0 with unified editor, search, and snapshots
Implement schema v2 migration, outline/setting/inspiration CRUD, unified TipTap editing, reference panel with mentions, FTS global search, chapter version history, writing landmarks, word frequency analysis, light theme contrast fixes, and full unit/E2E test coverage. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { ipcMain } from 'electron'
|
||||
import { IPC } from '../../../shared/ipc-channels'
|
||||
import type { OutlineStatus } from '../../../shared/types'
|
||||
import { BookRegistryService } from '../../services/book-registry'
|
||||
import { ftsSync } from '../../services/fts-sync.service'
|
||||
import { wrap } from '../result'
|
||||
|
||||
export function registerOutlineHandlers(registry: BookRegistryService): void {
|
||||
ipcMain.handle(IPC.OUTLINE_LIST, (_e, { bookId }: { bookId: string }) =>
|
||||
wrap(() => registry.getOutlineRepo(bookId).listFlat())
|
||||
)
|
||||
|
||||
ipcMain.handle(
|
||||
IPC.OUTLINE_CREATE,
|
||||
(
|
||||
_e,
|
||||
{
|
||||
bookId,
|
||||
parentId,
|
||||
title,
|
||||
sortOrder
|
||||
}: { bookId: string; parentId?: string | null; title: string; sortOrder?: number }
|
||||
) =>
|
||||
wrap(() => {
|
||||
const repo = registry.getOutlineRepo(bookId)
|
||||
const order = sortOrder ?? repo.nextSortOrder(parentId ?? null)
|
||||
const item = repo.create(parentId ?? null, title, order)
|
||||
const db = registry.getDb(bookId)
|
||||
ftsSync.upsert(db, 'outline', item.id, item.title, item.description)
|
||||
return item
|
||||
})
|
||||
)
|
||||
|
||||
ipcMain.handle(
|
||||
IPC.OUTLINE_UPDATE,
|
||||
(
|
||||
_e,
|
||||
{
|
||||
bookId,
|
||||
id,
|
||||
patch
|
||||
}: {
|
||||
bookId: string
|
||||
id: string
|
||||
patch: Partial<{
|
||||
title: string
|
||||
description: string
|
||||
status: OutlineStatus
|
||||
expectedWordCount: number | null
|
||||
chapterId: string | null
|
||||
sortOrder: number
|
||||
}>
|
||||
}
|
||||
) =>
|
||||
wrap(() => {
|
||||
const item = registry.getOutlineRepo(bookId).update(id, patch)
|
||||
const db = registry.getDb(bookId)
|
||||
ftsSync.upsert(db, 'outline', item.id, item.title, item.description)
|
||||
return item
|
||||
})
|
||||
)
|
||||
|
||||
ipcMain.handle(IPC.OUTLINE_DELETE, (_e, { bookId, id }: { bookId: string; id: string }) =>
|
||||
wrap(() => {
|
||||
registry.getOutlineRepo(bookId).delete(id)
|
||||
ftsSync.remove(registry.getDb(bookId), 'outline', id)
|
||||
})
|
||||
)
|
||||
|
||||
ipcMain.handle(
|
||||
IPC.OUTLINE_MOVE,
|
||||
(
|
||||
_e,
|
||||
{
|
||||
bookId,
|
||||
id,
|
||||
parentId,
|
||||
sortOrder
|
||||
}: { bookId: string; id: string; parentId?: string | null; sortOrder: number }
|
||||
) => wrap(() => registry.getOutlineRepo(bookId).move(id, parentId ?? null, sortOrder))
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user