Skip to content

fix: one playback driver per map, and a full dwell after each date's tiles land - #238

Merged
mluena merged 1 commit into
developfrom
fix/timeline-single-driver-dwell
Sep 7, 2026
Merged

mluena merged 1 commit into
developfrom
fix/timeline-single-driver-dwell

Conversation

@mluena

@mluena mluena commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Overview

Follow-up to #229 (OEMC-443), prompted by the report that playback on main felt smooth and on develop did not. Measured both with the same harness (layer l15, monitor m11, 30 s of playback, per DIM_DATE: first tile request, last tile response, gap to the next date's first request).

main, normal network develop, normal network main, 1.5 s per tile develop, 1.5 s per tile
dates in 30 s 16 13 14 10
mean interval between dates 1.8 s 2.3 s 2.3 s 3.3 s
gap between "tiles landed" and next request 2.3 s 2.3 s −0.7 s (overlapping) +0.13 s

Two problems fall out of that.

Two Timelines drive playback. The legend is rendered once per breakpoint, desktop and mobile, with one copy hidden by CSS, so two Timeline instances are mounted at all widths and each ran its own interval. On main they were nearly in phase: frequent double steps, a date requested and abandoned after 16 of its 24 tiles, the next one requested 50 ms later, mean interval 1.8 s instead of 2.5 s. The tile-readiness gate from #229 hides most of it, but a 200 ms double step still showed up in 30 s.

The interval started at the previous step. Load time counted against it, so with slow tiles the next date was requested 130 ms after the current one appeared. The map sat frozen on the old date for 3.2 s, swapped, and froze again. main overlapped requests instead (−0.7 s gap), which reads as a continuous crossfade but is exactly the GeoServer waste OEMC-443 removes.

Changes, all in src/hooks/timeline.ts plus one atom in src/app/store.tsx, so both Timeline copies pick them up and nothing collides with #237:

  • Only the Timeline that claims timelinePlaybackOwnerAtom steps. The other stays passive and takes over if the owner unmounts.
  • The dwell starts when the map goes idle after a step, not at the step. Every date stays on screen for the full 2.5 s. If no tile load follows a step, the dwell starts at the step so playback never stalls.

Result with the same harness:

normal network 1.5 s per tile
mean interval between dates 2.8 s 5.8 s
gap between "tiles landed" and next request 2.65 s 2.65 s
double steps none none

Cadence with cached tiles goes from 2.5 s to 2.8 s (the ~150 ms tile load plus effect latency, on top of the 2.5 s dwell). Flag it if that matters; the constant is TIMELINE_STEP_DURATION.

Note for the store: with strict off, atom<string | null>(null) resolves to jotai's read-only overload and the setter types as never, so the owner atom is atom<string>() with undefined meaning "no owner".

Designs

N/A

Testing instructions

  1. Open /explore/monitor/m11, activate a layer with a time dimension, let playback run. Dates advance one at a time, roughly every 2.8 s; none is skipped.
  2. DevTools, Network, filter GetMap. Each date's 24 tiles complete before the next date is requested; no batch is abandoned half way.
  3. Throttle to "Slow 3G". Each date stays on screen for a full 2.5 s after its tiles appear, with the slider and the map on the same date. Playback is slower, never frozen-then-flicker.
  4. Resize the window across the tablet breakpoint (768 px) while playing. Playback continues at the same cadence; the other legend copy takes over the driver without a pause or a double step.
  5. Pause and play again, scrub the slider, click ticks: behaviour unchanged.
  6. Compare mode: the comparative timeline plays with the same pacing.

Feature relevant tickets

OEMC-443 (follow-up to #229)


Checklist before submitting

  • Meaningful commits and code rebased on develop.
  • Update CHANGELOG
  • If this PR adds feature that should be tested for regressions when
    deploying to staging/production, please add brief testing instructions
    to the deploy checklist

…tiles land

Two Timelines are always mounted, one per legend breakpoint with one
hidden by CSS, and each one drove playback. On main that meant two
intervals nearly in phase and frequent double steps: a date requested,
16 of its 24 tiles abandoned, the next date requested 50 ms later. The
tile-readiness gate from OEMC-443 hid most of it but a 200 ms double
step still slipped through.

The step interval also started at the previous step, so load time
counted against it. With slow tiles (3.2 s per date) the next date was
requested 130 ms after the current one appeared: the map sat frozen on
the old date, swapped, and froze again.

Only the Timeline that claims timelinePlaybackOwnerAtom steps now; the
other stays passive and takes over if the owner unmounts. And the dwell
starts when the map goes idle after a step, so every date is on screen
for the full interval. Cadence is tile load time + 2.5 s: measured
2.8 s with cached tiles (was 2.5 s, or 1.8 s on main with the double
steps) and 5.8 s with 1.5 s tiles, no double steps in either case.
@mluena
mluena deployed to production September 7, 2026 14:48 — with GitHub Actions Active
@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
oemc Ready Ready Preview Sep 7, 2026 2:49pm UTC

Request Review

@mluena
mluena merged commit 939109a into develop Sep 7, 2026
2 checks passed
@mluena
mluena deleted the fix/timeline-single-driver-dwell branch September 7, 2026 15:04
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.

1 participant