From fb0f4bc747f2cf281691f1fe2a2aaa198cfa2089 Mon Sep 17 00:00:00 2001 From: Het Savani <114601993+Hetsavani@users.noreply.github.com> Date: Tue, 19 May 2026 18:31:09 +0530 Subject: [PATCH] =?UTF-8?q?feat(focus-mode):=20show=20flowtime=20and=20cou?= =?UTF-8?q?ntdown=20timer=20in=20browser=20tab=20ti=E2=80=A6=20(#7640)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(focus-mode): show flowtime and countdown timer in browser tab title and removes app name during timer * fix(focus-mode): correct flowtime break browser title behavior --- .../browser-title.service.spec.ts | 115 ++++++++++++++---- .../browser-title/browser-title.service.ts | 19 +-- 2 files changed, 106 insertions(+), 28 deletions(-) diff --git a/src/app/core/browser-title/browser-title.service.spec.ts b/src/app/core/browser-title/browser-title.service.spec.ts index 862b1df804..812b4a417c 100644 --- a/src/app/core/browser-title/browser-title.service.spec.ts +++ b/src/app/core/browser-title/browser-title.service.spec.ts @@ -56,7 +56,7 @@ describe('BrowserTitleService', () => { }); describe('_getTitle', () => { - it('should return base title when not in Pomodoro mode', () => { + it('should show elapsed time for Flowtime mode when running', () => { const result = (service as any)._getTitle( FocusModeMode.Flowtime, 1500000, @@ -64,10 +64,80 @@ describe('BrowserTitleService', () => { true, false, false, + 30000, + ); + + expect(result).toBe('00:30'); + }); + + it('should show "Paused" for Flowtime mode when paused and time has elapsed', () => { + const result = (service as any)._getTitle( + FocusModeMode.Flowtime, + 0, + false, + false, + true, + false, + 120000, + ); + + expect(result).toBe('Paused 02:00'); + }); + + it('should show remaining time for Flowtime break offer (not running, zero elapsed)', () => { + const result = (service as any)._getTitle( + FocusModeMode.Flowtime, + 300000, + true, + false, + true, + false, 0, ); - expect(result).toBe('Super Productivity'); + expect(result).toBe('05:00 (Break)'); + }); + + it('should show remaining time for active Flowtime break', () => { + const result = (service as any)._getTitle( + FocusModeMode.Flowtime, + 270000, + true, + true, + false, + false, + 30000, + ); + + expect(result).toBe('04:30 (Break)'); + }); + + it('should show "Paused" and remaining time for paused Flowtime break', () => { + const result = (service as any)._getTitle( + FocusModeMode.Flowtime, + 270000, + true, + false, + true, + false, + 30000, + ); + + expect(result).toBe('Paused 04:30 (Break)'); + }); + + it('should show remaining time for Countdown mode when running', () => { + const result = (service as any)._getTitle( + FocusModeMode.Countdown, + 600000, + false, + true, + false, + false, + 0, + ); + + expect(result).toBe('10:00'); }); it('should return base title when in Pomodoro but not running or paused', () => { @@ -95,7 +165,7 @@ describe('BrowserTitleService', () => { 0, ); - expect(result).toBe('(25:00) Super Productivity'); + expect(result).toBe('25:00'); }); it('should show "Paused" when paused', () => { @@ -109,7 +179,7 @@ describe('BrowserTitleService', () => { 0, ); - expect(result).toBe('(Paused 25:00) Super Productivity'); + expect(result).toBe('Paused 25:00'); }); it('should show "Break" when break is active', () => { @@ -123,10 +193,10 @@ describe('BrowserTitleService', () => { 0, ); - expect(result).toBe('(05:00 Break) Super Productivity'); + expect(result).toBe('05:00 (Break)'); }); - it('should show both "Paused" and "Break" when both are active', () => { + it('should show both "Paused" and "Break" when both are active and time elapsed', () => { const result = (service as any)._getTitle( FocusModeMode.Pomodoro, 300000, @@ -134,10 +204,10 @@ describe('BrowserTitleService', () => { false, true, false, - 0, + 1000, ); - expect(result).toBe('(Paused 05:00 Break) Super Productivity'); + expect(result).toBe('Paused 05:00 (Break)'); }); it('should show elapsed time during overtime', () => { @@ -151,7 +221,7 @@ describe('BrowserTitleService', () => { 1560000, ); - expect(result).toBe('(26:00) Super Productivity'); + expect(result).toBe('26:00'); }); it('should show elapsed break time during overtime', () => { @@ -165,7 +235,7 @@ describe('BrowserTitleService', () => { 360000, ); - expect(result).toBe('(06:00 Break) Super Productivity'); + expect(result).toBe('06:00 (Break)'); }); it('should pad single digit minutes correctly', () => { @@ -179,7 +249,7 @@ describe('BrowserTitleService', () => { 0, ); - expect(result).toBe('(05:00) Super Productivity'); + expect(result).toBe('05:00'); }); }); @@ -190,25 +260,22 @@ describe('BrowserTitleService', () => { TestBed.flushEffects(); - expect(titleService.setTitle).toHaveBeenCalledWith('(24:59) Super Productivity'); + expect(titleService.setTitle).toHaveBeenCalledWith('24:59'); focusModeServiceMock.isBreakActive.set(true); focusModeServiceMock.timeRemaining.set(299000); TestBed.flushEffects(); - expect(titleService.setTitle).toHaveBeenCalledWith( - '(04:59 Break) Super Productivity', - ); + expect(titleService.setTitle).toHaveBeenCalledWith('04:59 (Break)'); focusModeServiceMock.isRunning.set(false); focusModeServiceMock.isSessionPaused.set(true); + focusModeServiceMock.timeElapsed.set(1000); TestBed.flushEffects(); - expect(titleService.setTitle).toHaveBeenCalledWith( - '(Paused 04:59 Break) Super Productivity', - ); + expect(titleService.setTitle).toHaveBeenCalledWith('Paused 04:59 (Break)'); focusModeServiceMock.isSessionPaused.set(false); focusModeServiceMock.isRunning.set(true); @@ -217,11 +284,17 @@ describe('BrowserTitleService', () => { TestBed.flushEffects(); - expect(titleService.setTitle).toHaveBeenCalledWith( - '(26:00 Break) Super Productivity', - ); + expect(titleService.setTitle).toHaveBeenCalledWith('26:00 (Break)'); focusModeServiceMock.mode.set(FocusModeMode.Flowtime); + focusModeServiceMock.timeElapsed.set(60000); + + TestBed.flushEffects(); + + expect(titleService.setTitle).toHaveBeenCalledWith('01:00 (Break)'); + + focusModeServiceMock.isRunning.set(false); + focusModeServiceMock.isSessionPaused.set(false); TestBed.flushEffects(); diff --git a/src/app/core/browser-title/browser-title.service.ts b/src/app/core/browser-title/browser-title.service.ts index 8b5d19d46e..510720363f 100644 --- a/src/app/core/browser-title/browser-title.service.ts +++ b/src/app/core/browser-title/browser-title.service.ts @@ -41,8 +41,9 @@ export class BrowserTitleService { isInOvertime: boolean, timeElapsed: number, ): string { - if (mode === FocusModeMode.Pomodoro && (isRunning || isSessionPaused)) { - const displayTime = isInOvertime ? timeElapsed : timeRemaining; + if (isRunning || isSessionPaused) { + const isCountTimeDown = mode !== FocusModeMode.Flowtime || isBreakActive; + const displayTime = isCountTimeDown && !isInOvertime ? timeRemaining : timeElapsed; const timeStr = msToMinuteClockString(displayTime); @@ -50,14 +51,18 @@ export class BrowserTitleService { const formattedTime = `${minutes.padStart(2, '0')}:${seconds}`; const breakStr = isBreakActive - ? ` ${this._translateService.instant(T.F.FOCUS_MODE.BROWSER_TITLE_BREAK)}` + ? ` (${this._translateService.instant(T.F.FOCUS_MODE.BROWSER_TITLE_BREAK)})` : ''; - const pausedStr = isSessionPaused - ? `${this._translateService.instant(T.F.FOCUS_MODE.BROWSER_TITLE_PAUSED)} ` - : ''; + const isActuallyPaused = isSessionPaused && !(isBreakActive && timeElapsed === 0); - return `(${pausedStr}${formattedTime}${breakStr}) ${this._baseTitle}`; + if (isActuallyPaused) { + return `${this._translateService.instant( + T.F.FOCUS_MODE.BROWSER_TITLE_PAUSED, + )} ${formattedTime}${breakStr}`; + } + + return `${formattedTime}${breakStr}`; } return this._baseTitle;