UI-07: rebuild Rides History with search, activity filter, and real ride thumbnails
Restyles TripsScreen toward Map HUD's GlassPanel language: a search bar and activity-filter dropdown, four distinct summary stat cards (replacing the mockup's four-identical-cards artifact), and per-ride RideMap thumbnails showing each ride's own recorded path instead of stock photos. RideHistorySummary is a pure function rather than a provider, since folding over an already-fetched trip list is cheap regardless of history length, and it makes the aggregation directly unit-testable. Average speed is distance-weighted across the whole history rather than averaging each ride's own average. Adds a showAttribution flag to RideMap (default true) to suppress the TileAttribution control on tiny list thumbnails, where it was both a UX problem and a test collision with each card's own activity icon. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Xki7YAcc2TiN2PRZJ2tXr
This commit is contained in:
@@ -25,7 +25,7 @@ v3 held to.
|
||||
| [UI-04](UI-04-customizable-hud-widgets.md) | Customizable HUD telemetry widgets (drag, resize, visibility toggle) | L | UI-03 | Done |
|
||||
| [UI-05](UI-05-map-hud-record-screen.md) | Map HUD: Record screen redesign | M | UI-01, UI-03, UI-04 | Done |
|
||||
| [UI-06](UI-06-plan-and-route-planning.md) | Plan & Route Planning redesign | M | UI-01, UI-03 | Done |
|
||||
| [UI-07](UI-07-rides-history.md) | Rides History redesign | M | UI-01, UI-03 | Not started |
|
||||
| [UI-07](UI-07-rides-history.md) | Rides History redesign | M | UI-01, UI-03 | Done |
|
||||
| [UI-08](UI-08-theme-modern-professional-dark.md) | Theme migration to Modern Professional Dark | S | — | Done |
|
||||
| [UI-09](UI-09-monochrome-dark-map-tiles.md) | Monochrome dark map tiles | S | — | Done |
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# UI-07 — Rides History redesign
|
||||
|
||||
**Depends on** UI-01, UI-03 · **Size** M · **Status** Not started
|
||||
**Depends on** UI-01, UI-03 · **Size** M · **Status** Done
|
||||
|
||||
## Goal
|
||||
Rebuild the Trips list as "Rides History": a dimmed live map background (per UI-01, not
|
||||
@@ -55,13 +55,13 @@ other tab has (dimmed), not the mockup's static blurred screenshot — see UI-01
|
||||
match whatever UI-01's nav bar ships with.
|
||||
|
||||
## Acceptance criteria
|
||||
- [ ] Background is the shared live map (dimmed), not a static image
|
||||
- [ ] Search narrows the list by name/date
|
||||
- [ ] Filter narrows the list by activity type
|
||||
- [ ] Summary row shows four distinct, real statistics, not one number repeated
|
||||
- [ ] Each ride card shows an actual thumbnail of that ride's own path, not a stock photo
|
||||
- [ ] Merge/delete/rename actions from today's `TripsScreen` still work
|
||||
- [ ] Colors and icon fill-states match Map HUD, not the Stitch export's card styling
|
||||
- [x] Background is the shared live map (dimmed), not a static image
|
||||
- [x] Search narrows the list by name/date
|
||||
- [x] Filter narrows the list by activity type
|
||||
- [x] Summary row shows four distinct, real statistics, not one number repeated
|
||||
- [x] Each ride card shows an actual thumbnail of that ride's own path, not a stock photo
|
||||
- [x] Merge/delete/rename actions from today's `TripsScreen` still work
|
||||
- [x] Colors and icon fill-states match Map HUD, not the Stitch export's card styling
|
||||
|
||||
## Tests
|
||||
- Widget: search filters the visible list correctly
|
||||
@@ -82,3 +82,67 @@ other tab has (dimmed), not the mockup's static blurred screenshot — see UI-01
|
||||
## Out of scope
|
||||
Any change to trip data, merge, or split logic (V3-10) — presentation and search/filter
|
||||
only.
|
||||
|
||||
## Outcome
|
||||
|
||||
`TripsScreen` is now a headerless screen (per UI-01) over the shared dimmed background
|
||||
map, with a `GlassPanel`-wrapped search bar (`ride-search`) plus a `PopupMenuButton`
|
||||
activity filter (`activity-filter`), a four-card distinct summary row, and `_TripCard`s
|
||||
carrying a real 88x88 `RideMap` thumbnail of that ride's own recorded path.
|
||||
|
||||
**`RideHistorySummary`** is a plain pure function (`RideHistorySummary.compute(List<Trip>)`),
|
||||
not a Riverpod provider — folding over an already-fetched list is cheap regardless of ride
|
||||
count, and being a pure function is what made it directly unit-testable against a
|
||||
hand-computed total, per the ticket's own Tests section. Its average speed is
|
||||
distance-weighted across the whole history (not an average of each ride's own average),
|
||||
so a handful of long rides isn't drowned out by many short ones. The summary reflects the
|
||||
full unfiltered history, not the currently-searched/filtered subset — it's an overview
|
||||
stat, not a count of what's visible below it.
|
||||
|
||||
**Bug found and fixed while wiring the thumbnails:** the shared `RideMap` widget
|
||||
unconditionally rendered `TileAttribution` (added in UI-09) inside every `FlutterMap`,
|
||||
including tiny 88x88 list thumbnails — both a real UX problem (attribution controls
|
||||
cluttering dozens of small thumbnails) and an actual test collision (`find.byType(Icon)`
|
||||
scoped to one trip's keyed subtree started matching the attribution button's own icon
|
||||
too, once thumbnails were added). Fixed by adding a `showAttribution` bool parameter to
|
||||
`RideMap` (default `true`, so every existing full-size map call site — Map tab
|
||||
background, Route Planner, Trip Detail — is unaffected) and passing `showAttribution:
|
||||
false` specifically for `_TripCard`'s thumbnail.
|
||||
|
||||
**The same `GlassPanel`-needs-`Material`-ancestor bug UI-06 already hit** recurred
|
||||
identically in `_TripCard` (rebuilt from `StatelessWidget` to `ConsumerWidget` to watch
|
||||
the per-trip point/segment streams for its thumbnail) and was fixed the same way:
|
||||
`Material(type: MaterialType.transparency)` wrapping the `InkWell`.
|
||||
|
||||
**Rename is correctly out of scope for this file**: it lives on `TripDetailScreen`
|
||||
(`_rename`), not the list, and was never touched here — the ticket's "merge/delete/rename
|
||||
still work" line is satisfied by leaving Trip Detail's own rename alone while restyling
|
||||
only the list's merge/delete selection toolbar.
|
||||
|
||||
**Tests:** `flutter analyze` clean. `flutter test` green at **374 tests** (up from 370),
|
||||
adding: a widget test that search narrows the list to matching rides, a widget test that
|
||||
filtering by activity narrows the list, and two unit tests for `RideHistorySummary.compute`
|
||||
(a hand-computed multi-trip total, and the empty-history zero-division guard) in a new
|
||||
`test/ride_history_summary_test.dart`. Two pre-existing `widget_test.dart` assertions
|
||||
needed updating for the new card structure: `'an active ride does not appear in the
|
||||
list'` asserted `find.byType(Card)` (now `find.byType(RideMap)`, unique to a trip card
|
||||
since `_SearchAndFilter`/`_SummaryStatCard` don't render one), and the icon-count
|
||||
collision above resolved once attribution was suppressed on thumbnails.
|
||||
|
||||
**Android emulator verification** (`Medium_Phone_API_35`): confirmed end-to-end after
|
||||
working around significant, unrelated host resource pressure during this session (the
|
||||
emulator repeatedly hit System UI/app ANRs under low host memory; resolved by freeing
|
||||
host RAM, a full emulator restart, and a `force-stop`+relaunch of the app — see session
|
||||
notes, not an app defect). Verified on-device: search field narrows the list correctly
|
||||
(a query matching neither ride's name/date shows "No rides match your search.", clearing
|
||||
it restores both); the activity filter's `PopupMenuButton` opens with all seven
|
||||
activities plus "All activities", correctly highlights the currently-active choice,
|
||||
narrows to zero rides when filtered to an activity neither seeded ride has (Bicycle),
|
||||
and shows both again when filtered to the activity they actually have (Motorcycle); the
|
||||
four summary cards (Total Dist/Total Time/Rides/Avg Speed) render as genuinely distinct
|
||||
values, not the mockup's four-identical-cards artifact; both ride cards render real,
|
||||
distinct polyline thumbnails with no attribution icon visible; long-pressing a card
|
||||
enters selection mode with the Cancel/count/Merge/Delete toolbar, Merge correctly stays
|
||||
disabled at one selection and enables at exactly two. Colors/icons match Map HUD's
|
||||
established palette (translucent `GlassPanel` cards, blue accent, same activity icon set)
|
||||
throughout.
|
||||
|
||||
Reference in New Issue
Block a user