Files
samplez/rippr-src/docs/v2/08-nav-shell.md
uhryniuk 280fd7f988 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>
2026-08-11 08:30:25 -05:00

99 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# T08 — Navigation shell + ViewModels
**Phase** 4 · **Depends on** T01 · **Status** Done
## Goal
Three navigable destinations, theme extracted out of the Activity, and state moved into
ViewModels. Done when Record, Trips, and Trip Detail are reachable with a working back
stack and `MainActivity` no longer owns screen state.
## Context
`app/src/main/java/com/rippr/MainActivity.kt` (216 lines) currently does everything:
permission launcher, service intents, theme definition, screen composition, and state.
That was proportionate for one screen and will not survive three.
Existing pieces to preserve rather than rewrite:
- The permission flow (`RequestMultiplePermissions`, with `POST_NOTIFICATIONS` added only
on TIRAMISU+) works and should move largely as-is.
- The battery-optimisation exemption prompt is genuinely useful for an app that must
survive a multi-hour ride; keep it on the Record screen.
- `RipprTheme` is currently a private composable applying `darkColorScheme()`. Dylan
called the UI "simple and clean" and explicitly likes it — **do not redesign it**.
Extract, do not restyle.
- `StatRow` and `BigStat` are reusable; move them into a shared `ui/components/`.
## Design
```
ui/
theme/ Theme.kt, Color.kt
components/ StatRow.kt, BigStat.kt, ConfirmDialog.kt
record/ RecordScreen.kt, RecordViewModel.kt
trips/ TripsScreen.kt, TripsViewModel.kt
detail/ TripDetailScreen.kt, TripDetailViewModel.kt
RipprNavHost.kt
```
Routes:
| Route | Screen |
|---|---|
| `record` | Start destination |
| `trips` | Trip list |
| `trip/{tripId}` | Detail, `tripId: Long` argument |
`navigation-compose` rather than hand-rolled state switching: the back stack from detail
→ list is worth not writing by hand, and it gives correct behaviour on the system back
gesture for free.
**ViewModels** get the repository through a simple factory — the app already uses a
`@Volatile` singleton for `AppDatabase` and T03 adds one for `TripRepository`. Hilt would
be more ceremony than a three-screen app earns.
**Navigation from Record → Trips** goes in a top bar action, keeping the Record screen's
centre free for the numeric readout.
## Implementation
1. Extract `ui/theme/` from `MainActivity`.
2. Move `StatRow` / `BigStat` into `ui/components/`, unchanged.
3. Create `RipprNavHost` with the three routes.
4. Add a ViewModel per screen with a shared factory.
5. Reduce `MainActivity` to: permissions, battery exemption, `setContent { RipprTheme { RipprNavHost() } }`.
6. Move service-intent dispatch into `RecordViewModel`.
## Acceptance criteria
- [x] All three destinations reachable; system back works from detail
- [x] `MainActivity` holds no screen state
- [x] Visual appearance of the Record screen is unchanged
- [x] Permission flow and battery-optimisation prompt still function
- [ ] Config change (rotation) does not lose state
> **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
Instrumented Compose UI tests:
- Navigate record → trips → detail → back → back
- Rotation preserves screen state
- Existing suites stay green
## Risks / gotchas
- **Do not restyle.** The brief was "simple and clean, I like that". This task is
structural only.
- **`tripId` argument type.** Room ids are `Long`; declare `NavType.LongType` explicitly
or it silently arrives as a String.
- The v1 UI reads state via `collectAsStateWithLifecycle` already — keep that, it is the
correct choice over `collectAsState` for lifecycle-aware collection.
## Out of scope
Screen content beyond wiring (T09, T10, T11); any map (T13).