mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
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<T>` 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`.
This commit is contained in:
parent
a5f72734ed
commit
37729c13d8
9 changed files with 181 additions and 17 deletions
2
.github/copilot-instructions.md
vendored
2
.github/copilot-instructions.md
vendored
|
|
@ -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<T>` 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.
|
||||
|
|
|
|||
|
|
@ -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<NavKey>` in `commonMain` (e.g., `fun EntryProviderScope<NavKey>.settingsGraph(backStack: NavBackStack<NavKey>)`). Host shells (`app`, `desktop`) assemble these into a single `entryProvider<NavKey>` 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<T>` 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.
|
||||
|
|
|
|||
|
|
@ -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<T>` 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`.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<NavKey>(saveableStateHolder)
|
||||
},
|
||||
remember(viewModelStoreOwner) {
|
||||
ViewModelStoreNavEntryDecorator<NavKey>(
|
||||
viewModelStore = viewModelStoreOwner.viewModelStore,
|
||||
removeViewModelStoreOnPop = removeOnPop,
|
||||
)
|
||||
},
|
||||
),
|
||||
modifier = Modifier.fillMaxSize().recalculateWindowInsets().safeDrawingPadding(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<NavKey>, uiViewModel: UIViewModel
|
|||
NavDisplay(
|
||||
backStack = backStack,
|
||||
onBack = { backStack.removeLastOrNull() },
|
||||
entryDecorators =
|
||||
listOf(
|
||||
rememberSaveableStateHolderNavEntryDecorator<NavKey>(),
|
||||
rememberViewModelStoreNavEntryDecorator<NavKey>(),
|
||||
),
|
||||
entryProvider = provider,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
|
|
|
|||
121
docs/decisions/navigation3-api-alignment-2026-03.md
Normal file
121
docs/decisions/navigation3-api-alignment-2026-03.md
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
<!--
|
||||
- Copyright (c) 2026 Meshtastic LLC
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-->
|
||||
|
||||
# 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<SceneStrategy<T>>` | Allows NavDisplay to render multi-pane Scenes | ❌ Not used — defaulting to `SinglePaneSceneStrategy` |
|
||||
| `SceneStrategy<T>` interface | Custom scene calculation from backstack entries | ❌ Not used |
|
||||
| `DialogSceneStrategy` | Renders `entry<T>(metadata = dialog())` entries as overlay Dialogs | ❌ Not used — dialogs handled manually |
|
||||
| `SceneDecoratorStrategy<T>` | 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<NavEntryDecorator<T>>` | 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<NavKey> { entry<T> { ... } }` | 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<T>` 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<T>` 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<T>(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<T>(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`
|
||||
|
|
@ -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<T>` parameter is deprecated in favor of `sceneStrategies: List<SceneStrategy<T>>`.
|
||||
- New `sceneDecoratorStrategies: List<SceneDecoratorStrategy<T>>` 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<T>` 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue