Skip to content

Fix portal timers stopping when tab is backgrounded + upgrade Next.js to patch DoS CVE#2095

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/fix-timers-not-running-background
Draft

Fix portal timers stopping when tab is backgrounded + upgrade Next.js to patch DoS CVE#2095
Copilot wants to merge 3 commits intomainfrom
copilot/fix-timers-not-running-background

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 21, 2026

Description

Portal timers (field/scoresheet and judging/rubrics) halt when the browser tab loses focus because browsers throttle setInterval in backgrounded tabs, causing ticks to be skipped entirely.

Timer fix (use-field-timer.ts, use-judging-timer.ts)

Replaced the tick-counting approach with wall-clock compensation:

  • Track lastTickAt (wall-clock timestamp) via ref when the timer starts/resumes
  • Poll every 500ms instead of 1000ms
  • On each poll, compute elapsedTicks = Math.floor((now - lastTickAt) / 1000) and advance lastTickAt by only whole seconds — fractional time accumulates correctly across polls
  • Dispatch a single TICK_BY action instead of a loop of TICK dispatches
intervalRef.current = setInterval(() => {
  if (lastTickAtRef.current === null) return;
  const now = Date.now();
  const elapsedMs = now - lastTickAtRef.current;
  const elapsedTicks = Math.floor(elapsedMs / 1000);
  if (elapsedTicks > 0) {
    lastTickAtRef.current += elapsedTicks * 1000;
    dispatch({ type: 'TICK_BY', count: elapsedTicks });
  }
}, 500);

TICK_BY in the judging timer handles multi-stage transitions in a single reducer call. The effect dependency is reduced to [state.isRunning] — no longer recreated on every tick.

The field timer's endgame sound uses a threshold-crossing check (prev > 30 && curr <= 30) instead of exact equality, so the 30-second cue plays even if time jumps past that mark while backgrounded.

Dependency upgrade (package.json, package-lock.json)

Upgraded next from ^16.1.6^16.2.3 (resolves to 16.2.4) to patch a Denial of Service via Server Components vulnerability (affected >= 16.0.0-beta.0, < 16.2.3). Companion packages updated to match:

Package Before After
next ^16.1.6 ^16.2.3
eslint-config-next ^16.1.6 ^16.2.3
@next/eslint-plugin-next ^16.1.1 ^16.2.3

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Screenshots

N/A — timer logic only, no UI changes.

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • My changes generate no new warnings

Copilot AI and others added 2 commits April 21, 2026 19:02
Use wall-clock time tracking in useFieldTimer and useJudgingTimer hooks
to compensate for browser throttling of setInterval in backgrounded tabs.

- Track lastTickAt (wall clock timestamp of last processed tick) via ref
- Use 500ms polling interval for responsiveness
- On each poll, calculate elapsed whole seconds and dispatch a single
  TICK_BY action instead of multiple TICK dispatches
- Add TICK_BY reducer action to both hooks that advances time in one
  reducer call (handling multi-stage transitions in the judging timer)
- Update endgame sound trigger in useFieldTimer to use a
  threshold-crossing check (prev > 30 && curr <= 30) so the sound plays
  even if the timer jumps past the 30-second mark while backgrounded

Agent-Logs-Url: https://github.com/FIRSTIsrael/lems/sessions/862d5df0-5063-4adb-ad71-43f94de3bd0d

Co-authored-by: johnmeshulam <55348702+johnmeshulam@users.noreply.github.com>
CVE: Next.js Denial of Service with Server Components
Affected: >= 16.0.0-beta.0, < 16.2.3
Resolved to: 16.2.4 (latest patch release)

Also update companion packages to match:
- @next/eslint-plugin-next: ^16.1.1 -> ^16.2.3
- eslint-config-next: ^16.1.6 -> ^16.2.3

Agent-Logs-Url: https://github.com/FIRSTIsrael/lems/sessions/862d5df0-5063-4adb-ad71-43f94de3bd0d

Co-authored-by: johnmeshulam <55348702+johnmeshulam@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix portal timers not running in background Fix portal timers stopping when tab is backgrounded + upgrade Next.js to patch DoS CVE Apr 21, 2026
Copilot AI requested a review from johnmeshulam April 21, 2026 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

Portal timers don't run in background

2 participants