Fix paused timer auto-resuming on page navigation

applySnapshot was always setting isPaused = false and blockStartedAt =
Date.now() regardless of the actual timer state, causing a paused block
to appear running whenever the dashboard was reloaded.

- Add is_paused field to DashboardSnapshot schema
- Dashboard endpoint derives is_paused by checking whether the last
  start/resume/pause event for the current block is a pause
- applySnapshot now reads is_paused from the snapshot instead of
  resetting to false, and only sets blockStartedAt when the block is
  actually running (not paused)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 14:27:05 -08:00
parent 37416436ba
commit 3efecfda49
3 changed files with 9 additions and 3 deletions

View File

@@ -70,7 +70,8 @@ async def get_dashboard(child_id: int, db: AsyncSession = Depends(get_db)):
)
completed_ids = [e.block_id for e in events_result.scalars().all() if e.block_id]
# Compute elapsed seconds for the current block from timer_events
# Compute elapsed seconds and paused state for the current block from timer_events
is_paused = False
if session and session.current_block_id:
tick_result = await db.execute(
select(TimerEvent)
@@ -93,6 +94,8 @@ async def get_dashboard(child_id: int, db: AsyncSession = Depends(get_db)):
if last_start:
elapsed += (datetime.utcnow() - last_start).total_seconds()
block_elapsed_seconds = int(elapsed)
# Paused if the last tick event was a pause (last_start is None but events exist)
is_paused = bool(tick_events) and tick_events[-1].event_type == "pause"
return DashboardSnapshot(
session=session,
@@ -100,6 +103,7 @@ async def get_dashboard(child_id: int, db: AsyncSession = Depends(get_db)):
blocks=blocks,
completed_block_ids=completed_ids,
block_elapsed_seconds=block_elapsed_seconds,
is_paused=is_paused,
day_start_time=day_start_time,
day_end_time=day_end_time,
)

View File

@@ -43,5 +43,6 @@ class DashboardSnapshot(BaseModel):
blocks: list[ScheduleBlockOut] = []
completed_block_ids: list[int] = []
block_elapsed_seconds: int = 0 # seconds already elapsed for the current block
is_paused: bool = False # whether the current block's timer is paused
day_start_time: time | None = None
day_end_time: time | None = None