V3-04: live map on the recording screen

Feeds RideMap from watchPointsForTrip/watchSegmentsForTrip via autoDispose.family providers. RecordingEngine stays map-free (enforced by architecture_test.dart). RideMap gained lifecycle-aware tile teardown and follow-mode, both shared with the trip-detail map.
This commit is contained in:
2026-08-17 14:45:37 -05:00
parent 0267d0108c
commit f3c7e2d6b4
8 changed files with 239 additions and 13 deletions

View File

@@ -20,7 +20,7 @@ backup are v4 — see [../BACKLOG.md](../BACKLOG.md).
| [V3-01](V3-01-activity-type.md) | Activity type per ride | M | — | Done |
| [V3-02](V3-02-settings-screen.md) | Settings screen | S | — | Done |
| [V3-03](V3-03-units.md) | Distance and speed units | S | V3-02 | Done |
| [V3-04](V3-04-live-map.md) | Live map on the recording screen | M | — | Not started |
| [V3-04](V3-04-live-map.md) | Live map on the recording screen | M | — | Done |
| [V3-05](V3-05-mounted-mode.md) | Mounted (handlebar) mode | M | V3-04 | Not started |
| [V3-06](V3-06-notification-stats.md) | Live stats in the notification | S | — | Not started |
| [V3-07](V3-07-route-drawing.md) | Route drawing (pins, straight lines) | M | — | Not started |

View File

@@ -1,6 +1,6 @@
# V3-04 — Live map on the recording screen
**Phase** Live map · **Depends on** nothing · **Size** M · **Status** Not started
**Phase** Live map · **Depends on** nothing · **Size** M · **Status** Done
## Goal
While recording, show the path as it is drawn, on the recording screen.
@@ -60,3 +60,31 @@ Behind the existing map toggle, off by default while it is unproven on battery.
## Out of scope
Mounted mode (V3-05). Other riders on the map (v4).
## Outcome
Shipped as designed. `AppDatabase.watchPointsForTrip`/`watchSegmentsForTrip` feed two
`autoDispose.family` providers (`livePointsProvider`, `liveSegmentsProvider`) keyed by
trip id; a `_LiveMap` adapter widget on the record screen reads them and hands the result
to the existing `RideMap`, unchanged in shape. `RecordingEngine` was never touched —
verified by `test/architecture_test.dart`, which greps the source rather than trusting a
comment.
`RideMap` itself grew two small, general capabilities rather than a parallel "live"
widget: a `WidgetsBindingObserver` that drops the `TileLayer` entirely (not just visually,
via widget tree omission) outside `AppLifecycleState.resumed`, and an optional `follow`
flag that recentres on the latest point via `didUpdateWidget` + a post-frame
`MapController.move`, cancelled permanently by the first user-gesture pan. Both apply
to the trip-detail map too, which is a free win: a backgrounded detail screen no longer
holds tiles fetching either.
Three existing record-screen tests (`recording swaps to PAUSE and STOP`, `paused offers
RESUME`, `discard asks before destroying anything`) had to gain an explicit `map: false` —
they predate this ticket and would otherwise have started constructing a real
`FlutterMap`/`TileLayer` against an active trip, which is exactly the tile-fetch-in-tests
problem the trip-detail tests already route around.
3 new tests: the grep-based engine-purity check in `architecture_test.dart`, plus two in
`widget_test.dart` — map presence/absence by toggle and trip state, and the lifecycle
transition (paused drops `TileLayer` but keeps `PolylineLayer`; resumed brings it back),
driven via the standard `flutter/lifecycle` platform-message technique rather than a
private binding API. `flutter analyze` clean; full suite green (224 tests, up from 221).