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:
86
rippr-src/docs/v2/11-trip-detail.md
Normal file
86
rippr-src/docs/v2/11-trip-detail.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# T11 — Trip detail screen (stats only)
|
||||
|
||||
**Phase** 4 · **Depends on** T05, T08 · **Status** Done
|
||||
|
||||
## Goal
|
||||
|
||||
A full breakdown of a single ride — summary figures, elevation profile, speed
|
||||
distribution — with a deliberate placeholder where the map will go. Done when every
|
||||
statistic renders correctly and the screen is verifiable before osmdroid lands.
|
||||
|
||||
## Context
|
||||
|
||||
Splitting this from the map is intentional. osmdroid brings tile caching, `MapView`
|
||||
lifecycle, and coordinate projection — three sources of subtle failure. Building the
|
||||
screen first means that when the map misbehaves in T13, the surrounding screen is already
|
||||
known-good and the bug has nowhere to hide.
|
||||
|
||||
Data comes from `RideStatistics.compute()` (T05) over `pointsForTrip(id)` and
|
||||
`segmentsForTrip(id)`. Unlike the list screen, this one **does** load points — a few
|
||||
thousand rows for one trip is fine, and the derived series need them.
|
||||
|
||||
## Design
|
||||
|
||||
Sections top to bottom:
|
||||
|
||||
1. **Header** — name (inline-editable in T12) and start date/time
|
||||
2. **Map placeholder** — a bordered box captioned "Map coming in T13", replaced wholesale
|
||||
by T13/T14. Reserving the space now means the layout does not shift later.
|
||||
3. **Summary grid** — distance, moving time, elapsed time, max speed, average moving
|
||||
speed, elevation gain
|
||||
4. **Elevation profile** — line chart over distance-along-path
|
||||
5. **Speed distribution** — histogram in 10 km/h buckets
|
||||
6. **Segments** — listed only when there is more than one, showing where the ride paused
|
||||
|
||||
Charts are drawn with **Compose `Canvas`**, not a charting library. Two simple series do
|
||||
not justify a dependency, and hand-drawn keeps them consistent with the existing visual
|
||||
language.
|
||||
|
||||
Both charts need: an explicit empty/insufficient-data state, axis labels with units, and
|
||||
`tabular-nums` on any numeric label.
|
||||
|
||||
**Point loading happens off the main thread** in the ViewModel, with a loading state. A
|
||||
three-hour ride is ~21,600 rows; loading that synchronously would jank the transition
|
||||
into the screen.
|
||||
|
||||
## Implementation
|
||||
|
||||
1. `TripDetailViewModel` loading trip, points, and segments on `Dispatchers.IO`, exposing
|
||||
`Loading | Ready(summary, profile, histogram, segments) | NotFound`.
|
||||
2. Summary grid from `RideSummary`.
|
||||
3. `ElevationChart` composable — `Canvas`, path stroke, min/max labels.
|
||||
4. `SpeedHistogram` composable — `Canvas`, bars, bucket labels.
|
||||
5. Segment list, shown conditionally.
|
||||
6. Map placeholder box.
|
||||
7. `NotFound` state for a deleted trip.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] All summary figures match `RideStatistics.compute()`
|
||||
- [ ] Charts render for a real ride and degrade gracefully with <2 points
|
||||
- [x] Segments section appears only when the ride was paused
|
||||
- [x] Loading state shown while points load; no main-thread I/O
|
||||
- [ ] Deleted trip shows `NotFound` rather than crashing
|
||||
- [x] Map placeholder occupies the space the real map will take
|
||||
|
||||
> **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: loading, ready, not-found, single-segment vs multi-segment.
|
||||
Unit tests for the chart data-preparation helpers (scaling, bucketing) — the drawing
|
||||
itself is verified by screenshot on the emulator.
|
||||
|
||||
## Risks / gotchas
|
||||
|
||||
- **Main-thread point loading is the obvious trap here.** Keep it in the ViewModel on IO.
|
||||
- **Chart division by zero** when all altitudes or speeds are identical — a flat ride
|
||||
gives a zero-height range. Guard the scaling.
|
||||
- **Do not start integrating the map in this task.** The separation is the point.
|
||||
|
||||
## Out of scope
|
||||
|
||||
The map (T13, T14), rename/delete/merge (T12), export (T16).
|
||||
Reference in New Issue
Block a user