summaryrefslogtreecommitdiff
path: root/src/preload
diff options
context:
space:
mode:
authorhaoyuren <13851610112@163.com>2026-03-11 18:16:45 -0500
committerhaoyuren <13851610112@163.com>2026-03-11 18:16:45 -0500
commitebec1a1073f9cc5b69e125d5b284669545ea3d9f (patch)
tree731ae664b9966b6fbd269c55be2ba5c01ee3341f /src/preload
Initial commit: ClaudeTeX - LaTeX editor with Overleaf sync
Features: - Electron + React + TypeScript app with Cosmic Latte theme - CodeMirror 6 editor with LaTeX syntax highlighting - PDF preview with pdf.js, zoom controls, SyncTeX double-click jump - File tree with context menu (new/rename/delete/reveal) - Overleaf Git clone with token auth + macOS Keychain storage - Git pull/push sync for Overleaf projects - Embedded terminal (xterm.js + node-pty) with Claude CLI integration - LaTeX compilation via latexmk with auto package install detection - Structured compile log (errors/warnings) with click-to-navigate - Main document setting (auto-detect or right-click to set) - Custom modal system (input/confirm/alert) - Resizable panel layout (file tree | editor | PDF + terminal) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'src/preload')
-rw-r--r--src/preload/index.d.ts7
-rw-r--r--src/preload/index.ts78
2 files changed, 85 insertions, 0 deletions
diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts
new file mode 100644
index 0000000..ccfa000
--- /dev/null
+++ b/src/preload/index.d.ts
@@ -0,0 +1,7 @@
+import type { ElectronAPI } from './index'
+
+declare global {
+ interface Window {
+ api: ElectronAPI
+ }
+}
diff --git a/src/preload/index.ts b/src/preload/index.ts
new file mode 100644
index 0000000..ab360c0
--- /dev/null
+++ b/src/preload/index.ts
@@ -0,0 +1,78 @@
+import { contextBridge, ipcRenderer } from 'electron'
+
+const api = {
+ // File system
+ openProject: () => ipcRenderer.invoke('dialog:openProject'),
+ selectSaveDir: () => ipcRenderer.invoke('dialog:selectSaveDir'),
+ readDir: (path: string) => ipcRenderer.invoke('fs:readDir', path),
+ readFile: (path: string) => ipcRenderer.invoke('fs:readFile', path),
+ findMainTex: (dir: string) => ipcRenderer.invoke('fs:findMainTex', dir) as Promise<string | null>,
+ readBinary: (path: string) => ipcRenderer.invoke('fs:readBinary', path) as Promise<ArrayBuffer>,
+ writeFile: (path: string, content: string) => ipcRenderer.invoke('fs:writeFile', path, content),
+ createFile: (dir: string, name: string) => ipcRenderer.invoke('fs:createFile', dir, name),
+ createDir: (dir: string, name: string) => ipcRenderer.invoke('fs:createDir', dir, name),
+ renameFile: (oldPath: string, newPath: string) => ipcRenderer.invoke('fs:rename', oldPath, newPath),
+ deleteFile: (path: string) => ipcRenderer.invoke('fs:delete', path),
+ fileStat: (path: string) => ipcRenderer.invoke('fs:stat', path),
+
+ // File watcher
+ watchStart: (path: string) => ipcRenderer.invoke('watcher:start', path),
+ watchStop: () => ipcRenderer.invoke('watcher:stop'),
+ onWatchChange: (cb: (data: { event: string; path: string }) => void) => {
+ const handler = (_e: Electron.IpcRendererEvent, data: { event: string; path: string }) => cb(data)
+ ipcRenderer.on('watcher:change', handler)
+ return () => ipcRenderer.removeListener('watcher:change', handler)
+ },
+
+ // LaTeX
+ compile: (path: string) => ipcRenderer.invoke('latex:compile', path),
+ getPdfPath: (texPath: string) => ipcRenderer.invoke('latex:getPdfPath', texPath),
+ onCompileLog: (cb: (log: string) => void) => {
+ const handler = (_e: Electron.IpcRendererEvent, log: string) => cb(log)
+ ipcRenderer.on('latex:log', handler)
+ return () => ipcRenderer.removeListener('latex:log', handler)
+ },
+
+ // Terminal
+ ptySpawn: (cwd: string) => ipcRenderer.invoke('pty:spawn', cwd),
+ ptyWrite: (data: string) => ipcRenderer.invoke('pty:write', data),
+ ptyResize: (cols: number, rows: number) => ipcRenderer.invoke('pty:resize', cols, rows),
+ ptyKill: () => ipcRenderer.invoke('pty:kill'),
+ onPtyData: (cb: (data: string) => void) => {
+ const handler = (_e: Electron.IpcRendererEvent, data: string) => cb(data)
+ ipcRenderer.on('pty:data', handler)
+ return () => ipcRenderer.removeListener('pty:data', handler)
+ },
+ onPtyExit: (cb: () => void) => {
+ const handler = () => cb()
+ ipcRenderer.on('pty:exit', handler)
+ return () => ipcRenderer.removeListener('pty:exit', handler)
+ },
+
+ // Overleaf
+ overleafCloneWithAuth: (projectId: string, dest: string, token: string, remember: boolean) =>
+ ipcRenderer.invoke('overleaf:cloneWithAuth', projectId, dest, token, remember) as Promise<{ success: boolean; message: string; detail: string }>,
+ overleafCheck: () => ipcRenderer.invoke('overleaf:check') as Promise<{ loggedIn: boolean; email: string }>,
+ overleafLogout: () => ipcRenderer.invoke('overleaf:logout'),
+ gitPull: (cwd: string) => ipcRenderer.invoke('git:pull', cwd),
+ gitPush: (cwd: string) => ipcRenderer.invoke('git:push', cwd),
+ gitStatus: (cwd: string) => ipcRenderer.invoke('git:status', cwd),
+
+ // SyncTeX
+ synctexEdit: (pdfPath: string, page: number, x: number, y: number) =>
+ ipcRenderer.invoke('synctex:editFromPdf', pdfPath, page, x, y) as Promise<{ file: string; line: number } | null>,
+ synctexView: (texPath: string, line: number, pdfPath: string) =>
+ ipcRenderer.invoke('synctex:viewFromSource', texPath, line, pdfPath) as Promise<{ page: number; x: number; y: number } | null>,
+
+ // LaTeX package management
+ installTexPackages: (packages: string[]) =>
+ ipcRenderer.invoke('latex:installPackages', packages) as Promise<{ success: boolean; message: string; packages?: string[] }>,
+
+ // Shell
+ openExternal: (url: string) => ipcRenderer.invoke('shell:openExternal', url),
+ showInFinder: (path: string) => ipcRenderer.invoke('shell:showInFinder', path)
+}
+
+contextBridge.exposeInMainWorld('api', api)
+
+export type ElectronAPI = typeof api