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:
@@ -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
|
||||
|
||||
@@ -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) */
|
||||
|
||||
Reference in New Issue
Block a user