fix(frontend): sync worktree config to renderer on terminal restoration (#982)

* fix(frontend): sync worktree config to renderer on terminal restoration

When terminals are restored after app restart, the worktree config
was not being synced to the renderer, causing the worktree label
to not appear. This adds a new IPC channel to send worktree config
during restoration and a listener in useTerminalEvents to update
the terminal store.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(frontend): always sync worktreeConfig to handle deleted worktrees

Addresses PR review feedback: send worktreeConfig IPC message
unconditionally so the renderer can clear stale worktree labels
when a worktree is deleted while the app is closed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Andy
2026-01-13 10:12:31 +01:00
committed by AndyMik90
parent 2a2dc3b8c7
commit 68fe0860b2
6 changed files with 36 additions and 0 deletions
@@ -189,6 +189,9 @@ export async function restoreTerminal(
const win = getWindow();
if (win) {
win.webContents.send(IPC_CHANNELS.TERMINAL_TITLE_CHANGE, session.id, session.title);
// Always sync worktreeConfig to renderer (even if undefined) to ensure correct state
// This handles both: showing labels after recovery AND clearing stale labels when worktrees are deleted
win.webContents.send(IPC_CHANNELS.TERMINAL_WORKTREE_CONFIG_CHANGE, session.id, terminal.worktreeConfig);
}
// Defer Claude resume until terminal becomes active (is viewed by user)
@@ -69,6 +69,7 @@ export interface TerminalAPI {
onTerminalOutput: (callback: (id: string, data: string) => void) => () => void;
onTerminalExit: (callback: (id: string, exitCode: number) => void) => () => void;
onTerminalTitleChange: (callback: (id: string, title: string) => void) => () => void;
onTerminalWorktreeConfigChange: (callback: (id: string, config: TerminalWorktreeConfig | undefined) => void) => () => void;
onTerminalClaudeSession: (callback: (id: string, sessionId: string) => void) => () => void;
onTerminalRateLimit: (callback: (info: RateLimitInfo) => void) => () => void;
onTerminalOAuthToken: (
@@ -227,6 +228,22 @@ export const createTerminalAPI = (): TerminalAPI => ({
};
},
onTerminalWorktreeConfigChange: (
callback: (id: string, config: TerminalWorktreeConfig | undefined) => void
): (() => void) => {
const handler = (
_event: Electron.IpcRendererEvent,
id: string,
config: TerminalWorktreeConfig | undefined
): void => {
callback(id, config);
};
ipcRenderer.on(IPC_CHANNELS.TERMINAL_WORKTREE_CONFIG_CHANGE, handler);
return () => {
ipcRenderer.removeListener(IPC_CHANNELS.TERMINAL_WORKTREE_CONFIG_CHANGE, handler);
};
},
onTerminalClaudeSession: (
callback: (id: string, sessionId: string) => void
): (() => void) => {
@@ -114,6 +114,18 @@ export function useTerminalEvents({
return cleanup;
}, [terminalId]);
// Handle worktree config change (synced from main process during restoration)
// This ensures the worktree label appears after terminal recovery
useEffect(() => {
const cleanup = window.electronAPI.onTerminalWorktreeConfigChange((id, config) => {
if (id === terminalId) {
useTerminalStore.getState().setWorktreeConfig(terminalId, config);
}
});
return cleanup;
}, [terminalId]);
// Handle Claude session ID capture
useEffect(() => {
const cleanup = window.electronAPI.onTerminalClaudeSession((id, sessionId) => {
@@ -92,6 +92,7 @@ export const terminalMock = {
onTerminalOutput: () => () => {},
onTerminalExit: () => () => {},
onTerminalTitleChange: () => () => {},
onTerminalWorktreeConfigChange: () => () => {},
onTerminalClaudeSession: () => () => {},
onTerminalRateLimit: () => () => {},
onTerminalOAuthToken: () => () => {},
@@ -88,6 +88,7 @@ export const IPC_CHANNELS = {
TERMINAL_OUTPUT: 'terminal:output',
TERMINAL_EXIT: 'terminal:exit',
TERMINAL_TITLE_CHANGE: 'terminal:titleChange',
TERMINAL_WORKTREE_CONFIG_CHANGE: 'terminal:worktreeConfigChange', // Worktree config restored/changed (for sync on recovery)
TERMINAL_CLAUDE_SESSION: 'terminal:claudeSession', // Claude session ID captured
TERMINAL_PENDING_RESUME: 'terminal:pendingResume', // Terminal has pending Claude resume (for deferred activation)
TERMINAL_RATE_LIMIT: 'terminal:rateLimit', // Claude Code rate limit detected
+2
View File
@@ -219,6 +219,8 @@ export interface ElectronAPI {
onTerminalOutput: (callback: (id: string, data: string) => void) => () => void;
onTerminalExit: (callback: (id: string, exitCode: number) => void) => () => void;
onTerminalTitleChange: (callback: (id: string, title: string) => void) => () => void;
/** Listen for worktree config changes (synced from main process during restoration) */
onTerminalWorktreeConfigChange: (callback: (id: string, config: TerminalWorktreeConfig | undefined) => void) => () => void;
onTerminalClaudeSession: (callback: (id: string, sessionId: string) => void) => () => void;
onTerminalRateLimit: (callback: (info: RateLimitInfo) => void) => () => void;
/** Listen for OAuth authentication completion (token is auto-saved to profile, never exposed to frontend) */