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:
James Rich 2026-03-26 13:33:10 -05:00
parent a5f72734ed
commit 37729c13d8
9 changed files with 181 additions and 17 deletions

View file

@ -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.