Fix double-click to switch blocks and TV elapsed reset

Double-click fix:
- After awaiting the pause, optimistically set current_block_id and
  isPaused on the store so the UI switches instantly. The subsequent
  WS start event confirms the state without requiring a second click.

TV elapsed reset fix:
- The TV's local cache was empty for blocks paused before it connected,
  so returning to those blocks showed 0 elapsed.
- Backend now computes the block's accumulated elapsed from previous
  start/pause cycles and includes it as block_elapsed_seconds in the
  'start' WS event payload.
- All clients (Dashboard and TV) now use this authoritative server value
  instead of relying solely on the local cache.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 21:33:36 -08:00
parent a63674fe56
commit a02876c20d
3 changed files with 33 additions and 2 deletions

View File

@@ -189,6 +189,29 @@ async def timer_action(
await db.commit()
await db.refresh(session)
# For 'start' events, compute elapsed from previous intervals so every
# client (including TV) can restore the correct offset without a cache.
block_elapsed_seconds = 0
if body.event_type == "start" and event.block_id:
tick_result = await db.execute(
select(TimerEvent)
.where(
TimerEvent.session_id == session.id,
TimerEvent.block_id == event.block_id,
TimerEvent.event_type.in_(["start", "resume", "pause"]),
TimerEvent.id != event.id,
)
.order_by(TimerEvent.occurred_at)
)
tick_events = tick_result.scalars().all()
last_start_time = None
for e in tick_events:
if e.event_type in ("start", "resume"):
last_start_time = e.occurred_at
elif e.event_type == "pause" and last_start_time:
block_elapsed_seconds += int((e.occurred_at - last_start_time).total_seconds())
last_start_time = None
# Broadcast the timer event to all TV clients
ws_payload = {
"event": body.event_type,
@@ -196,6 +219,7 @@ async def timer_action(
"block_id": event.block_id,
"current_block_id": session.current_block_id,
"is_active": session.is_active,
"block_elapsed_seconds": block_elapsed_seconds,
}
await manager.broadcast(session.child_id, ws_payload)