Two copies for two jobs. rippr-src/ is a browsable git archive export of the tracked tree at 2f76983 - no build outputs, no local.properties, no nested .git - which is convenient to read in gitea but carries no history and will drift. rippr-full-history.bundle is the real backup: all 18 commits, verified as "records a complete history" and test-cloned before committing. This matters because ~/dojo/rippr has no git remote and otherwise exists only on one machine. rippr-src/SNAPSHOT.md explains the difference and how to restore. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3.1 KiB
T10 — Trips list screen
Phase 4 · Depends on T02, T08 · Status Done
Goal
A scrollable list of completed rides, each showing enough to identify it, tapping through to detail. Done when past rides are browsable and the list updates reactively as rides complete.
Context
There is currently no way to see a past ride at all — v1 has one screen showing lifetime totals. This is the first place trips become visible as objects.
TripDao.observeCompletedTrips() from T02 provides the data, ordered startedAt DESC.
All displayed values are already persisted on the Trip row by T07, so this screen
runs no computation — no loading points, no statistics. That keeps it fast with
hundreds of rides.
Design
One row per trip:
Sat 9 Aug · 14:32 47.2 km
1h 12m moving · max 118 km/h ▸
- Name if set, otherwise a date-derived label ("Sat 9 Aug · 14:32")
- Distance as the right-aligned prominent figure
- Moving time and max speed as the secondary line
- Monospace with
tabular-numsfor the figures so columns align down the list
Empty state matters here — a new install has no trips, and an empty screen with no explanation reads as broken. Show a short line pointing at the Record tab.
An in-progress trip is excluded (endedAt IS NULL). A half-finished ride in the
history list with a growing distance would be confusing; the Record screen owns that.
Grouping by month is tempting but premature. Revisit when there are enough rides to justify it.
Implementation
TripsViewModelexposingobserveCompletedTrips()as state.LazyColumnofTripRow.- Date formatting via
java.timewith the device locale and zone — not hardcoded patterns. Ride timestamps come fromLocation.time, which is UTC epoch millis. - Reuse
Telemetry.formatDuration. - Distance formatting helper — km with one decimal; metres below 1 km.
- Tap navigates to
trip/{tripId}. - Empty state.
Acceptance criteria
- Completed trips listed newest first
- Active trip excluded
- Empty state shown on a fresh install
- Tap opens the right trip
- List updates when a ride completes, without manual refresh
- No point-table reads — the screen uses only
Triprows
Not verified. The unchecked items above, and the Compose UI tests below, were not done. Verification for T08–T11 was manual on the emulator (screenshots through the full flow) plus the existing unit and instrumented suites. Compose UI tests are outstanding — tracked in T18.
Tests
Compose UI tests:
- Empty state on no data
- Rows render in the right order
- Tap emits the right navigation event
- Active trip absent from the list
Instrumented DAO test for ordering and the endedAt IS NULL exclusion.
Risks / gotchas
- Timezone.
Location.timeis UTC. Format in the device zone or a ride at 21:00 local shows as tomorrow. - Do not compute stats here. If a value is missing from the
Triprow, fix T07 rather than loading points in the list — that path leads to a screen that janks after fifty rides.
Out of scope
Rename/delete/merge (T12); detail content (T11).