@@ -250,6 +250,33 @@ export const DiffOverlay: React.FC<DiffOverlayProps> = React.memo(({
250250 } ;
251251 } , [ isOpen , sessionId , target , filePath , handleRefresh ] ) ;
252252
253+ // Fallback: staging operations always record a timeline event, while status updates can be throttled/skipped.
254+ // This keeps the overlay in sync when users stage/unstage via the RightPanel checkboxes.
255+ useEffect ( ( ) => {
256+ if ( ! isOpen || ! sessionId || ! target ) return ;
257+ if ( target . kind !== 'working' || ! filePath ) return ;
258+ const unsub = window . electronAPI ?. events ?. onTimelineEvent ?.( ( data ) => {
259+ if ( ! data || data . sessionId !== sessionId ) return ;
260+ const e = data . event as { kind ?: unknown ; status ?: unknown ; meta ?: unknown } | undefined ;
261+ if ( ! e || e . kind !== 'git.command' ) return ;
262+ if ( e . status !== 'finished' && e . status !== 'failed' ) return ;
263+ const meta = ( e . meta || { } ) as Record < string , unknown > ;
264+ const source = typeof meta . source === 'string' ? meta . source : '' ;
265+ if ( source !== 'gitStaging' ) return ;
266+
267+ if ( overlayRefreshTimerRef . current ) {
268+ window . clearTimeout ( overlayRefreshTimerRef . current ) ;
269+ }
270+ overlayRefreshTimerRef . current = window . setTimeout ( ( ) => {
271+ overlayRefreshTimerRef . current = null ;
272+ void handleRefresh ( ) ;
273+ } , 80 ) ;
274+ } ) ;
275+ return ( ) => {
276+ if ( unsub ) unsub ( ) ;
277+ } ;
278+ } , [ isOpen , sessionId , target , filePath , handleRefresh ] ) ;
279+
253280 if ( ! isOpen ) return null ;
254281
255282 const workingScope = target ?. kind === 'working' ? ( target . scope || 'all' ) : null ;
0 commit comments