Add Rippr source snapshot and full-history bundle

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>
This commit is contained in:
2026-08-11 08:30:25 -05:00
parent 4debdfa518
commit 280fd7f988
106 changed files with 10377 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
# 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-nums` for 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
1. `TripsViewModel` exposing `observeCompletedTrips()` as state.
2. `LazyColumn` of `TripRow`.
3. Date formatting via `java.time` with the device locale and zone — **not** hardcoded
patterns. Ride timestamps come from `Location.time`, which is UTC epoch millis.
4. Reuse `Telemetry.formatDuration`.
5. Distance formatting helper — km with one decimal; metres below 1 km.
6. Tap navigates to `trip/{tripId}`.
7. Empty state.
## Acceptance criteria
- [x] Completed trips listed newest first
- [x] Active trip excluded
- [x] Empty state shown on a fresh install
- [x] Tap opens the right trip
- [ ] List updates when a ride completes, without manual refresh
- [x] No point-table reads — the screen uses only `Trip` rows
> **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.time` is 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 `Trip` row, 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).