From b77f18f68175baa70d60403242ea784ae720a557 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Mon, 19 Jan 2026 15:40:31 +0100 Subject: [PATCH] fix(focus-mode): prevent taskbar progress bar filling every second Converts setTaskBarProgress$ effect from selector-based to action-based with 500ms throttling to prevent excessive IPC calls. The selector-based effect was firing on every timer tick (1s), causing the Windows taskbar progress bar to fill completely every second instead of gradually over the session duration. Fixes #6061 --- .../focus-mode/store/focus-mode.effects.ts | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/app/features/focus-mode/store/focus-mode.effects.ts b/src/app/features/focus-mode/store/focus-mode.effects.ts index 91ae86144..4b2a98c45 100644 --- a/src/app/features/focus-mode/store/focus-mode.effects.ts +++ b/src/app/features/focus-mode/store/focus-mode.effects.ts @@ -633,14 +633,33 @@ export class FocusModeEffects { ); // Electron-specific effects + // Action-based effect to update Windows taskbar progress (fixes #6061) + // Throttled to prevent excessive IPC calls (timer ticks every 1s) + // Follows action-based pattern (CLAUDE.md Section 8) instead of selector-based setTaskBarProgress$ = IS_ELECTRON && createEffect( () => - this.store.select(selectors.selectProgress).pipe( - skipWhileApplyingRemoteOps(), - withLatestFrom(this.store.select(selectors.selectIsRunning)), - tap(([progress, isRunning]) => { + this.actions$.pipe( + ofType( + actions.tick, + actions.startFocusSession, + actions.pauseFocusSession, + actions.unPauseFocusSession, + actions.startBreak, + actions.skipBreak, + actions.completeBreak, + actions.completeFocusSession, + actions.cancelFocusSession, + ), + // Throttle to prevent excessive IPC calls (timer ticks every 1s) + // Use leading + trailing to ensure immediate feedback and final state + throttleTime(500, undefined, { leading: true, trailing: true }), + withLatestFrom( + this.store.select(selectors.selectProgress), + this.store.select(selectors.selectIsRunning), + ), + tap(([_action, progress, isRunning]) => { window.ea.setProgressBar({ progress: progress / 100, progressBarMode: isRunning ? 'normal' : 'pause',