UI-05: rebuild Record screen as the Map HUD (design north star)

Replaces the scrolling stats-card layout with the full-bleed Map HUD:
UI-04's draggable/resizable HUD widgets float over UI-01's shared
background map (full opacity on this tab), and the old Pause/Stop/Resume/
Discard buttons become full-bleed, icon-only segments matching the
mockup's tertiary-container/error-container colors exactly. The idle
state keeps its prior compact layout deliberately -- HUD widgets only
appear once a ride exists, preserving the existing "a resting screen
must not look like a ride going nowhere" guarantee rather than
reinterpreting it.

State-machine logic (ticker, wakelock, speed subscription, error
handling) is untouched; every pre-existing record-screen test passed
unchanged against the rebuilt screen. Added tests that actually tap
Start/Pause/Stop and verify engine state changes, confirm HUD widgets
render over the map rather than replacing it, and verify the
mounted-mode speed digit's real contrast ratio against GlassPanel's
translucent surface specifically (the ticket's own named risk).

Corrects a UI-04 mistake found while implementing this ticket: the HUD's
default four metrics were ordered Speed/Distance/Elapsed/Max Speed, a
guess made before reading the actual Map HUD mockup HTML closely. The
real fixed row is Speed/Avg Speed/Dist/Time -- reordered HudMetric to
match and updated every test that asserted the old order.

Adds PulsingLocationMarker (UI-03) to RideMap's live usage via a new
showLocationMarker flag, and explicit tertiaryContainer/errorContainer
tokens to ripprColors so the control bar matches the design system's
literal values rather than an auto-derived tonal palette.

Verified end-to-end on a real emulator: Start, Pause, Resume, and Stop
all correctly drive the trip state machine with the full live map behind
everything. A lengthy false alarm during this verification (taps
appearing to do nothing) turned out to be a screenshot-scale
mis-measurement on the verification side, not an app defect -- resolved
by sampling pixel colors directly from the raw screenshot to find the
control bar's true on-screen position.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Xki7YAcc2TiN2PRZJ2tXr
This commit is contained in:
2026-08-24 08:22:51 -05:00
parent bcface3529
commit fa6b1b8ef2
13 changed files with 508 additions and 230 deletions

View File

@@ -119,11 +119,17 @@ Built the full generic infrastructure the ticket scopes, deliberately stopping s
wiring it into the real Record screen -- that assembly (real metric values from
`RecordUiState`, replacing the fixed stats card) is UI-05's job, per the dependency
graph. `HudMetric` (`lib/src/hud/hud_metric.dart`) is the stable 8-value enum;
critically, the first four (`speed, distance, elapsedTime, maxSpeed`) are ordered to
match the Stitch mockup's fixed row exactly, since `HudWidgetLayout.defaultFor` derives
both default grid position and which metrics start visible directly from enum index --
a bug caught by a widget-layout test (`maxSpeed` briefly wasn't in the first four because
`movingTime` was ordered ahead of it).
critically, the first four are ordered to match the Stitch mockup's fixed row exactly,
since `HudWidgetLayout.defaultFor` derives both default grid position and which metrics
start visible directly from enum index.
**Correction (UI-05):** this ticket originally ordered those first four as
`speed, distance, elapsedTime, maxSpeed` -- a guess made without having read the actual
Map HUD mockup HTML closely yet. Implementing UI-05 against that same HTML directly
showed the real fixed row is Speed/**Avg Speed**/Dist/Time. The enum was reordered to
`speed, avgSpeed, distance, elapsedTime, maxSpeed, movingTime, elevationGain,
pointsCaptured` and every test here that had asserted the old order was updated
alongside it -- see UI-05's own Outcome for the full account.
`HudWidgetLayout` (`hud_widget_layout.dart`) holds fractional `x/y/width/height` +
`visible`, with `clamped()` enforcing a legibility floor and sane ceiling (size clamped