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:
98
rippr-src/docs/v2/08-nav-shell.md
Normal file
98
rippr-src/docs/v2/08-nav-shell.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user