92 lines
6.1 KiB
Markdown
92 lines
6.1 KiB
Markdown
---
|
|
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
|