feat: 实现笔临 P0/P1 Electron 桌面应用 v0.1.0
交付写作核心(TipTap、自动保存、分卷分章)、Onboarding、7 主题与双语 i18n、快捷键设置;主进程使用 node:sqlite;补全 Vitest 与 Playwright E2E;统一 design/ 目录并移除 desigin 拼写错误路径。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron'
|
||||
import { IPC } from '../shared/ipc-channels'
|
||||
import type {
|
||||
ActionId,
|
||||
BookMeta,
|
||||
BookOpenResult,
|
||||
Chapter,
|
||||
CreateBookParams,
|
||||
GlobalSettings,
|
||||
IpcResult,
|
||||
UpdateChapterParams,
|
||||
Volume
|
||||
} from '../shared/types'
|
||||
|
||||
const electronAPI = {
|
||||
window: {
|
||||
minimize: (): Promise<void> => ipcRenderer.invoke(IPC.WINDOW_MINIMIZE),
|
||||
maximize: (): Promise<void> => ipcRenderer.invoke(IPC.WINDOW_MAXIMIZE),
|
||||
close: (): Promise<void> => ipcRenderer.invoke(IPC.WINDOW_CLOSE)
|
||||
},
|
||||
settings: {
|
||||
get: (): Promise<IpcResult<GlobalSettings>> => ipcRenderer.invoke(IPC.SETTINGS_GET),
|
||||
update: (partial: Partial<GlobalSettings>): Promise<IpcResult<GlobalSettings>> =>
|
||||
ipcRenderer.invoke(IPC.SETTINGS_UPDATE, partial)
|
||||
},
|
||||
book: {
|
||||
list: (): Promise<IpcResult<BookMeta[]>> => ipcRenderer.invoke(IPC.BOOK_LIST),
|
||||
create: (params: CreateBookParams): Promise<IpcResult<BookMeta>> =>
|
||||
ipcRenderer.invoke(IPC.BOOK_CREATE, params),
|
||||
delete: (bookId: string): Promise<IpcResult<void>> =>
|
||||
ipcRenderer.invoke(IPC.BOOK_DELETE, { bookId }),
|
||||
open: (bookId: string): Promise<IpcResult<BookOpenResult>> =>
|
||||
ipcRenderer.invoke(IPC.BOOK_OPEN, { bookId }),
|
||||
updateMeta: (
|
||||
bookId: string,
|
||||
patch: { lastChapterId?: string | null; status?: BookMeta['status'] }
|
||||
): Promise<IpcResult<BookMeta>> => ipcRenderer.invoke(IPC.BOOK_UPDATE_META, { bookId, ...patch })
|
||||
},
|
||||
volume: {
|
||||
create: (bookId: string, name: string): Promise<IpcResult<Volume>> =>
|
||||
ipcRenderer.invoke(IPC.VOLUME_CREATE, { bookId, name }),
|
||||
update: (
|
||||
bookId: string,
|
||||
volumeId: string,
|
||||
patch: { name?: string; description?: string }
|
||||
): Promise<IpcResult<Volume>> =>
|
||||
ipcRenderer.invoke(IPC.VOLUME_UPDATE, { bookId, volumeId, ...patch }),
|
||||
delete: (bookId: string, volumeId: string): Promise<IpcResult<void>> =>
|
||||
ipcRenderer.invoke(IPC.VOLUME_DELETE, { bookId, volumeId })
|
||||
},
|
||||
chapter: {
|
||||
create: (bookId: string, volumeId: string, title: string): Promise<IpcResult<Chapter>> =>
|
||||
ipcRenderer.invoke(IPC.CHAPTER_CREATE, { bookId, volumeId, title }),
|
||||
get: (bookId: string, chapterId: string): Promise<IpcResult<Chapter>> =>
|
||||
ipcRenderer.invoke(IPC.CHAPTER_GET, { bookId, chapterId }),
|
||||
update: (params: UpdateChapterParams): Promise<IpcResult<Chapter>> =>
|
||||
ipcRenderer.invoke(IPC.CHAPTER_UPDATE, params),
|
||||
delete: (bookId: string, chapterId: string): Promise<IpcResult<void>> =>
|
||||
ipcRenderer.invoke(IPC.CHAPTER_DELETE, { bookId, chapterId })
|
||||
},
|
||||
shortcut: {
|
||||
getAll: (): Promise<IpcResult<Record<ActionId, string>>> =>
|
||||
ipcRenderer.invoke(IPC.SHORTCUT_GET_ALL),
|
||||
register: (action: ActionId, accelerator: string): Promise<IpcResult<void>> =>
|
||||
ipcRenderer.invoke(IPC.SHORTCUT_REGISTER, { action, accelerator })
|
||||
},
|
||||
onShortcutTriggered: (callback: (action: ActionId) => void): (() => void) => {
|
||||
const handler = (_event: IpcRendererEvent, payload: { action: ActionId }) => {
|
||||
callback(payload.action)
|
||||
}
|
||||
ipcRenderer.on(IPC.SHORTCUT_TRIGGERED, handler)
|
||||
return () => ipcRenderer.removeListener(IPC.SHORTCUT_TRIGGERED, handler)
|
||||
}
|
||||
}
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', electronAPI)
|
||||
|
||||
export type ElectronAPI = typeof electronAPI
|
||||
Reference in New Issue
Block a user