(ipcRenderer: IpcRendererLike, webFrame: WebFrameLike)
| 18 | } |
| 19 | |
| 20 | export function createElectronApi(ipcRenderer: IpcRendererLike, webFrame: WebFrameLike) { |
| 21 | return { |
| 22 | // Window controls |
| 23 | window: { |
| 24 | minimize: () => ipcRenderer.send('window:minimize'), |
| 25 | maximize: () => ipcRenderer.send('window:maximize'), |
| 26 | close: () => ipcRenderer.send('window:close'), |
| 27 | }, |
| 28 | |
| 29 | // Renderer UI (zoom whole page — scales every px/rem consistently) |
| 30 | ui: { setZoomFactor: (factor: number) => webFrame.setZoomFactor(factor) }, |
| 31 | |
| 32 | // Shell utilities |
| 33 | shell: { openExternal: (url: string) => ipcRenderer.invoke('shell:openExternal', url) }, |
| 34 | |
| 35 | // System info |
| 36 | system: { |
| 37 | memory: (): Promise<{ total: number; used: number; available: number }> => |
| 38 | ipcRenderer.invoke('system:memory') as Promise<{ total: number; used: number; available: number }>, |
| 39 | }, |
| 40 | |
| 41 | // Python / FastAPI bridge |
| 42 | python: { |
| 43 | start: (): Promise<{ success: boolean; port?: number; error?: string }> => |
| 44 | ipcRenderer.invoke('python:start') as Promise<{ success: boolean; port?: number; error?: string }>, |
| 45 | status: (): Promise<{ ready: boolean; apiUrl: string }> => |
| 46 | ipcRenderer.invoke('python:status') as Promise<{ ready: boolean; apiUrl: string }>, |
| 47 | onCrashed: (cb: (data: { code: number | null }) => void) => { |
| 48 | ipcRenderer.on('python:crashed', (_event, data) => cb(data as { code: number | null })) |
| 49 | }, |
| 50 | offCrashed: () => ipcRenderer.removeAllListeners('python:crashed'), |
| 51 | onLog: (cb: (line: string) => void) => { |
| 52 | ipcRenderer.on('python:log', (_event, line) => cb(line as string)) |
| 53 | }, |
| 54 | offLog: () => ipcRenderer.removeAllListeners('python:log'), |
| 55 | }, |
| 56 | |
| 57 | // File system dialogs + local file reading |
| 58 | fs: { |
| 59 | selectImage: (): Promise<string | null> => |
| 60 | ipcRenderer.invoke('fs:selectImage') as Promise<string | null>, |
| 61 | selectMeshFile: (): Promise<string | null> => |
| 62 | ipcRenderer.invoke('fs:selectMeshFile') as Promise<string | null>, |
| 63 | saveModel: (defaultName: string): Promise<string | null> => |
| 64 | ipcRenderer.invoke('fs:saveModel', defaultName) as Promise<string | null>, |
| 65 | readFileBase64: (filePath: string): Promise<string> => |
| 66 | ipcRenderer.invoke('fs:readFileBase64', filePath) as Promise<string>, |
| 67 | selectDirectory: (defaultPath?: string): Promise<string | null> => |
| 68 | ipcRenderer.invoke('fs:selectDirectory', defaultPath) as Promise<string | null>, |
| 69 | savePath: (args: { filters: { name: string; extensions: string[] }[]; defaultPath?: string }): Promise<string | null> => |
| 70 | ipcRenderer.invoke('fs:savePath', args) as Promise<string | null>, |
| 71 | listDir: (dirPath: string): Promise<string[]> => |
| 72 | ipcRenderer.invoke('fs:listDir', dirPath) as Promise<string[]>, |
| 73 | moveDirectory: (args: { src: string; dest: string }): Promise<{ success: boolean; error?: string }> => |
| 74 | ipcRenderer.invoke('fs:moveDirectory', args) as Promise<{ success: boolean; error?: string }>, |
| 75 | deleteDirectory: (dirPath: string): Promise<{ success: boolean; error?: string }> => |
| 76 | ipcRenderer.invoke('fs:deleteDirectory', dirPath) as Promise<{ success: boolean; error?: string }>, |
| 77 | readScreenshotDataUrl: (filename: string): Promise<string> => |
no test coverage detected