feat(train): the workouts listed, and each one's page with its map (ADR 0030, D22-D24)

Home lists the person's workouts newest first under their months, each
with its activity's icon, its name (else the time of day's and the
activity's), when it started, its distance, moving time and pace or
speed; those this device can't open come last, locked. A workout's page
shows its track on the instance's map source (flutter_map with
vector_map_tiles, pinned at 9.0.0-beta.13), in pieces between its
pauses, start and end marked; its totals with the elevation gained;
its splits per kilometre on foot, per 5 km cycling; pace or speed and
elevation over the distance, drawn by the app's own painter; and what
the map's source sees. Its name and notes are edited there; deleting
asks first and can be undone for a moment from home (halkyon_app's
DelayedDeletions, TrainPerson.deletions).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-28 14:29:39 +01:00
commit 405577050d
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -1,7 +1,7 @@
# ADR 0030: Halkyon Train, what it does and where its data comes from
- **Status:** decided 27–28 Oct 2026, by the developer (D1–D22 below). The shell (D12)
is built; recording (D13–D22) is being built.
- **Status:** decided 27–28 Oct 2026, by the developer (D1–D24 below). The shell (D12)
is built; recording (D13–D24) is being built.
- **Numbering:** 0025 is held by the federation draft (stashed), 0026–0029 by the .NET
rewrite on the local branch `rewrite-dotnet`, abandoned on 27 Oct; Train takes the next
free number so that neither is ever read as this one.
@ -346,7 +346,45 @@ Strava. What was found, 27 Oct:
(D11), so 5c needs no deploy; a workout's page names the source drawing it and what it
sees (the device's address and the area viewed, not the track). The sidecar comes when
route planning gives Train's server a reason to run on the instance: the region's
PMTiles file served by Caddy with range requests, no server code.
PMTiles file served as ordinary tiles (D23).
- **D23 `flutter_map` 8 with `vector_map_tiles` 9's beta** (recommended; 28 Oct): D11's
combination doesn't exist as released, as `vector_map_tiles`' stable line (8) needs
`flutter_map` 7 and its PMTiles plugin (1.5.0, October 2024) `vector_map_tiles` 8,
while the 9 line, beta since November 2024 (beta.13 on 1 September 2026), is where its
maintainer works and needs `flutter_map` 8. Over the stable line, all three packages
of 2024 and held there until 9 is out, and over `maplibre` (0.3.7), native and smooth
but drawing tracks and their colours as its layers rather than Flutter's widgets, the
reason for D11's choice. The beta is pinned exactly and moves to 9.0.0 once released;
the sidecar serves the region's PMTiles file as ordinary vector tiles with Protomaps'
`pmtiles serve` (go-pmtiles, BSD-3-Clause) instead of the app reading it, so the app
holds nothing of PMTiles'.
- **D24 The workouts and a workout's page** (the developer's; 28 Oct): home lists
the workouts newest first under their months, each with its activity's icon, its name
(else the time of day's and the activity's, "Morning run"), its day and start, distance,
moving time and pace (km/h cycling); one this device can't open shows locked; Record
stays. A workout's page: the map on its upper part, the track in cobalt, its pauses
gaps rather than straight jumps, start and end marked, the source's credit on it, fit
to the track (heart rate's colours with the strap, 5e); its totals (distance, moving
time, pace or speed, the whole time, the elevation gained, counting climbs above 3 m
of the fixes precise enough, as GPS's altitude is noisy); its splits, per kilometre on
foot, per 5 km cycling; charts of pace or speed and of elevation over the distance,
drawn by the app's own small painter (over `fl_chart`, MIT, larger than two lines
need and one more dependency to follow); under the map, which source draws it and what
that sees, with its page where the operator names one (D22). Its name and notes are
edited; deleting asks first and offers an undo, as Learn's deletions do. Without GPS no
map and no splits.
Built so (28 Oct), with choices of mine for the developer to look at: the day's parts
start at 5, 12, 17 and 22 on the device's clock; locked workouts come last under no
month, as when they were is sealed too; the map stays fixed above the page as it
scrolls, pans and zooms but doesn't turn, and folds the source's credit into
flutter_map's attribution button, the credit being wider than a phone; start green,
end cerise, the track cobalt in either theme (the map's colours are the source's);
the charts show their lowest and highest value beside them and nothing else; where
the instance can't be asked for its map source, the page says so and shows the rest;
the elevation counts a climb once it passes 3 m above where it last turned, so a
steady climb's last metres short of the next 3 are not counted (a 20 m hill reads as
18 or 19 m): the simple filter, to be compared with recorded runs.
## Consequences