From 37729c13d864ffede118b6ddf8e07327f5907e6c Mon Sep 17 00:00:00 2001 From: James Rich Date: Thu, 26 Mar 2026 13:33:10 -0500 Subject: [PATCH] feat: upgrade to Navigation 3 Beta 01 and implement entry-scoped ViewModels - Update Navigation 3 to `1.1.0-beta01`, JetBrains Lifecycle to `2.11.0-alpha02`, and Compose Multiplatform to `1.11.0-beta01`. - Integrate `ViewModelStoreNavEntryDecorator` and `SaveableStateHolderNavEntryDecorator` into `NavDisplay` for both Android and Desktop shells. - Enable automatic ViewModel scoping where ViewModels obtained via `koinViewModel()` inside `entry` blocks are now tied to the backstack entry's lifetime and cleared on pop. - Add `jetbrains.lifecycle.viewmodel.navigation3` dependency to support entry-level `ViewModelStore` management. - Update `AGENTS.md`, `GEMINI.md`, and `copilot-instructions.md` to reflect the transition from Activity/Window-scoped ViewModels to entry-scoped lifecycles. - Introduce `navigation3-api-alignment-2026-03.md` to document the audit of Navigation 3 Scene architecture and Material 3 Adaptive integration. - Update `kmp-status.md` and existing decision docs to reflect the new dependency baseline and predictive back handling via `NavigationBackHandler`. --- .github/copilot-instructions.md | 2 +- AGENTS.md | 2 +- GEMINI.md | 2 +- app/build.gradle.kts | 1 + .../main/kotlin/org/meshtastic/app/ui/Main.kt | 21 +++ .../desktop/ui/DesktopMainScreen.kt | 7 + .../navigation3-api-alignment-2026-03.md | 121 ++++++++++++++++++ docs/decisions/navigation3-parity-2026-03.md | 29 +++-- docs/kmp-status.md | 13 +- 9 files changed, 181 insertions(+), 17 deletions(-) create mode 100644 docs/decisions/navigation3-api-alignment-2026-03.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 8dea1e55c..d0200049f 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -79,7 +79,7 @@ Meshtastic-Android is a Kotlin Multiplatform (KMP) application for off-grid, dec - **KMP file naming:** In KMP modules, `commonMain` and platform source sets (`androidMain`, `jvmMain`) share the same package namespace. If both contain a file with the same name (e.g., `LogExporter.kt`), the Kotlin/JVM compiler will produce a duplicate class error. Use distinct filenames: keep the `expect` declaration in `LogExporter.kt` and put shared helpers in a separate file like `LogFormatter.kt`. - **Concurrency:** Use Kotlin Coroutines and Flow. - **Dependency Injection:** Use **Koin Annotations** with the K2 compiler plugin (`koin-plugin` in version catalog). The `koin-annotations` library version is unified with `koin-core` (both use `version.ref = "koin"`). The `KoinConventionPlugin` uses the typed `KoinGradleExtension` to configure the K2 plugin (e.g., `compileSafety.set(false)`). Keep root graph assembly in `app`. -- **ViewModels:** Follow the MVI/UDF pattern. Use the multiplatform `androidx.lifecycle.ViewModel` in `commonMain`. +- **ViewModels:** Follow the MVI/UDF pattern. Use the multiplatform `androidx.lifecycle.ViewModel` in `commonMain`. Both `app` and `desktop` pass `ViewModelStoreNavEntryDecorator` to `NavDisplay`, so ViewModels obtained via `koinViewModel()` inside `entry` blocks are scoped to the entry's backstack lifetime and cleared on pop. - **BLE:** All Bluetooth communication must route through `core:ble` using Kable. - **Networking:** Pure **Ktor** — no OkHttp anywhere. Engines: `ktor-client-android` for Android, `ktor-client-java` for desktop/JVM. Use Ktor `Logging` plugin for HTTP debug logging (not OkHttp interceptors). `HttpClient` is provided via Koin in `app/di/NetworkModule` and `core:network/di/CoreNetworkAndroidModule`. - **Image Loading (Coil):** Use `coil-network-ktor3` with `KtorNetworkFetcherFactory` on **all** platforms. `ImageLoader` is configured in host modules only (`app` via Koin `@Single`, `desktop` via `setSingletonImageLoaderFactory`). Feature modules depend only on `libs.coil` (coil-compose) for `AsyncImage` — never add `coil-network-*` or `coil-svg` to feature modules. diff --git a/AGENTS.md b/AGENTS.md index 791689062..24815bac4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -81,7 +81,7 @@ Meshtastic-Android is a Kotlin Multiplatform (KMP) application for off-grid, dec - **Feature navigation graphs:** Feature modules export Navigation 3 graph functions as extension functions on `EntryProviderScope` in `commonMain` (e.g., `fun EntryProviderScope.settingsGraph(backStack: NavBackStack)`). Host shells (`app`, `desktop`) assemble these into a single `entryProvider` block. Do NOT define navigation graphs in platform-specific source sets. - **Concurrency:** Use Kotlin Coroutines and Flow. - **Dependency Injection:** Use **Koin Annotations** with the K2 compiler plugin (`koin-plugin` in version catalog). The `koin-annotations` library version is unified with `koin-core` (both use `version.ref = "koin"`). The `KoinConventionPlugin` uses the typed `KoinGradleExtension` to configure the K2 plugin (e.g., `compileSafety.set(false)`). Keep root graph assembly in `app`. -- **ViewModels:** Follow the MVI/UDF pattern. Use the multiplatform `androidx.lifecycle.ViewModel` in `commonMain`. +- **ViewModels:** Follow the MVI/UDF pattern. Use the multiplatform `androidx.lifecycle.ViewModel` in `commonMain`. Both `app` and `desktop` pass `ViewModelStoreNavEntryDecorator` to `NavDisplay`, so ViewModels obtained via `koinViewModel()` inside `entry` blocks are scoped to the entry's backstack lifetime and cleared on pop. - **BLE:** All Bluetooth communication must route through `core:ble` using Kable. - **Networking:** Pure **Ktor** — no OkHttp anywhere. Engines: `ktor-client-android` for Android, `ktor-client-java` for desktop/JVM. Use Ktor `Logging` plugin for HTTP debug logging (not OkHttp interceptors). `HttpClient` is provided via Koin in `app/di/NetworkModule` and `core:network/di/CoreNetworkAndroidModule`. - **Image Loading (Coil):** Use `coil-network-ktor3` with `KtorNetworkFetcherFactory` on **all** platforms. `ImageLoader` is configured in host modules only (`app` via Koin `@Single`, `desktop` via `setSingletonImageLoaderFactory`). Feature modules depend only on `libs.coil` (coil-compose) for `AsyncImage` — never add `coil-network-*` or `coil-svg` to feature modules. diff --git a/GEMINI.md b/GEMINI.md index 2dede594d..ef91358c2 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -79,7 +79,7 @@ Meshtastic-Android is a Kotlin Multiplatform (KMP) application for off-grid, dec - **KMP file naming:** In KMP modules, `commonMain` and platform source sets (`androidMain`, `jvmMain`) share the same package namespace. If both contain a file with the same name (e.g., `LogExporter.kt`), the Kotlin/JVM compiler will produce a duplicate class error. Use distinct filenames: keep the `expect` declaration in `LogExporter.kt` and put shared helpers in a separate file like `LogFormatter.kt`. - **Concurrency:** Use Kotlin Coroutines and Flow. - **Dependency Injection:** Use **Koin Annotations** with the K2 compiler plugin (`koin-plugin` in version catalog). The `koin-annotations` library version is unified with `koin-core` (both use `version.ref = "koin"`). The `KoinConventionPlugin` uses the typed `KoinGradleExtension` to configure the K2 plugin (e.g., `compileSafety.set(false)`). Keep root graph assembly in `app`. -- **ViewModels:** Follow the MVI/UDF pattern. Use the multiplatform `androidx.lifecycle.ViewModel` in `commonMain`. +- **ViewModels:** Follow the MVI/UDF pattern. Use the multiplatform `androidx.lifecycle.ViewModel` in `commonMain`. Both `app` and `desktop` pass `ViewModelStoreNavEntryDecorator` to `NavDisplay`, so ViewModels obtained via `koinViewModel()` inside `entry` blocks are scoped to the entry's backstack lifetime and cleared on pop. - **BLE:** All Bluetooth communication must route through `core:ble` using Kable. - **Dependencies:** Check `gradle/libs.versions.toml` before assuming a library is available. - **JetBrains fork aliases:** Version catalog aliases for JetBrains-forked AndroidX artifacts use the `jetbrains-*` prefix (e.g., `jetbrains-lifecycle-runtime-compose`, `jetbrains-navigation3-ui`). Plain `androidx-*` aliases are true Google AndroidX artifacts. Never mix them up in `commonMain`. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 752b2be0b..0aa13896b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -250,6 +250,7 @@ dependencies { implementation(libs.androidx.lifecycle.process) implementation(libs.jetbrains.lifecycle.viewmodel.compose) implementation(libs.jetbrains.lifecycle.runtime.compose) + implementation(libs.jetbrains.lifecycle.viewmodel.navigation3) implementation(libs.jetbrains.navigation3.ui) implementation(libs.androidx.paging.compose) implementation(libs.ktor.client.android) diff --git a/app/src/main/kotlin/org/meshtastic/app/ui/Main.kt b/app/src/main/kotlin/org/meshtastic/app/ui/Main.kt index 5753d316a..5c46dbde2 100644 --- a/app/src/main/kotlin/org/meshtastic/app/ui/Main.kt +++ b/app/src/main/kotlin/org/meshtastic/app/ui/Main.kt @@ -26,10 +26,16 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveableStateHolder import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner +import androidx.lifecycle.viewmodel.navigation3.ViewModelStoreNavEntryDecorator +import androidx.lifecycle.viewmodel.navigation3.ViewModelStoreNavEntryDecoratorDefaults import androidx.navigation3.runtime.NavKey +import androidx.navigation3.runtime.SaveableStateHolderNavEntryDecorator import androidx.navigation3.runtime.entryProvider import androidx.navigation3.runtime.rememberNavBackStack import androidx.navigation3.ui.NavDisplay @@ -84,9 +90,24 @@ fun MainScreen(uIViewModel: UIViewModel = koinViewModel()) { settingsGraph(backStack) firmwareGraph(backStack) } + val saveableStateHolder = rememberSaveableStateHolder() + val viewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) + val removeOnPop = ViewModelStoreNavEntryDecoratorDefaults.removeViewModelStoreOnPop() NavDisplay( backStack = backStack, entryProvider = provider, + entryDecorators = + listOf( + remember(saveableStateHolder) { + SaveableStateHolderNavEntryDecorator(saveableStateHolder) + }, + remember(viewModelStoreOwner) { + ViewModelStoreNavEntryDecorator( + viewModelStore = viewModelStoreOwner.viewModelStore, + removeViewModelStoreOnPop = removeOnPop, + ) + }, + ), modifier = Modifier.fillMaxSize().recalculateWindowInsets().safeDrawingPadding(), ) } diff --git a/desktop/src/main/kotlin/org/meshtastic/desktop/ui/DesktopMainScreen.kt b/desktop/src/main/kotlin/org/meshtastic/desktop/ui/DesktopMainScreen.kt index 082512ac4..6dcf90e8a 100644 --- a/desktop/src/main/kotlin/org/meshtastic/desktop/ui/DesktopMainScreen.kt +++ b/desktop/src/main/kotlin/org/meshtastic/desktop/ui/DesktopMainScreen.kt @@ -24,9 +24,11 @@ import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator import androidx.navigation3.runtime.NavBackStack import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.entryProvider +import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator import androidx.navigation3.ui.NavDisplay import org.koin.compose.viewmodel.koinViewModel import org.meshtastic.core.ui.component.MeshtasticAppShell @@ -57,6 +59,11 @@ fun DesktopMainScreen(backStack: NavBackStack, uiViewModel: UIViewModel NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, + entryDecorators = + listOf( + rememberSaveableStateHolderNavEntryDecorator(), + rememberViewModelStoreNavEntryDecorator(), + ), entryProvider = provider, modifier = Modifier.fillMaxSize(), ) diff --git a/docs/decisions/navigation3-api-alignment-2026-03.md b/docs/decisions/navigation3-api-alignment-2026-03.md new file mode 100644 index 000000000..4c71be572 --- /dev/null +++ b/docs/decisions/navigation3-api-alignment-2026-03.md @@ -0,0 +1,121 @@ + + +# Navigation 3 & Material 3 Adaptive — API Alignment Audit + +**Date:** 2026-03-26 +**Status:** Active +**Scope:** Adoption of Navigation 3 `1.1.0-beta01` Scene APIs, transition metadata, ViewModel scoping, and Material 3 Adaptive integration. +**Supersedes:** [`navigation3-parity-2026-03.md`](navigation3-parity-2026-03.md) Alpha04 Changelog section (versions updated). + +## Current Dependency Baseline + +| Library | Version | Group | +|---|---|---| +| Navigation 3 UI | `1.1.0-beta01` | `org.jetbrains.androidx.navigation3:navigation3-ui` | +| Navigation Event | `1.1.0-alpha01` | `org.jetbrains.androidx.navigationevent:navigationevent-compose` | +| Lifecycle ViewModel Navigation3 | `2.11.0-alpha02` | `org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-navigation3` | +| Material 3 Adaptive | `1.3.0-alpha06` | `org.jetbrains.compose.material3.adaptive:adaptive*` | +| Material 3 Adaptive Navigation Suite | `1.11.0-alpha05` | `org.jetbrains.compose.material3:material3-adaptive-navigation-suite` | +| Compose Multiplatform | `1.11.0-beta01` | `org.jetbrains.compose` | +| Compose Multiplatform Material 3 | `1.11.0-alpha05` | `org.jetbrains.compose.material3:material3` | + +## API Audit: What's Available vs. What We Use + +### 1. NavDisplay — Scene Architecture (available since `1.1.0-alpha04`, stable in `beta01`) + +**Available APIs we're NOT using:** + +| API | Purpose | Status in project | +|---|---|---| +| `sceneStrategies: List>` | Allows NavDisplay to render multi-pane Scenes | ❌ Not used — defaulting to `SinglePaneSceneStrategy` | +| `SceneStrategy` interface | Custom scene calculation from backstack entries | ❌ Not used | +| `DialogSceneStrategy` | Renders `entry(metadata = dialog())` entries as overlay Dialogs | ❌ Not used — dialogs handled manually | +| `SceneDecoratorStrategy` | Wraps/decorates scenes with additional UI | ❌ Not used | +| `NavEntry.metadata` | Attaches typed metadata to entries (transitions, dialog hints, Scene classification) | ❌ Not used | +| `NavDisplay.TransitionKey` / `PopTransitionKey` / `PredictivePopTransitionKey` | Per-entry custom transitions via metadata | ❌ Not used | +| `transitionSpec` / `popTransitionSpec` / `predictivePopTransitionSpec` params | Default transition animations for NavDisplay | ❌ Not used — no transitions at all | +| `sharedTransitionScope: SharedTransitionScope?` | Shared element transitions between scenes | ❌ Not used | +| `entryDecorators: List>` | Wraps entry content with additional behavior | ❌ Not used (defaulting to `SaveableStateHolderNavEntryDecorator`) | + +**APIs we ARE using correctly:** + +| API | Usage | +|---|---| +| `NavDisplay(backStack, entryProvider, modifier)` | Both `app/Main.kt` and `desktop/DesktopMainScreen.kt` | +| `rememberNavBackStack(SavedStateConfiguration, startKey)` | Backstack persistence | +| `entryProvider { entry { ... } }` | All feature graph registrations | +| `NavigationBackHandler` from `navigationevent-compose` | Used in `AdaptiveListDetailScaffold` | + +### 2. ViewModel Scoping (`lifecycle-viewmodel-navigation3` `2.11.0-alpha02`) + +**Key finding:** The `ViewModelStoreNavEntryDecorator` is available and provides automatic per-entry ViewModel scoping tied to backstack lifetime. The project declares this dependency in `desktop/build.gradle.kts` but does **not** pass it as an `entryDecorator` to `NavDisplay`. + +Currently, `koinViewModel()` calls inside `entry` blocks use the nearest `ViewModelStoreOwner` from the composition — which is the Activity/Window level. This means: +- ViewModels are **not** automatically cleared when their entry is popped from the backstack. +- The project works around this with manual `key = "metrics-$destNum"` parameter keying. + +**Opportunity:** Adding `rememberViewModelStoreNavEntryDecorator()` to `NavDisplay.entryDecorators` would give each backstack entry its own `ViewModelStoreOwner`, so `koinViewModel()` calls would be automatically scoped to the entry's lifetime. + +### 3. Material 3 Adaptive — Nav3 Scene Integration + +**Key finding:** The JetBrains `adaptive-navigation` artifact at `1.3.0-alpha06` does **NOT** include `MaterialListDetailSceneStrategy`. That API only exists in the Google AndroidX version (`androidx.compose.material3.adaptive:adaptive-navigation:1.3.0-alpha09+`). + +This means the project **cannot** currently use the official M3 Adaptive Scene bridge through `NavDisplay(sceneStrategies = ...)`. The current approach of hosting `ListDetailPaneScaffold` inside `entry` blocks (via `AdaptiveListDetailScaffold`) is the correct pattern for the JetBrains fork at this version. + +**When to revisit:** Monitor the JetBrains adaptive fork for `MaterialListDetailSceneStrategy` inclusion. It will likely arrive when the JetBrains fork catches up to the AndroidX `1.3.0-alpha09+` feature set. + +### 4. NavigationSuiteScaffold (`1.11.0-alpha05`) + +**Status:** ✅ Adopted (2026-03-26). `MeshtasticNavigationSuite` now uses `NavigationSuiteScaffold` with `calculateFromAdaptiveInfo()` and custom `NavigationSuiteType` coercion. No further alignment needed. + +## Prioritized Opportunities + +### P0: Add `ViewModelStoreNavEntryDecorator` to NavDisplay (high-value, low-risk) + +Gives each backstack entry its own ViewModel scope. ViewModels are automatically cleared when their entry is popped. This is the primary intended usage of `lifecycle-viewmodel-navigation3`. + +**Impact:** Fixes subtle ViewModel leaks where popped entries retain their ViewModel in the Activity/Window store. Eliminates the need for manual `key = "metrics-$destNum"` ViewModel keying patterns over time. + +**Files:** `app/Main.kt`, `desktop/DesktopMainScreen.kt`, `core/ui/build.gradle.kts` (dependency). + +### P1: Add default NavDisplay transitions (medium-value, low-risk) + +Currently there are zero animations when navigating between entries. The `NavDisplay` supports `transitionSpec`, `popTransitionSpec`, and `predictivePopTransitionSpec` parameters for default transitions (slide, fade, etc.). + +**Impact:** Immediate UX improvement on both Android and Desktop with ~10 lines of code. + +**Files:** `app/Main.kt`, `desktop/DesktopMainScreen.kt` (or a shared composable wrapper in `core:ui`). + +### P2: Adopt `DialogSceneStrategy` for navigation-driven dialogs (medium-value, medium-risk) + +Routes that render as dialogs (e.g., confirmation dialogs, share sheet) can use `entry(metadata = DialogSceneStrategy.dialog()) { ... }` instead of manual `Dialog` composable wrapping. This keeps them on the backstack with proper predictive-back support. + +**Impact:** Cleaner dialog lifecycle management. Currently low urgency since most dialogs use `AlertHost`. + +### P3: Per-entry transition metadata (low-value until Scene adoption) + +Individual entries can declare custom transitions via `entry(metadata = NavDisplay.transitionSpec { ... })`. This is most useful when different route types should animate differently (e.g., detail screens slide in, settings screens fade). + +**Impact:** Polish improvement. Low priority until default transitions (P1) are established. + +### Deferred: Scene-based multi-pane layout + +The `MaterialListDetailSceneStrategy` is not available in the JetBrains adaptive fork at `1.3.0-alpha06`. The project's `AdaptiveListDetailScaffold` wrapper is the correct approach for now. Revisit when the JetBrains fork includes the Scene bridge, or consider writing a custom `SceneStrategy` that integrates with the existing `ListDetailPaneScaffold`. + +## Decision + +Adopt **P0** (ViewModel scoping) and **P1** (default transitions) now. Defer P2/P3 and Scene-based multi-pane until the JetBrains adaptive fork adds `MaterialListDetailSceneStrategy`. + +## References + +- Navigation 3 source: `navigation3-ui` `1.1.0-beta01` (inspected from Gradle cache) +- [`NavDisplay.kt`](https://cs.android.com/androidx/platform/frameworks/support/+/main:navigation3/navigation3-ui/src/commonMain/kotlin/androidx/navigation3/ui/NavDisplay.kt) (upstream) +- [`SceneStrategy.kt`](https://cs.android.com/androidx/platform/frameworks/support/+/main:navigation3/navigation3-ui/src/commonMain/kotlin/androidx/navigation3/scene/SceneStrategy.kt) (upstream) +- Material 3 Adaptive JetBrains fork: `org.jetbrains.compose.material3.adaptive` `1.3.0-alpha06` diff --git a/docs/decisions/navigation3-parity-2026-03.md b/docs/decisions/navigation3-parity-2026-03.md index a314af54d..c5633a6ee 100644 --- a/docs/decisions/navigation3-parity-2026-03.md +++ b/docs/decisions/navigation3-parity-2026-03.md @@ -36,19 +36,28 @@ Both modules still define separate graph-builder files (`app/navigation/*.kt`, ` 4. **Predictive back handling is KMP native.** - Custom `PredictiveBackHandler` wrapper was removed in favor of Jetpack's official KMP `NavigationBackHandler` from `androidx.navigationevent:navigationevent-compose`. -## Alpha04 Changelog Impact Check (2026-03-13) +## Alpha04 → Beta01 Changelog Impact Check -Source reviewed: Compose Multiplatform `v1.11.0-alpha04` release notes. +Source reviewed: Navigation 3 `1.1.0-beta01` (JetBrains fork), CMP `1.11.0-beta01`, Lifecycle `2.11.0-alpha02`. -1. **No direct Navigation 3 API breakage called out.** - - Release notes include component version bumps for Navigation 3 (`1.1.0-alpha04`) but no `NavBackStack`, `NavDisplay`, or `entryProvider` API migration requirements. - - Existing shell patterns in `app` and `desktop` remain valid. -2. **Primary risk is dependency wiring drift, not runtime behavior.** +> **Superseded by:** [`navigation3-api-alignment-2026-03.md`](navigation3-api-alignment-2026-03.md) for the full API surface audit and Scene architecture adoption plan. + +1. **NavDisplay API updated to Scene-based architecture.** + - The `sceneStrategy: SceneStrategy` parameter is deprecated in favor of `sceneStrategies: List>`. + - New `sceneDecoratorStrategies: List>` parameter available. + - New `sharedTransitionScope: SharedTransitionScope?` parameter for shared element transitions. + - Existing shell patterns in `app` and `desktop` remain valid using the default `SinglePaneSceneStrategy`. +2. **Entry-scoped ViewModel lifecycle adopted.** + - Both `app` and `desktop` now pass `ViewModelStoreNavEntryDecorator` + `SaveableStateHolderNavEntryDecorator` as explicit `entryDecorators` to `NavDisplay`. + - ViewModels obtained via `koinViewModel()` inside `entry` blocks are now scoped to the entry's backstack lifetime. +3. **No direct Navigation 3 API breakage.** + - Release is beta (API stabilized). No migration from alpha04 was required for existing usage patterns. +4. **Primary risk is dependency wiring drift, not runtime behavior.** - JetBrains Navigation 3 currently publishes `navigation3-ui` coordinates (no separate `navigation3-runtime` artifact in Maven Central). The `jetbrains-navigation3-runtime` alias intentionally points to `navigation3-ui` and is documented in the version catalog. -3. **Saved-state and typed-route parity risk remains unchanged.** - - Desktop still uses manual serializer registration; this is an existing risk and not introduced by alpha04. -4. **Compose-wide migration notes do not currently impact navigation codepaths.** - - `Shader` wrapper changes and `Canvas.nativeCanvas` deprecations are not used in the Navigation 3 shell files. + - Note: The `remember*` composable factory functions from `navigation3-runtime` are not visible in non-KMP Android modules due to Kotlin metadata resolution. Use direct class constructors instead (as done in `app/Main.kt`). +5. **Saved-state and typed-route parity risk remains unchanged.** + - Desktop still uses manual serializer registration; this is an existing risk and not introduced by beta01. +6. **Updated active docs to reflect the current dependency baseline (`1.11.0-beta01`, `1.1.0-beta01`, `1.3.0-alpha06`, `2.11.0-alpha02`).** ### Actions Taken diff --git a/docs/kmp-status.md b/docs/kmp-status.md index 8f3db2fc5..470d8e565 100644 --- a/docs/kmp-status.md +++ b/docs/kmp-status.md @@ -155,14 +155,19 @@ Remaining to be extracted from `:app` or unified in `commonMain`: | Dependency | Version | Why | |---|---|---| -| Compose Multiplatform | `1.11.0-alpha04` | Required for JetBrains Adaptive `1.3.0-alpha06` | -| Koin | `4.2.0-RC2` | Nav3 + K2 compiler plugin support | -| JetBrains Lifecycle | `2.10.0-beta01` | Multiplatform ViewModel/lifecycle | -| JetBrains Navigation 3 | `1.1.0-alpha04` | Multiplatform navigation | +| Compose Multiplatform | `1.11.0-beta01` | Required for JetBrains Adaptive `1.3.0-alpha06` and Material 3 `1.11.0-alpha05` | +| Compose Multiplatform Material 3 | `1.11.0-alpha05` | Material 3 components including `NavigationSuiteScaffold` | +| Koin | `4.2.0` | Nav3 + K2 compiler plugin support | +| JetBrains Lifecycle | `2.11.0-alpha02` | Multiplatform ViewModel/lifecycle; includes `lifecycle-viewmodel-navigation3` for entry-scoped ViewModels | +| JetBrains Navigation 3 | `1.1.0-beta01` | Multiplatform navigation with Scene architecture, `NavEntry.metadata`, transition specs | +| JetBrains Navigation Event | `1.1.0-alpha01` | KMP `NavigationBackHandler` for predictive back | +| JetBrains Material 3 Adaptive | `1.3.0-alpha06` | `ListDetailPaneScaffold`, `ThreePaneScaffold`, Large/XL breakpoints | | Kable BLE | `0.42.0` | Provides fully multiplatform BLE support | **Policy:** Stable by default. RC when it unlocks KMP functionality. Alpha only behind hard abstraction seams. Do not downgrade CMP or Koin — they enable critical KMP features. +> See [`decisions/navigation3-api-alignment-2026-03.md`](./decisions/navigation3-api-alignment-2026-03.md) for the full Navigation 3 API surface audit and Scene architecture adoption plan. + ## References - Roadmap: [`docs/roadmap.md`](./roadmap.md)