From 030f0c06ae86d64a7918328cb7a9696951dd1dc0 Mon Sep 17 00:00:00 2001 From: Truong Trung Nghia <149591043+ttncode@users.noreply.github.com> Date: Sun, 11 Oct 2026 22:32:57 +0700 Subject: [PATCH] fix: always notify on countdown end and add a notifications menu entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Make notifications discoverable and dependable. - **Notify whenever a countdown runs out**, also when the timer tab is in view. Hiding them on the visible tab made the feature look broken while testing it. Ending a session with **Done** still does not notify, since you are already there. - **Menu → Settings → Notifications** shows the current state and does the next useful thing: *Turn on notifications* asks the browser, *Notifications on · test* sends a test notification, *Notifications blocked* explains how to allow them in site settings. Covers the case where the first-visit banner was missed or dismissed. - **No hydration error from browser extensions.** Extensions such as ColorZilla add attributes (`cz-shortcut-listen`) to `
` before React hydrates; `suppressHydrationWarning` on ``/`` stops the dev error overlay, which was also covering the notification banner. ## Testing - Lint, typecheck, unit tests and build pass. - Browser with a stubbed permission state: menu shows *Turn on notifications* → after allowing shows *Notifications on · test* and the test notification fires; a 1-minute session in a visible tab produced "Focus session complete". --- README.md | 2 +- src/app/layout.tsx | 5 +++-- src/components/focus/notifications.ts | 9 +++++--- src/components/shell/StartMenu.tsx | 32 ++++++++++++++++++++++++++- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ce867d6..a1ce6db 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Runs as a web app or as a browser extension, and keeps every bit of data in your ## What you get - **Focus timer** with pause, resume, breaks, extend-on-complete and goal history (press ↑/↓ in the goal field). -- **Notifications** when a session or break ends while the timer tab is in the background (the app offers to turn them on the first time you open it). +- **Notifications** when a focus session or break runs out. The app offers to turn them on the first time you open it; you can also turn them on, test them or see why they are blocked from **Menu → Settings → Notifications**. - **Pixel-art progress animations** — a coffee cup that fills, a battery that charges, a rocket that lifts off — plus an auto-shuffle option. - **To-dos** with time estimates, notes, drag-and-drop ordering, a backlog and archive; start a focus session straight from a to-do. - **Habits** with 7- and 30-day grids and notes per day. diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 4a0710f..64a57b3 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -21,8 +21,9 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - {children} + // Browser extensions (e.g. ColorZilla) add attributes to / before React hydrates. + + {children} ); } diff --git a/src/components/focus/notifications.ts b/src/components/focus/notifications.ts index 1cdd806..41ca231 100644 --- a/src/components/focus/notifications.ts +++ b/src/components/focus/notifications.ts @@ -25,11 +25,14 @@ export async function requestNotificationPermission(): Promise