openpencil/electron/preload.ts
Kayshen Xu 2b35c86618
V0.3.2 (#28)
* feat(electron): update electron-builder.yml to specify artifact naming convention for Windows builds. This change enhances clarity and consistency in the build output.

* feat(electron): implement a file logger for the main process

- Added a new logger module that writes logs to `{userData}/logs/main.log` with daily rotation and retains logs for the last 7 days.
- Integrated logging functionality into the main process, replacing console error messages with log entries for better error tracking and debugging.
- Introduced IPC handlers to retrieve the log directory path for user access.
- Updated the preload and main files to utilize the new logging system, enhancing overall application reliability and maintainability.

* feat(mcp): introduce layered design workflow and selection management

- Added a new layered design workflow with tools: `design_skeleton`, `design_content`, and `design_refine` for improved multi-section design generation.
- Implemented segmented prompt retrieval in `get_design_prompt` to allow focused access to design knowledge.
- Created new API endpoints for managing canvas selection state with `selection.get` and `selection.post`, enabling real-time updates and synchronization.
- Enhanced document management with live selection fetching and improved node operations for better design content handling.
- Updated README and CLAUDE.md to reflect new features and usage guidelines for the layered design process.
2026-03-10 21:55:47 +08:00

113 lines
3.7 KiB
TypeScript

import { contextBridge, ipcRenderer, type IpcRendererEvent } from 'electron'
export type UpdaterStatus =
| 'disabled'
| 'idle'
| 'checking'
| 'available'
| 'downloading'
| 'downloaded'
| 'not-available'
| 'error'
export interface UpdaterState {
status: UpdaterStatus
currentVersion: string
latestVersion?: string
downloadProgress?: number
releaseDate?: string
error?: string
}
export interface ElectronAPI {
isElectron: true
openFile: () => Promise<{ filePath: string; content: string } | null>
saveFile: (
content: string,
defaultPath?: string,
) => Promise<string | null>
saveToPath: (filePath: string, content: string) => Promise<string>
onMenuAction: (callback: (action: string) => void) => () => void
onOpenFile: (callback: (filePath: string) => void) => () => void
readFile: (filePath: string) => Promise<{ filePath: string; content: string } | null>
getPendingFile: () => Promise<string | null>
getLogDir: () => Promise<string>
setTheme: (theme: 'dark' | 'light', colors?: { bg: string; fg: string }) => void
getPreferences: () => Promise<Record<string, string>>
setPreference: (key: string, value: string) => Promise<void>
removePreference: (key: string) => Promise<void>
updater: {
getState: () => Promise<UpdaterState>
checkForUpdates: () => Promise<UpdaterState>
quitAndInstall: () => Promise<boolean>
getAutoCheck: () => Promise<boolean>
setAutoCheck: (enabled: boolean) => Promise<boolean>
onStateChange: (callback: (state: UpdaterState) => void) => () => void
}
}
const api: ElectronAPI = {
isElectron: true,
openFile: () => ipcRenderer.invoke('dialog:openFile'),
saveFile: (content: string, defaultPath?: string) =>
ipcRenderer.invoke('dialog:saveFile', { content, defaultPath }),
saveToPath: (filePath: string, content: string) =>
ipcRenderer.invoke('dialog:saveToPath', { filePath, content }),
setTheme: (theme: 'dark' | 'light', colors?: { bg: string; fg: string }) =>
ipcRenderer.invoke('theme:set', theme, colors),
getPreferences: () => ipcRenderer.invoke('prefs:getAll'),
setPreference: (key: string, value: string) => ipcRenderer.invoke('prefs:set', key, value),
removePreference: (key: string) => ipcRenderer.invoke('prefs:remove', key),
onMenuAction: (callback: (action: string) => void) => {
const listener = (_event: IpcRendererEvent, action: string) => {
callback(action)
}
ipcRenderer.on('menu:action', listener)
return () => {
ipcRenderer.removeListener('menu:action', listener)
}
},
onOpenFile: (callback: (filePath: string) => void) => {
const listener = (_event: IpcRendererEvent, filePath: string) => {
callback(filePath)
}
ipcRenderer.on('file:open', listener)
return () => {
ipcRenderer.removeListener('file:open', listener)
}
},
readFile: (filePath: string) => ipcRenderer.invoke('file:read', filePath),
getPendingFile: () => ipcRenderer.invoke('file:getPending'),
getLogDir: () => ipcRenderer.invoke('log:getDir'),
updater: {
getState: () => ipcRenderer.invoke('updater:getState'),
checkForUpdates: () => ipcRenderer.invoke('updater:checkForUpdates'),
quitAndInstall: () => ipcRenderer.invoke('updater:quitAndInstall'),
getAutoCheck: () => ipcRenderer.invoke('updater:getAutoCheck'),
setAutoCheck: (enabled: boolean) => ipcRenderer.invoke('updater:setAutoCheck', enabled),
onStateChange: (callback: (state: UpdaterState) => void) => {
const listener = (_event: IpcRendererEvent, state: UpdaterState) => {
callback(state)
}
ipcRenderer.on('updater:state', listener)
return () => {
ipcRenderer.removeListener('updater:state', listener)
}
},
},
}
contextBridge.exposeInMainWorld('electronAPI', api)