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.8 KiB
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, withPOST_NOTIFICATIONSadded 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.
RipprThemeis currently a private composable applyingdarkColorScheme(). Dylan called the UI "simple and clean" and explicitly likes it — do not redesign it. Extract, do not restyle.StatRowandBigStatare reusable; move them into a sharedui/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
- Extract
ui/theme/fromMainActivity. - Move
StatRow/BigStatintoui/components/, unchanged. - Create
RipprNavHostwith the three routes. - Add a ViewModel per screen with a shared factory.
- Reduce
MainActivityto: permissions, battery exemption,setContent { RipprTheme { RipprNavHost() } }. - Move service-intent dispatch into
RecordViewModel.
Acceptance criteria
- All three destinations reachable; system back works from detail
MainActivityholds no screen state- Visual appearance of the Record screen is unchanged
- 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.
tripIdargument type. Room ids areLong; declareNavType.LongTypeexplicitly or it silently arrives as a String.- The v1 UI reads state via
collectAsStateWithLifecyclealready — keep that, it is the correct choice overcollectAsStatefor lifecycle-aware collection.
Out of scope
Screen content beyond wiring (T09, T10, T11); any map (T13).