Skip to content

fix: Pomodoro timer no longer advances while the page is closed - #66

Open
Punnawit9285 wants to merge 6 commits into
docchula:masterfrom
Punnawit9285:fix-pomodoro
Open

fix: Pomodoro timer no longer advances while the page is closed#66
Punnawit9285 wants to merge 6 commits into
docchula:masterfrom
Punnawit9285:fix-pomodoro

Conversation

@Punnawit9285

Copy link
Copy Markdown
Collaborator

A closed tab reopens paused at the second it stopped.

Switching tabs is unaffected. A hidden page keeps ticking.

interval(1000) is throttled once a tab is hidden, so counting one second per
tick made the countdown and the phase-change chime drift behind real time.
Derive the remaining time from a wall-clock anchor instead, so a throttled or
delayed tick corrects itself.

Also unlock the AudioContext from the start/resume gesture and keep it
suspended between chimes. iOS blocks a context first resumed from a timer
callback, and holding an active audio session for the life of the page was
observed to interrupt the lecture video playing alongside it.
Restoring a saved timer treated the wall-clock gap since the tab closed as
elapsed study time, walking phase by phase to catch up and crediting a
completed session on each pass. Reopening after three days took the session
count from 2 to 494. The catch-up loop also tested the saved phase rather
than the one it was advancing, so break phases were counted as completed
study sessions too.

The timer only advances while the page is open, so drop the catch-up along
with the 12-hour cap that tried to bound it. A closed tab now resumes paused
at the second it stopped, in the same phase, with the session count
untouched. Switching tabs is unaffected: a hidden page keeps ticking.

Flush the timer on visibilitychange and pagehide so a tab closed mid-phase
resumes from where it actually stopped rather than from the last phase
change, and make the periodic save a 5-second wall-clock throttle, since the
old modulo gate can be skipped now that the countdown is wall-clock derived.
@Punnawit9285 Punnawit9285 changed the title The timer no longer advances while the page is closed fix: Pomodoro timer no longer advances while the page is closed Aug 30, 2026
@ittipatken

Copy link
Copy Markdown
Member

Isn’t the timer should be stopped when the tab is closed?

A hidden page kept ticking, so time spent reading something in another tab
counted as study time. Pause on visibilitychange instead, and resume as soon as
the page comes back. Only a pause this handler caused is resumed automatically:
a deliberate pause stays paused, and so does a tab that was closed rather than
hidden, since the flag does not survive the reload.

pause() now settles the countdown from the wall-clock anchor rather than the
last tick. That was accurate enough when pausing was a button press, but it now
happens on every tab switch, often just as a hidden tab's interval is throttled.

Session counts are also tagged with the study day they were earned on and
cleared once it changes. The boundary is 04:00 rather than midnight so a session
running at 2am still counts towards that night. The rollover is checked on each
tick, on restore, and when a tab becomes visible again, since an idle tab is not
ticking and would otherwise miss it.
Ionic sets "contain: layout" on .ion-page, which makes it the containing block
for position:fixed descendants. The notification therefore resolved against the
page box instead of the viewport, so it drifted by however much the two
disagree. In the in-app browsers used by the Google and Chrome apps that gap is
the height of their dynamic toolbar, which dropped the notification down over
the course list.

Move it out of the component and attach it to document.body, where fixed
positioning means the viewport again. While an element is fullscreen the browser
paints only that element's subtree, so it follows the fullscreen element in and
out for the duration. Its styles move to global.scss along with it, since the
element no longer sits inside the component's view encapsulation.

The DOM handling lives in its own class rather than the component so it can be
driven directly in a browser test, without Angular or Ionic. The entry
transition is restarted with a synchronous reflow rather than a pair of
animation frames: a second frame never arrives in a tab that is not
compositing, which left the notification invisible.

Its top offset clears the toolbar so it cannot straddle the header, and the
title and body are set as text, never markup.
On iOS the lecture video was handed to Apple's native fullscreen player, which
renders outside the web view. Nothing in the DOM can be drawn over it, so the
Pomodoro phase notification never appeared while a video was fullscreen.

Set playsinline so playback stays in the page, and preferFullWindow so video.js
uses its own full-window mode instead of the native player. preferFullWindow is
only consulted when the browser exposes no Fullscreen API, which is exactly the
iPhone and in-app web view case; browsers that have the API are unaffected and
fullscreen the player element as before, with the notification placed inside it.

The trade is that fullscreen on those browsers is now a full-window page rather
than the native player, so its AirPlay and picture-in-picture affordances are
not available there. An overlay cannot be drawn over a native player at all, so
this is the only way to show the notification.
@Punnawit9285

Copy link
Copy Markdown
Collaborator Author

The timer is stopped when user switch tab as you suggested now, which timer will resume immediately after user return to Flick

Also I make timer progress reset at everyday 4 a.m. too so that it won't show user excessively high cycle count number like in the status quo.

@ittipatken

Copy link
Copy Markdown
Member

The timer should not reset at a specific time, for example a user might start using the timer at 03:00.

Pausing on a tab switch is right when the lecture being timed is on this page,
and wrong when the studying is happening on another site. Neither default suits
both, so the session type is now the user's choice: watching lectures pauses on
leaving, studying elsewhere keeps running.

The control is a segment on the timer card with a line stating what the current
choice does, so the behaviour is visible rather than something to discover by
switching tabs. Options come from SESSION_MODES so the labels live beside the
phases and duration fields rather than in the template.

Defaults to watching lectures, which is the existing behaviour, and the choice
is saved with the other preferences.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants