Files
CodePilot/electron/preload.ts
T
7418andClaude Opus 4.6 0eabed8c27 feat: Git integration, terminal, unified layout — full Phase 1-5 implementation
**Layout refactor (Phase 1):**
- UnifiedTopBar replacing Header.tsx — chat title editing, project folder,
  commit/push split button, Git branch+dirty badge, terminal/file-tree toggles
- PanelZone renders FileTree, GitPanel, PreviewPanel side-by-side on the right
- Independent panel toggle states in PanelContext
- ResizeHandle unified across all panels
- Removed old RightPanel, Header, DocPreview components

**Git backend (Phase 2):**
- src/lib/git/service.ts — execFile-based Git operations with timeout + injection safety
- API routes: status, branches, checkout, log, commit, push, commit-detail, worktrees, derive
- Worktree derive creates DB session inheriting source session settings

**Git frontend (Phase 3):**
- GitPanel with 4 collapsible sections: Status, Branches, History, Worktrees
- CommitDialog with commit vs commit-and-push modes
- GitBranchSelector with inline error, worktree-occupied branches disabled
- GitWorktreeSection with switch-to/derive actions, current/dirty indicators
- useGitStatus polled in AppShell, derived into context (no redundant setState)

**Terminal (Phase 4):**
- electron/terminal-manager.ts — child_process.spawn fallback (PTY upgrade documented)
- IPC handlers + TerminalDrawer/TerminalInstance components

**Polish (Phase 5):**
- Push inline feedback with 4s auto-dismiss
- Branch detection fix, commit diff exit-code handling
- Removed redundant git state: currentBranch/gitDirtyCount now derived, not setState
- useTerminal isElectron uses lazy initializer instead of effect
- i18n keys (en + zh), user tutorial docs, handover document

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:38:00 +08:00

52 lines
2.2 KiB
TypeScript

// eslint-disable-next-line @typescript-eslint/no-require-imports
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
versions: {
electron: process.versions.electron,
node: process.versions.node,
chrome: process.versions.chrome,
},
shell: {
openPath: (folderPath: string) => ipcRenderer.invoke('shell:open-path', folderPath),
},
dialog: {
openFolder: (options?: { defaultPath?: string; title?: string }) =>
ipcRenderer.invoke('dialog:open-folder', options),
},
install: {
checkPrerequisites: () => ipcRenderer.invoke('install:check-prerequisites'),
start: () => ipcRenderer.invoke('install:start'),
cancel: () => ipcRenderer.invoke('install:cancel'),
getLogs: () => ipcRenderer.invoke('install:get-logs'),
onProgress: (callback: (data: unknown) => void) => {
const listener = (_event: unknown, data: unknown) => callback(data);
ipcRenderer.on('install:progress', listener);
return () => { ipcRenderer.removeListener('install:progress', listener); };
},
},
bridge: {
isActive: () => ipcRenderer.invoke('bridge:is-active'),
},
terminal: {
create: (opts: { id: string; cwd: string; cols: number; rows: number }) =>
ipcRenderer.invoke('terminal:create', opts),
write: (id: string, data: string) =>
ipcRenderer.send('terminal:write', { id, data }),
resize: (id: string, cols: number, rows: number) =>
ipcRenderer.invoke('terminal:resize', { id, cols, rows }),
kill: (id: string) =>
ipcRenderer.invoke('terminal:kill', id),
onData: (callback: (data: { id: string; data: string }) => void) => {
const listener = (_event: unknown, data: { id: string; data: string }) => callback(data);
ipcRenderer.on('terminal:data', listener);
return () => { ipcRenderer.removeListener('terminal:data', listener); };
},
onExit: (callback: (data: { id: string; code: number }) => void) => {
const listener = (_event: unknown, data: { id: string; code: number }) => callback(data);
ipcRenderer.on('terminal:exit', listener);
return () => { ipcRenderer.removeListener('terminal:exit', listener); };
},
},
});