Timeline marks carry labels; a tap by a tick goes to its mark

A layer's world clock coverage may now give each mark as an object,
{ time, label?, id?, kind? }, as well as a bare epoch ms number, and the
two may be mixed. worldClock.coverage() keeps marks as the sorted list of
distinct times, so existing readers are unchanged, and adds markDetails:
the merged marks in time order (then kind, label and id), each frozen and
holding only the fields given. Marks given alike by several sources appear
once, a bare time is dropped where a labelled mark shares it, and a mark
with no finite time is ignored. The contract is documented in the
worldClock JSDoc and docs/APPLICATION.md.

Launches label their marks with the mission's name (the launch's where it
has none), cut to 27 characters in capitals as the mission index shows
names. Earthquakes of magnitude 6 and up label theirs with the magnitude
as the map shows it and the feed's place cut to 40 characters, such as
"M6.4 · 113 km SSE of Lata, Solomon Islands"; the layer now tells the clock
when the labels change as well as the times.

On the timeline, a pointer within 6 px of a tick shows its label over the
track (nothing for an unlabelled mark), and a tap there goes exactly to
the mark's time instead of the point tapped. A tap elsewhere and a drag
work as before, and ticks stay ticks. The arrow keys still step from mark
to mark; with the handle on a mark, its labels follow the time in the
handle's aria-valuetext, and show over the track while it has focus.
This commit is contained in:
Sameh Khamis committed 2026-11-14 20:30:01 -08:00
1 parent 7cb854c923
commit 558e4a919a
17 files changed
+490 -50

No files matched your search

+18
View File
@@ -191,6 +191,24 @@ observed-history clock those layers share for the catalog's lifetime. That
clock, the catalog's `weatherClock`, follows the world clock (`gods-eye-view/time`)
and has no time controls of its own: move time with the world clock's `seek`,
`play`, `pause` and `goLive` (`weatherClock.world` is the one it follows).
A layer gives the world clock's timeline the time it can show with
`worldClock.register({ id, coverage })` (`gods-eye-view/time`), which returns
the unregister; call `worldClock.coverageChanged()` when that time changes.
`coverage()` returns null while the layer has none, or
`{ start, end, marks? }` in epoch ms. `marks` are the moments worth going to,
drawn as ticks the timeline's arrow keys step to and a tap on or within 6 px of
snaps to. Each mark is a number, or `{ time, label?, id?, kind? }`: `label` is
short text shown when the pointer is on the tick and told with the time while
the handle is on the mark, `id` the layer's own key for the event and `kind`
what sort of event it is (`'launch'`, `'earthquake'`). The two forms may be
mixed; a mark without a finite time, and a `label`, `id` or `kind` that is not
a non-empty string, are ignored. `worldClock.coverage()` returns the union of
the registered layers, `{ start, end, marks, markDetails }`, or null: `marks`
is every mark's time once, in order, as numbers, and `markDetails` the marks in
time order, each a frozen `{ time, label?, id?, kind? }` holding only the
fields given, with marks given alike by several layers once and a bare time
left out where a mark with more to say shares it.
A `weather` source may also supply decoded frames: an optional
`getFrameImage({ product, time, size, bbox, signal })` returns a whole-extent or
detail image and an optional `getFrameTile({ product, time, z, x, y, size,