Implement main app navigation

This commit is contained in:
2026-05-08 14:03:26 +02:00
parent f7e866a08d
commit 794e27c554
90 changed files with 11725 additions and 187 deletions

View File

@@ -0,0 +1,91 @@
---
phase: 02.1
plan: 04
subsystem: navigation
tags: [kotlin, compose-multiplatform, navigation, navigation-compose, type-safe-routes, multi-back-stack]
requires: ["02.1-01", "02.1-02"]
provides:
- "navigation/Routes.kt — 8 @Serializable route types (4 graphs + 4 home destinations)"
- "navigation/BottomBarDestination.kt — enum binding routes ↔ string resources ↔ icons ↔ search visibility"
- "navigation/RootNavHost.kt — single root NavHost with 4 nested navigation() sub-graphs"
- "navigation/NavExtensions.kt — NavHostController.navigateToTab() with four-flag multi-back-stack incantation"
- "9 new shared shell/search keys in strings.xml"
affects:
- "composeApp/src/commonMain/composeResources/values/strings.xml (append-only — 9 new keys)"
- "composeApp/src/commonTest/kotlin/dev/ulfrx/recipe/navigation/NavigationTest.kt (un-Ignored, real assertions)"
tech-stack:
added:
- "androidx.navigation.compose.NavHost / navigation / composable (typed routes via @Serializable)"
- "androidx.navigation.navOptions DSL (used in tests)"
patterns:
- "Multi-back-stack tab navigation: popUpTo(graph.findStartDestination().id){saveState=true} + launchSingleTop + restoreState"
- "Per-tab parent NavBackStackEntry retrieval for future Koin VM scoping (RESEARCH § Pattern 2)"
key-files:
created:
- "composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/navigation/Routes.kt"
- "composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/navigation/BottomBarDestination.kt"
- "composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/navigation/RootNavHost.kt"
- "composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/navigation/NavExtensions.kt"
modified:
- "composeApp/src/commonMain/composeResources/values/strings.xml"
- "composeApp/src/commonTest/kotlin/dev/ulfrx/recipe/navigation/NavigationTest.kt"
decisions:
- "Used Icons.AutoMirrored.Outlined.MenuBook (deprecation warning was fatal under -Werror)"
- "TabHomePlaceholder uses BasicText from compose-foundation — avoids Material 1/3"
- "NavigationTest uses navOptions{} DSL with public shouldXxx() accessors; fake-builder fallback was not needed"
metrics:
duration: ~6m
completed: 2026-05-08
---
# Phase 02.1 Plan 04: Navigation Foundation Summary
Type-safe navigation skeleton with 4 nested tab graphs (Planner/Recipes/Pantry/Shopping), a `BottomBarDestination` enum exposing routes/labels/icons/search visibility, and a `navigateToTab` extension that enforces the multi-back-stack four-flag contract — verified by 3 unit tests.
## What Was Built
- **Routes.kt** — 8 `@Serializable data object` types: PlannerGraph/PlannerHome, RecipesGraph/RecipesHome, PantryGraph/PantryHome, ShoppingGraph/ShoppingHome.
- **BottomBarDestination.kt** — enum in D-03 order (Planner first as `Default`); only Recipes + Pantry have `hasSearch=true`/non-null `searchPlaceholder`. Bound to `Icons.Outlined.{CalendarMonth,Inventory2,ShoppingCart}` and `Icons.AutoMirrored.Outlined.MenuBook`.
- **RootNavHost.kt** — single root `NavHost(startDestination = PlannerGraph)` containing four `navigation<*Graph>(startDestination = *Home)` blocks. Each `composable<*Home>` retrieves the parent graph's `NavBackStackEntry` via `navController.getBackStackEntry(*Graph)` (Pattern 2 wired and ready for plan 02.1-08 to consume with `koinViewModel(viewModelStoreOwner = parent)`). Renders private `TabHomePlaceholder` using `BasicText` — no Material dependency.
- **NavExtensions.kt** — `fun NavHostController.navigateToTab(graphRoute: Any)` applies `popUpTo(graph.findStartDestination().id){saveState=true}`, `launchSingleTop = true`, `restoreState = true`.
- **strings.xml** — 9 new keys appended (4 tab labels + 2 search placeholders + 3 search a11y), Polish copy verbatim from UI-SPEC. All 7 existing `auth_*` keys preserved.
- **NavigationTest.kt** — `@Ignore` removed; 3 tests assert the four-flag contract via the public `navOptions { ... }` DSL and `shouldLaunchSingleTop()` / `shouldRestoreState()` / `shouldPopUpToSaveState()` accessors.
## Verification
- `./gradlew :composeApp:compileKotlinIosSimulatorArm64 -q` → exit 0
- `./gradlew :composeApp:iosSimulatorArm64Test --tests "dev.ulfrx.recipe.navigation.NavigationTest"` → BUILD SUCCESSFUL (3 tests pass)
- `./gradlew :composeApp:linkDebugFrameworkIosSimulatorArm64 -q` → exit 0
- All acceptance grep counts match per task.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug] Deprecated `Icons.Outlined.MenuBook` failed -Werror compile**
- **Found during:** Task 1 verify
- **Issue:** `'val Icons.Outlined.MenuBook: ImageVector' is deprecated. Use the AutoMirrored version` — Werror promoted the warning to a build failure.
- **Fix:** Switched to `Icons.AutoMirrored.Outlined.MenuBook` and updated import.
- **Files modified:** `composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/navigation/BottomBarDestination.kt`
- **Commit:** 9b9029a (folded into Task 1 commit)
No other deviations. Plan executed as written.
## Open Questions Resolved
- **navOptions DSL availability under nav-compose 2.9.2 K/N:** Public `navOptions { ... }` builder and `shouldLaunchSingleTop()` / `shouldRestoreState()` / `shouldPopUpToSaveState()` accessors are all publicly exposed. The fake-builder fallback path described in the plan was not needed.
- **TabHomePlaceholder text strategy:** Settled on `androidx.compose.foundation.text.BasicText` — keeps the placeholder Material-free per UI-SPEC line 31. Plan 02.1-08 will replace with real `Tab*Screen` composables.
## Commits
- 9b9029a `feat(02.1-04): add type-safe routes and bottom bar destinations`
- 5634171 `feat(02.1-04): add RootNavHost and navigateToTab extension`
- 41d9bf4 `test(02.1-04): assert navigateToTab applies four-flag back-stack contract`
## Self-Check: PASSED
- FOUND: composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/navigation/Routes.kt
- FOUND: composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/navigation/BottomBarDestination.kt
- FOUND: composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/navigation/RootNavHost.kt
- FOUND: composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/navigation/NavExtensions.kt
- FOUND commit 9b9029a, 5634171, 41d9bf4