mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
docs: remove agent cruft, condense and validate remaining docs (#5110)
This commit is contained in:
parent
75e2177da7
commit
8a06157ff4
21 changed files with 30 additions and 1150 deletions
|
|
@ -1,15 +0,0 @@
|
|||
# Decision Records
|
||||
|
||||
Architectural decision records and reviews. Each captures context, decision, and consequences.
|
||||
|
||||
| Decision | File | Status |
|
||||
|---|---|---|
|
||||
| Architecture review (March 2026) | [`architecture-review-2026-03.md`](./architecture-review-2026-03.md) | Active |
|
||||
| Navigation 3 parity strategy (Android + Desktop) | [`navigation3-parity-2026-03.md`](./navigation3-parity-2026-03.md) | Active |
|
||||
| Navigation 3 API alignment audit | [`navigation3-api-alignment-2026-03.md`](./navigation3-api-alignment-2026-03.md) | Active |
|
||||
| BLE KMP strategy (Kable) | [`ble-strategy.md`](./ble-strategy.md) | Decided |
|
||||
| Hilt → Koin migration | [`koin-migration.md`](./koin-migration.md) | Complete |
|
||||
| Testing consolidation (`core:testing`) | [`testing-consolidation-2026-03.md`](./testing-consolidation-2026-03.md) | Complete |
|
||||
|
||||
For the current KMP migration status, see [`docs/kmp-status.md`](../kmp-status.md).
|
||||
For the forward-looking roadmap, see [`docs/roadmap.md`](../roadmap.md).
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
# Architecture Review — March 2026
|
||||
|
||||
> Status: **Active**
|
||||
> Last updated: 2026-03-31
|
||||
|
||||
Re-evaluation of project modularity and architecture against modern KMP and Android best practices. Identifies gaps and actionable improvements across modularity, reusability, clean abstractions, DI, and testing.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The codebase is **~98% structurally KMP** — 18/20 core modules and 8/8 feature modules declare `jvm()` targets and cross-compile in CI. Shared `commonMain` code accounts for ~52K LOC vs ~18K platform-specific LOC (a 74/26 split). This is strong.
|
||||
|
||||
Of the five structural gaps originally identified, four are resolved and one remains in progress:
|
||||
|
||||
1. **`app` is a God module** — originally 90 files / ~11K LOC of transport, service, UI, and ViewModel code that should live in core/feature modules. *(✅ Resolved — app module reduced to 8 files: `MainActivity`, `MeshUtilApplication`, Nav shell, DI config, and shared map UI components)*
|
||||
2. ~~**Radio transport layer is app-locked**~~ — ✅ Resolved: `RadioTransport` interface in `core:repository/commonMain`; shared `StreamFrameCodec` + `TcpTransport` in `core:network`.
|
||||
3. ~~**`java.*` APIs leak into `commonMain`**~~ — ✅ Resolved: `Locale`, `ConcurrentHashMap`, `ReentrantLock` purged.
|
||||
4. ~~**Zero feature-level `commonTest`**~~ — ✅ Resolved: 193 shared tests across all 8 features; `core:testing` module established.
|
||||
5. ~~**No `feature:connections` module**~~ — ✅ Resolved: KMP module with shared UI and dynamic transport detection.
|
||||
|
||||
## Source Code Distribution
|
||||
|
||||
| Source set | Files | ~LOC | Purpose |
|
||||
|---|---:|---:|---|
|
||||
| `core/*/commonMain` | 337 | 32,700 | Shared business/data logic |
|
||||
| `feature/*/commonMain` | 146 | 19,700 | Shared feature UI + ViewModels |
|
||||
| `feature/*/androidMain` | 62 | 14,700 | Platform UI (charts, previews, permissions) |
|
||||
| `app/src/main` | 8 | ~450 | Android app shell + shared map UI components |
|
||||
| `desktop/src` | 26 | 4,800 | Desktop app shell |
|
||||
| `core/*/androidMain` | 49 | 3,500 | Platform implementations |
|
||||
| `core/*/jvmMain` | 11 | ~500 | JVM actuals |
|
||||
| `core/*/jvmAndroidMain` | 4 | ~200 | Shared JVM+Android code |
|
||||
|
||||
**Key ratio:** 74% of production code is in `commonMain` (shared). Goal: 85%+.
|
||||
|
||||
---
|
||||
|
||||
## A. Critical Modularity Gaps
|
||||
|
||||
### A1. `app` module is a God module
|
||||
|
||||
The `app` module should be a thin shell (~20 files): `MainActivity`, DI assembly, nav host, and shared flavor-agnostic UI. Originally it held **90 files / ~11K LOC**, now reduced to an **8-file shell** (6 original + 2 shared map UI components: `MapButton`, `MapControlsOverlay`):
|
||||
|
||||
| Area | Files | LOC | Where it should live |
|
||||
|---|---:|---:|---|
|
||||
| `repository/radio/` | 22 | ~2,000 | `core:service` / `core:network` |
|
||||
| `service/` | 12 | ~1,500 | Extracted to `core:service/androidMain` ✓ |
|
||||
| `navigation/` | ~1 | ~200 | Root Nav 3 host wiring stays in `app`. Feature graphs moved to `feature:*`. |
|
||||
| `settings/` ViewModels | 3 | ~350 | Thin Android wrappers (genuine platform deps) |
|
||||
| `widget/` | 4 | ~300 | Extracted to `feature:widget` ✓ |
|
||||
| `worker/` | 4 | ~350 | Extracted to `core:service/androidMain` and `feature:messaging/androidMain` ✓ |
|
||||
| DI + Application + MainActivity | 5 | ~500 | Stay in `app` ✓ |
|
||||
| UI screens + ViewModels | 5 | ~1,200 | Stay in `app` (Android-specific deps) |
|
||||
|
||||
**Progress:** Extracted `ChannelViewModel` → `feature:settings/commonMain`, `NodeMapViewModel` → `feature:map/commonMain`, `NodeContextMenu` → `feature:node/commonMain`, `EmptyDetailPlaceholder` → `core:ui/commonMain`. Remaining extractions require radio/service layer refactoring (bigger scope).
|
||||
|
||||
### A2. Radio interface layer is app-locked and non-KMP
|
||||
|
||||
The core transport abstraction was previously locked in `app/repository/radio/` via `IRadioInterface`. This has been successfully refactored:
|
||||
|
||||
1. Defined `RadioTransport` interface in `core:repository/commonMain` (replacing `IRadioInterface`)
|
||||
2. Moved `StreamFrameCodec`-based framing to `core:network/commonMain`
|
||||
3. Moved TCP transport to `core:network/jvmAndroidMain`
|
||||
4. BLE, Serial, and Mock transports now reside in `core:network` and implement `RadioTransport`.
|
||||
|
||||
**Recommended next steps:**
|
||||
1. Move BLE transport to `core:ble/androidMain`
|
||||
2. Move Serial/USB transport to `core:service/androidMain`
|
||||
|
||||
### A3. No `feature:connections` module *(resolved 2026-03-12)*
|
||||
|
||||
Device discovery UI was duplicated:
|
||||
- Android: `app/ui/connections/` (13 files: `ConnectionsScreen`, `ScannerViewModel`, 10 components)
|
||||
- Desktop: `desktop/ui/connections/DesktopConnectionsScreen.kt` (separate implementation)
|
||||
|
||||
**Outcome:** Created `feature:connections` KMP module with:
|
||||
- `commonMain`: `ScannerViewModel`, `ConnectionsScreen`, 11 shared UI components, `DeviceListEntry` sealed class, `GetDiscoveredDevicesUseCase` interface, `CommonGetDiscoveredDevicesUseCase` (TCP/recent devices)
|
||||
- `androidMain`: `AndroidScannerViewModel` (BLE bonding, USB permissions), `AndroidGetDiscoveredDevicesUseCase` (BLE/NSD/USB discovery), `NetworkRepository`, `UsbRepository`, `SerialConnection`
|
||||
- Desktop uses the shared `ConnectionsScreen` + `CommonGetDiscoveredDevicesUseCase` directly
|
||||
- Dynamic transport detection via `RadioInterfaceService.supportedDeviceTypes`
|
||||
- Module registered in both `AppKoinModule` and `DesktopKoinModule`
|
||||
|
||||
### A4. `core:api` AIDL coupling
|
||||
|
||||
`core:api` is Android-only (AIDL IPC). `ServiceClient` in `core:service/androidMain` wraps it. Desktop doesn't use it — it has `DirectRadioControllerImpl` in `core:service/commonMain`.
|
||||
|
||||
**Recommendation:** The `DirectRadioControllerImpl` pattern is correct. Ensure `RadioController` (already in `core:model/commonMain`) is the canonical interface; deprecate the AIDL-based path for in-process usage.
|
||||
|
||||
---
|
||||
|
||||
## B. KMP Platform Purity
|
||||
|
||||
### B1. `java.util.Locale` leaks in `commonMain` *(resolved 2026-03-11)*
|
||||
|
||||
| File | Usage |
|
||||
|---|---|
|
||||
| `core:data/.../TracerouteHandlerImpl.kt` | Replaced with `NumberFormatter.format(seconds, 1)` |
|
||||
| `core:data/.../NeighborInfoHandlerImpl.kt` | Replaced with `NumberFormatter.format(seconds, 1)` |
|
||||
| `core:prefs/.../MeshPrefsImpl.kt` | Replaced with locale-free `uppercase()` |
|
||||
|
||||
**Outcome:** The three `Locale` usages identified in March were removed from `commonMain`. Follow-up cleanup in the same sprint also moved `ReentrantLock`-based `SyncContinuation` to `jvmAndroidMain`, replaced prefs `ConcurrentHashMap` caches with atomic persistent maps, and pushed enum reflection behind `expect`/`actual` so no known `java.*` runtime calls remain in `commonMain`.
|
||||
|
||||
### B2. `ConcurrentHashMap` leaks in `commonMain` *(resolved 2026-03-11)*
|
||||
|
||||
Formerly found in 3 prefs files:
|
||||
- `core:prefs/.../MeshPrefsImpl.kt`
|
||||
- `core:prefs/.../UiPrefsImpl.kt`
|
||||
- `core:prefs/.../MapConsentPrefsImpl.kt`
|
||||
|
||||
**Outcome:** These caches now use `AtomicRef<PersistentMap<...>>` helpers in `commonMain`, eliminating the last `ConcurrentHashMap` usage from shared prefs code.
|
||||
|
||||
### B3. MQTT (Resolved)
|
||||
|
||||
`MQTTRepositoryImpl` has been migrated to `commonMain` using KMQTT, replacing Eclipse Paho.
|
||||
|
||||
**Fix:** Completed.
|
||||
- `kmqtt` library integrated for full KMP support.
|
||||
|
||||
### B4. Vico charts *(resolved)*
|
||||
|
||||
Vico chart screens (DeviceMetrics, EnvironmentMetrics, SignalMetrics, PowerMetrics, PaxMetrics) have been migrated to `feature:node/commonMain` using Vico's KMP artifacts (`vico-compose`, `vico-compose-m3`). Desktop wires them via shared composables. No Android-only chart code remains.
|
||||
|
||||
### B5. Cross-platform code deduplication *(resolved 2026-03-21)*
|
||||
|
||||
Comprehensive audit of `androidMain` vs `jvmMain` duplication across all feature modules. Extracted shared components:
|
||||
|
||||
| Component | Module | Eliminated from |
|
||||
|---|---|---|
|
||||
| `AlertHost` composable | `core:ui/commonMain` | Android `Main.kt`, Desktop `DesktopMainScreen.kt` |
|
||||
| `SharedDialogs` composable | `core:ui/commonMain` | Android `Main.kt`, Desktop `DesktopMainScreen.kt` |
|
||||
| `PlaceholderScreen` composable | `core:ui/commonMain` | 4 copies: `desktop/navigation`, `feature:map/jvmMain`, `feature:node/jvmMain` (×2) |
|
||||
| `ThemePickerDialog` + `ThemeOption` | `feature:settings/commonMain` | Android `SettingsScreen.kt`, Desktop `DesktopSettingsScreen.kt` |
|
||||
| `formatLogsTo()` + `redactedKeys` | `feature:settings/commonMain` (`LogFormatter.kt`) | Android + Desktop `LogExporter.kt` actuals |
|
||||
| `handleNodeAction()` | `feature:node/commonMain` | Android `NodeDetailScreen.kt`, Desktop `NodeDetailScreens.kt` |
|
||||
| `findNodeByNameSuffix()` | `feature:connections/commonMain` | Android USB matcher, TCP recent device matcher |
|
||||
|
||||
Also fixed `Dispatchers.IO` usage in `StoreForwardPacketHandlerImpl` (would break iOS), removed dead `UIViewModel.currentAlert` property, and added `firebase-debug.log` to `.gitignore`.
|
||||
|
||||
---
|
||||
|
||||
## C. DI Improvements
|
||||
|
||||
### C1. ~~Desktop manual ViewModel wiring~~ *(resolved 2026-03-13)*
|
||||
|
||||
`DesktopKoinModule.kt` originally had ~120 lines of hand-written `viewModel { ... }` blocks. These have been successfully replaced by including Koin modules from `commonMain` generated via the Koin K2 Compiler Plugin for automatic wiring.
|
||||
|
||||
### C2. ~~Desktop stubs lack compile-time validation~~ *(resolved 2026-03-13)*
|
||||
|
||||
`desktopPlatformStubsModule()` previously had stubs that were only validated at runtime.
|
||||
|
||||
**Outcome:** Added `DesktopKoinTest.kt` using Koin's `verify()` API. This test validates the entire Desktop DI graph (including platform stubs and DataStores) during the build. Discovered and fixed missing stubs for `CompassHeadingProvider`, `PhoneLocationProvider`, and `MagneticFieldProvider`.
|
||||
|
||||
### C3. DI module naming convention
|
||||
|
||||
Android uses `@Module`-annotated classes (`CoreDataModule`, `CoreBleAndroidModule`). Desktop imports them as `CoreDataModule().coreDataModule()`. This works but the double-invocation pattern is non-obvious.
|
||||
|
||||
**Recommendation:** Document the pattern in AGENTS.md. Consider if Koin Annotations 2.x supports a simpler import syntax.
|
||||
|
||||
---
|
||||
|
||||
## D. Test Architecture
|
||||
|
||||
### D1. Zero `commonTest` in feature modules *(resolved 2026-03-12)*
|
||||
|
||||
| Module | `commonTest` | `test`/`androidUnitTest` |
|
||||
|---|---:|---:|
|
||||
| `feature:settings` | 33 | 20 |
|
||||
| `feature:node` | 24 | 9 |
|
||||
| `feature:messaging` | 21 | 5 |
|
||||
| `feature:connections` | 27 | 0 |
|
||||
| `feature:firmware` | 15 | 25 |
|
||||
| `feature:wifi-provision` | 62 | 0 |
|
||||
|
||||
**Outcome:** All 8 feature modules now have `commonTest` coverage (211 shared tests). Combined with 70 platform unit tests, feature modules have 281 tests total. All Compose UI tests have been migrated from `androidTest` to `commonTest` using CMP `runComposeUiTest`; instrumented test infrastructure has been removed from CI.
|
||||
|
||||
### D2. No shared test fixtures *(resolved 2026-03-12)*
|
||||
|
||||
`core:testing` module established with shared fakes (`FakeNodeRepository`, `FakeServiceRepository`, `FakeRadioController`, `FakePacketRepository`) and `TestDataFactory` builders. Used by all feature `commonTest` suites.
|
||||
|
||||
### D3. Core module test gaps
|
||||
|
||||
36 `commonTest` files exist but are concentrated in `core:domain` (22 files) and `core:data` (10 files). Limited or zero tests in:
|
||||
- `core:service` (has `ServiceRepositoryImpl`, `DirectRadioControllerImpl`, `MeshServiceOrchestrator`)
|
||||
- `core:network` (has `StreamFrameCodecTest` — 10 tests; `TcpTransport` untested)
|
||||
- `core:ble` (connection state machine)
|
||||
- `core:ui` (utility functions)
|
||||
|
||||
`core:prefs` now has 12 `commonTest` tests (3 files: `FilterPrefsTest`, `TakPrefsTest`, `NotificationPrefsTest`) migrated from `androidHostTest` using Okio + `PreferenceDataStoreFactory.createWithPath()` for KMP compatibility.
|
||||
|
||||
### D4. Desktop has 2 tests
|
||||
|
||||
`desktop/src/test/` contains `DesktopKoinTest.kt` and `DesktopTopLevelDestinationParityTest.kt`. Still needs:
|
||||
- Navigation graph coverage
|
||||
|
||||
---
|
||||
|
||||
## E. Module Extraction Priority
|
||||
|
||||
Ordered by impact × effort:
|
||||
|
||||
| Priority | Extraction | Impact | Effort | Enables |
|
||||
|---:|---|---|---|---|
|
||||
| 1 | ~~`java.*` purge from `commonMain` (B1, B2)~~ | High | Low | ~~iOS target declaration~~ ✅ Done |
|
||||
| 2 | Radio transport interfaces to `core:repository` (A2) | High | Medium | Transport unification |
|
||||
| 3 | `core:testing` shared fixtures (D2) | Medium | Low | Feature commonTest |
|
||||
| 4 | Feature `commonTest` (D1) | Medium | Medium | KMP test coverage |
|
||||
| 5 | `feature:connections` (A3) | High | Medium | ~~Desktop connections~~ ✅ Done |
|
||||
| 6 | Service/worker extraction from `app` (A1) | Medium | Medium | Thin app module |
|
||||
| 7 | ~~Desktop Koin auto-wiring (C1, C2)~~ | Medium | Low | ✅ Resolved 2026-03-13 |
|
||||
| 8 | MQTT KMP (B3) | Medium | High | Desktop/iOS MQTT |
|
||||
| 9 | KMP charts (B4) | Medium | High | Desktop metrics |
|
||||
| 10 | ~~iOS target declaration~~ | High | Low | ~~CI purity gate~~ ✅ Done |
|
||||
|
||||
---
|
||||
|
||||
## Scorecard Update
|
||||
|
||||
| Area | Previous | Current | Notes |
|
||||
|---|---:|---:|---|
|
||||
| Shared business/data logic | 8.5/10 | **9/10** | RadioTransport interface unified; all core layers shared |
|
||||
| Shared feature/UI logic | 9.5/10 | **9/10** | All 8 KMP features; connections unified; cross-platform deduplication complete |
|
||||
| Android decoupling | 8.5/10 | **9/10** | Connections, Navigation, Services, & Widgets extracted; GMS purged; app ~40->target 20 files |
|
||||
| Multi-target readiness | 8/10 | **9/10** | Full JVM; release-ready desktop; iOS simulator builds compiling successfully |
|
||||
| CI confidence | 8.5/10 | **9/10** | 26 modules validated; feature:connections + feature:wifi-provision + desktop in CI; native release installers |
|
||||
| DI portability | 7/10 | **8/10** | Koin annotations in commonMain; supportedDeviceTypes injected per platform |
|
||||
| Test maturity | — | **9/10** | Mokkery, Turbine, and Kotest integrated; property-based testing established; broad coverage across all 9 features |
|
||||
|
||||
---
|
||||
|
||||
## F. JVM/Desktop Database Lifecycle
|
||||
|
||||
Room KMP's `setAutoCloseTimeout` API is Android-only. On JVM/Desktop, once a Room database is built, its SQLite connections (5 per WAL-mode DB: 4 readers + 1 writer) remain open indefinitely until explicitly closed via `RoomDatabase.close()`.
|
||||
|
||||
### Problem
|
||||
|
||||
When a user switches between multiple mesh devices, the previous device's database remained open in the in-memory cache. Each idle database consumed ~32 MB (connection pool + prepared statement caches), leading to unbounded memory growth proportional to the number of devices ever connected in a session.
|
||||
|
||||
### Solution
|
||||
|
||||
`DatabaseManager.switchActiveDatabase()` now explicitly closes the previously active database via `closeCachedDatabase()` before activating the new one. The closed database is removed from the in-memory cache but its file is preserved, allowing transparent re-opening on next access.
|
||||
|
||||
Additional fixes applied:
|
||||
1. **Init-order bug**: `dbCache` was declared after `currentDb`, causing NPE during `stateIn`'s `initialValue` evaluation. Reordered to ensure `dbCache` is initialized first.
|
||||
2. **Corruption handlers**: `ReplaceFileCorruptionHandler` added to `createDatabaseDataStore()` on both JVM and Android, preventing DataStore corruption from crashing the app.
|
||||
3. **`desktopDataDir()` deduplication**: Made public in `core:database/jvmMain` and removed the duplicate from `DesktopPlatformModule`, establishing a single source of truth for the desktop data directory.
|
||||
4. **DataStore scope consolidation**: Replaced two separate `CoroutineScope` instances with a single shared `dataStoreScope` in `DesktopPlatformModule`.
|
||||
5. **Coil cache path**: Desktop `Main.kt` updated to use `desktopDataDir()` instead of hardcoded `user.home`.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- Current migration status: [`kmp-status.md`](./kmp-status.md)
|
||||
- Roadmap: [`roadmap.md`](./roadmap.md)
|
||||
- Agent guide: [`../AGENTS.md`](../AGENTS.md)
|
||||
- Decision records: [`decisions/`](./decisions/)
|
||||
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
<!--
|
||||
- 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 | ✅ Used — `DialogSceneStrategy`, `ListDetailSceneStrategy`, `SupportingPaneSceneStrategy`, `SinglePaneSceneStrategy` |
|
||||
| `SceneStrategy<T>` interface | Custom scene calculation from backstack entries | ✅ Used via built-in strategies |
|
||||
| `DialogSceneStrategy` | Renders `entry<T>(metadata = dialog())` entries as overlay Dialogs | ✅ Adopted |
|
||||
| `SceneDecoratorStrategy<T>` | Wraps/decorates scenes with additional UI | ❌ Not used |
|
||||
| `NavEntry.metadata` | Attaches typed metadata to entries (transitions, dialog hints, Scene classification) | ✅ Used — `ListDetailSceneStrategy.listPane()`, `.detailPane()`, `.extraPane()` |
|
||||
| `NavDisplay.TransitionKey` / `PopTransitionKey` / `PredictivePopTransitionKey` | Per-entry custom transitions via metadata | ❌ Not used |
|
||||
| `transitionSpec` / `popTransitionSpec` / `predictivePopTransitionSpec` params | Default transition animations for NavDisplay | ✅ Used — 350 ms crossfade |
|
||||
| `sharedTransitionScope: SharedTransitionScope?` | Shared element transitions between scenes | ❌ Not used |
|
||||
| `entryDecorators: List<NavEntryDecorator<T>>` | Wraps entry content with additional behavior | ✅ Used — `SaveableStateHolderNavEntryDecorator` + `ViewModelStoreNavEntryDecorator` |
|
||||
|
||||
**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 with `ListDetailSceneStrategy` |
|
||||
|
||||
### 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 passes it as an `entryDecorator` to `NavDisplay` via `MeshtasticNavDisplay` in `core:ui/commonMain`.
|
||||
|
||||
ViewModels obtained via `koinViewModel()` inside `entry<T>` blocks are scoped to the entry's backstack lifetime and automatically cleared when the entry is popped.
|
||||
|
||||
### 3. Material 3 Adaptive — Nav3 Scene Integration
|
||||
|
||||
**Key finding:** The JetBrains `adaptive-navigation3` artifact at `1.3.0-alpha06` includes `ListDetailSceneStrategy` and `SupportingPaneSceneStrategy`. The project uses both via `rememberListDetailSceneStrategy` and `rememberSupportingPaneSceneStrategy` in `MeshtasticNavDisplay`, with draggable pane dividers via `VerticalDragHandle` + `paneExpansionDraggable`.
|
||||
|
||||
This means the project **successfully** uses the M3 Adaptive Scene bridge through `NavDisplay(sceneStrategies = ...)`. Feature entries annotate themselves with `ListDetailSceneStrategy.listPane()`, `.detailPane()`, or `.extraPane()` metadata.
|
||||
|
||||
**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)
|
||||
|
||||
**Status:** ✅ Adopted (2026-03-26). Each backstack entry now gets its own `ViewModelStoreOwner` via `rememberViewModelStoreNavEntryDecorator()`. ViewModels obtained via `koinViewModel()` are automatically cleared when their entry is popped. Encapsulated in `MeshtasticNavDisplay` in `core:ui/commonMain`.
|
||||
|
||||
**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.
|
||||
|
||||
### P1: Add default NavDisplay transitions (medium-value, low-risk)
|
||||
|
||||
**Status:** ✅ Adopted (2026-03-26). A shared 350 ms crossfade (`fadeIn` + `fadeOut`) is applied for both forward and pop navigation via `MeshtasticNavDisplay`. This replaces the library's platform defaults (Android: 700 ms fade; Desktop: no animation) with a faster, consistent transition.
|
||||
|
||||
**Impact:** Immediate UX improvement on both Android and Desktop. Desktop now has visible navigation transitions.
|
||||
|
||||
### P2: Adopt `DialogSceneStrategy` for navigation-driven dialogs (medium-value, medium-risk)
|
||||
|
||||
**Status:** ✅ Adopted (2026-03-26). `MeshtasticNavDisplay` includes `DialogSceneStrategy` in `sceneStrategies` before `SinglePaneSceneStrategy`. Feature modules can now use `entry<T>(metadata = DialogSceneStrategy.dialog()) { ... }` to render entries as overlay Dialogs with proper backstack lifecycle and predictive-back support.
|
||||
|
||||
**Impact:** Cleaner dialog lifecycle management available for future dialog routes. Existing dialogs via `AlertHost` are unaffected.
|
||||
|
||||
### Consolidation: `MeshtasticNavDisplay` shared wrapper
|
||||
|
||||
**Status:** ✅ Adopted (2026-03-26). A new `MeshtasticNavDisplay` composable in `core:ui/commonMain` encapsulates the standard `NavDisplay` configuration:
|
||||
- Entry decorators: `rememberSaveableStateHolderNavEntryDecorator` + `rememberViewModelStoreNavEntryDecorator`
|
||||
- Scene strategies: `DialogSceneStrategy` + `SinglePaneSceneStrategy`
|
||||
- Transition specs: 350 ms crossfade (forward + pop)
|
||||
|
||||
Both `app/Main.kt` and `desktop/DesktopMainScreen.kt` now call `MeshtasticNavDisplay` instead of configuring `NavDisplay` directly. The `lifecycle-viewmodel-navigation3` dependency was moved from host modules to `core:ui`.
|
||||
|
||||
### 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. Now unblocked by P1 adoption.
|
||||
|
||||
### Deferred: Custom Scene strategies
|
||||
|
||||
The `ListDetailSceneStrategy` and `SupportingPaneSceneStrategy` are adopted and working. Consider writing additional custom `SceneStrategy` implementations for specialized layouts (e.g., three-pane "Power User" scenes) as the Navigation 3 Scene API matures.
|
||||
|
||||
## 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`.~~
|
||||
|
||||
**Updated 2026-03-26:** P0, P1, and P2 adopted and consolidated into `MeshtasticNavDisplay` in `core:ui/commonMain`. P3 (per-entry transitions) is available for incremental adoption by feature modules. Scene-based multi-pane remains deferred.
|
||||
|
||||
## 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`
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
<!--
|
||||
- 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 Parity Strategy (Android + Desktop)
|
||||
|
||||
**Date:** 2026-03-11
|
||||
**Status:** Implemented (2026-03-21)
|
||||
**Scope:** `app` and `desktop` navigation structure using shared `core:navigation` routes
|
||||
|
||||
## Context
|
||||
|
||||
Desktop and Android both use Navigation 3 typed routes from `core:navigation`. Previously graph wiring had diverged — desktop used a separate `DesktopDestination` enum with 6 entries (including a top-level Firmware tab) while Android used 5 entries.
|
||||
|
||||
This has been resolved. Both shells now use the shared `TopLevelDestination` enum from `core:navigation/commonMain` with 5 entries (Conversations, Nodes, Map, Settings, Connections). Firmware is an in-flow route on both platforms.
|
||||
|
||||
Both modules still define separate graph-builder files (`app/navigation/*.kt`, `desktop/navigation/*.kt`) with different destination coverage and placeholder behavior, but the **top-level shell structure is unified**.
|
||||
|
||||
## Current-State Findings
|
||||
|
||||
1. **Top-level destinations are unified.**
|
||||
- Both shells iterate `TopLevelDestination.entries` from `core:navigation/commonMain`.
|
||||
- Shared icon mapping lives in `core:ui` (`TopLevelDestinationExt.icon`).
|
||||
- Parity tests exist in both `core:navigation/commonTest` (`NavigationParityTest`) and `desktop/test` (`DesktopTopLevelDestinationParityTest`).
|
||||
2. **Feature coverage is unified via `commonMain` feature graphs.**
|
||||
- The `settingsGraph`, `nodesGraph`, `contactsGraph`, `connectionsGraph`, `firmwareGraph`, and `mapGraph` are now fully shared and exported from their respective feature modules' `commonMain` source sets.
|
||||
- Desktop acts as a thin shell, delegating directly to these shared graphs.
|
||||
3. **Saved-state route registration is fully shared.**
|
||||
- `MeshtasticNavSavedStateConfig` in `core:navigation/commonMain` maintains the unified `SavedStateConfiguration` serializer list.
|
||||
- Both Android and Desktop reference this shared config when instantiating `rememberNavBackStack`.
|
||||
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 → Beta01 Changelog Impact Check
|
||||
|
||||
Source reviewed: Navigation 3 `1.1.0-beta01` (JetBrains fork), CMP `1.11.0-beta01`, Lifecycle `2.11.0-alpha02`.
|
||||
|
||||
> **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 use `MeshtasticNavDisplay` (`core:ui/commonMain`), which applies `ViewModelStoreNavEntryDecorator` + `SaveableStateHolderNavEntryDecorator` per active backstack.
|
||||
- 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.
|
||||
- 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 improved.**
|
||||
- Both hosts share `MeshtasticNavSavedStateConfig` from `core:navigation/commonMain` via `MultiBackstack`, reducing platform drift risk in serializer registration.
|
||||
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
|
||||
|
||||
- Renamed all JetBrains-forked lifecycle/nav3 version catalog aliases from `androidx-*` to `jetbrains-*` prefix to make fork provenance unambiguous:
|
||||
- `jetbrains-lifecycle-runtime`, `jetbrains-lifecycle-runtime-compose`, `jetbrains-lifecycle-viewmodel-compose`, `jetbrains-lifecycle-viewmodel-navigation3`
|
||||
- `jetbrains-navigation3-runtime`, `jetbrains-navigation3-ui`
|
||||
- Documented in the version catalog that `jetbrains-navigation3-runtime` intentionally maps to `navigation3-ui` until a separate runtime artifact is published.
|
||||
- Migrated `core:data` `commonMain` from `androidx.lifecycle:lifecycle-runtime` (Google) to `org.jetbrains.androidx.lifecycle:lifecycle-runtime` (JetBrains fork) for full consistency.
|
||||
- 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`).
|
||||
- Consolidated `app` adaptive dependencies to JetBrains Material 3 Adaptive coordinates (`org.jetbrains.compose.material3.adaptive:*`) so Android and Desktop consume the same adaptive artifact family. The Android-only navigation suite remains on `androidx.compose.material3:material3-adaptive-navigation-suite`.
|
||||
|
||||
### Deferred Follow-ups
|
||||
|
||||
- Add automated validation that desktop serializer registrations stay in sync with shared route keys.
|
||||
|
||||
## Options Evaluated
|
||||
|
||||
### Option A: Reuse `:app` navigation implementation directly in desktop
|
||||
|
||||
**Pros**
|
||||
- Maximum short-term parity in structure.
|
||||
|
||||
**Cons**
|
||||
- `:app` graph code is tightly coupled to Android wrappers (`Android*ViewModel`, Android-only screen wrappers, app-specific UI state like scroll-to-top flows).
|
||||
- Pulling this code into desktop would either fail at compile-time or force additional platform branching in app files.
|
||||
- Violates clean module boundaries (`desktop` should not depend on Android-specific app glue).
|
||||
|
||||
**Decision:** Not recommended.
|
||||
|
||||
### Option B: Keep fully separate desktop graph and replicate app behavior manually
|
||||
|
||||
**Pros**
|
||||
- Lowest refactor cost right now.
|
||||
- Keeps platform customization simple.
|
||||
|
||||
**Cons**
|
||||
- Drift is guaranteed over time.
|
||||
- No central policy for intentional vs accidental divergence.
|
||||
- High maintenance burden for parity-sensitive flows.
|
||||
|
||||
**Decision:** Not recommended as a long-term strategy.
|
||||
|
||||
### Option C (Recommended): Hybrid shared contract + platform graph adapters
|
||||
|
||||
**Pros**
|
||||
- Preserves platform-specific wiring where needed.
|
||||
- Reduces drift by moving parity-sensitive definitions to shared contracts.
|
||||
- Enables explicit, testable exceptions for desktop-only or Android-only behavior.
|
||||
|
||||
**Cons**
|
||||
- Requires incremental extraction work.
|
||||
- Needs light governance (parity matrix + tests + docs).
|
||||
|
||||
**Decision:** Recommended.
|
||||
|
||||
## Decision
|
||||
|
||||
Adopt a **hybrid parity model**:
|
||||
|
||||
1. Keep platform graph registration in `app` and `desktop`.
|
||||
2. Extract parity-sensitive navigation metadata into shared contracts (top-level destination set/order, route ownership map, and allowed platform exceptions).
|
||||
3. Keep platform-specific destination implementations as adapters around shared route keys.
|
||||
4. Add route parity tests so drift is detected automatically.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1 (Immediate): Stop drift on shell structure ✅
|
||||
|
||||
- ✅ Aligned desktop top-level destination policy with Android (removed Firmware from top-level; kept as in-flow).
|
||||
- ✅ Both shells now use shared `TopLevelDestination` enum from `core:navigation/commonMain`.
|
||||
- ✅ Shared icon mapping in `core:ui` (`TopLevelDestinationExt.icon`).
|
||||
- Parity matrix documented inline: top-level set is Conversations, Nodes, Map, Settings, Connections on both platforms.
|
||||
|
||||
### Phase 2 (Near-term): Extract shared navigation contracts ✅ (partially)
|
||||
|
||||
- ✅ Shared `TopLevelDestination` enum with `fromNavKey()` already serves as the canonical metadata object.
|
||||
- Both `app` and `desktop` shells iterate `TopLevelDestination.entries` — no separate `DesktopDestination` enum remains.
|
||||
- Remaining: optional visibility flags by platform, route grouping metadata (lower priority since shells are unified).
|
||||
|
||||
### Phase 3 (Near-term): Add parity checks ✅ (partially)
|
||||
|
||||
- ✅ `NavigationParityTest` in `core:navigation/commonTest` — asserts 5 top-level destinations and `fromNavKey` matching.
|
||||
- ✅ `DesktopTopLevelDestinationParityTest` in `desktop/test` — asserts desktop routes match Android parity set and firmware is not top-level.
|
||||
- Remaining: assert every desktop serializer registration corresponds to an actual route; assert every intentional exception is listed.
|
||||
|
||||
### Phase 4 (Mid-term): Reduce app-specific graph coupling
|
||||
|
||||
- Move reusable graph composition helpers out of `:app` where practical (while keeping Android-only wrappers in Android source sets).
|
||||
- Keep desktop-specific placeholder implementations, but tie them to explicit parity exception entries.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Navigation behavior remains platform-adaptive, but parity expectations become explicit and enforceable.
|
||||
- Desktop can keep legitimate deviations (map/charts/platform integrations) without silently changing IA.
|
||||
- New route additions will require touching one shared contract plus platform implementations, making review scope clearer.
|
||||
|
||||
## Source Anchors
|
||||
|
||||
- Shared routes: `core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/Routes.kt`
|
||||
- Shared saved-state config: `core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/NavigationConfig.kt`
|
||||
- Android shell: `app/src/main/kotlin/org/meshtastic/app/ui/Main.kt`
|
||||
- Shared graph registrations: `feature/*/src/commonMain/kotlin/org/meshtastic/feature/*/navigation/`
|
||||
- Platform graph content: `feature/*/src/{androidMain,jvmMain}/kotlin/org/meshtastic/feature/*/navigation/`
|
||||
- Desktop shell: `desktop/src/main/kotlin/org/meshtastic/desktop/ui/DesktopMainScreen.kt`
|
||||
- Desktop graph assembly: `desktop/src/main/kotlin/org/meshtastic/desktop/navigation/DesktopNavigation.kt`
|
||||
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# KMP Migration Status
|
||||
|
||||
> Last updated: 2026-04-10
|
||||
> Last updated: 2026-04-13
|
||||
|
||||
Single source of truth for Kotlin Multiplatform migration progress. For the forward-looking roadmap, see [`roadmap.md`](./roadmap.md). For completed decision records, see [`decisions/`](./decisions/).
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ Modules that share JVM-specific code between Android and desktop now standardize
|
|||
| `feature:messaging` | ✅ | ✅ Adaptive contacts + messages; fully shared `contactsGraph`, `MessageScreen`, `ContactsScreen`, and `MessageListPaged` |
|
||||
| `feature:connections` | ✅ | ✅ Shared `ConnectionsScreen` with dynamic transport detection |
|
||||
| `feature:intro` | — | — | Screens remain in `androidMain`; shared ViewModel only |
|
||||
| `feature:map` | — | Placeholder; shared `NodeMapViewModel`, `BaseMapViewModel`, and `TracerouteNodeSelection`. Map rendering decomposed into 3 `CompositionLocal` provider contracts (`MapViewProvider`, `NodeTrackMapProvider`, `TracerouteMapProvider`) with per-flavor implementations in `:app` |
|
||||
| `feature:map` | — | Placeholder; shared `NodeMapViewModel`, `BaseMapViewModel`. Map rendering decomposed into 3 `CompositionLocal` provider contracts (`MapViewProvider`, `NodeTrackMapProvider`, `TracerouteMapProvider`) with per-flavor implementations in `:app` |
|
||||
| `feature:firmware` | ✅ | ✅ Fully KMP: Unified OTA, native Secure DFU, USB/UF2, FirmwareRetriever |
|
||||
| `feature:wifi-provision` | ✅ | ✅ KMP WiFi provisioning via BLE (Nymea protocol); shared UI and ViewModel |
|
||||
| `feature:widget` | ❌ | — | Android-only (Glance appwidgets). Intentional. |
|
||||
|
|
@ -79,9 +79,7 @@ Working Compose Desktop application with:
|
|||
| Multi-target readiness | **9/10** | Full JVM; release-ready desktop; iOS simulator builds compiling successfully |
|
||||
| CI confidence | **9/10** | 26 modules validated (including feature:wifi-provision); native release installers automated |
|
||||
| DI portability | **8/10** | Koin annotations in commonMain; supportedDeviceTypes injected per platform |
|
||||
| Test maturity | **9/10** | Mokkery, Turbine, and Kotest integrated; property-based testing established; broad coverage across all 9 features |
|
||||
|
||||
> See [`decisions/architecture-review-2026-03.md`](./decisions/architecture-review-2026-03.md) for the full gap analysis.
|
||||
| Test maturity | **9/10** | Mokkery, Turbine, and Kotest integrated; property-based testing established; broad coverage across all 9 features. Gaps: `core:service`, `core:network` (TcpTransport), `core:ble` state machine, `core:ui` utils, desktop navigation graphs |
|
||||
|
||||
## Completion Estimates
|
||||
|
||||
|
|
@ -105,11 +103,11 @@ Based on the latest codebase investigation, the following steps are proposed to
|
|||
|
||||
| Decision | Status | Details |
|
||||
|---|---|---|
|
||||
| Navigation 3 parity model (shared `TopLevelDestination` + platform adapters) | ✅ Done | See [`decisions/navigation3-parity-2026-03.md`](./decisions/navigation3-parity-2026-03.md) |
|
||||
| Navigation 3 parity model (shared `TopLevelDestination` + platform adapters) | ✅ Done | Both shells use shared `TopLevelDestination` enum and `MeshtasticNavDisplay` from `core:ui/commonMain`; parity tests in `core:navigation/commonTest` |
|
||||
| Hilt → Koin | ✅ Done | See [`decisions/koin-migration.md`](./decisions/koin-migration.md) |
|
||||
| BLE abstraction (Kable) | ✅ Done | See [`decisions/ble-strategy.md`](./decisions/ble-strategy.md) |
|
||||
| Firmware KMP migration (pure Secure DFU) | ✅ Done | Native Nordic Secure DFU protocol reimplemented in pure KMP using Kable; desktop is first-class target |
|
||||
| Material 3 Adaptive (JetBrains) | ✅ Done | Version `1.3.0-alpha06` aligned with CMP `1.11.0-beta01`; supports Large (1200dp) and Extra-large (1600dp) breakpoints |
|
||||
| Material 3 Adaptive (JetBrains) | ✅ Done | Version `1.3.0-alpha06` aligned with CMP `1.11.0-beta02`; supports Large (1200dp) and Extra-large (1600dp) breakpoints |
|
||||
| JetBrains lifecycle/nav3 alias alignment | ✅ Done | All forked deps use `jetbrains-*` prefix in version catalog; `core:data` commonMain uses JetBrains lifecycle runtime |
|
||||
| Expect/actual consolidation | ✅ Done | 7 pairs eliminated; 15+ genuinely platform-specific retained |
|
||||
| Transport deduplication | ✅ Done | `StreamFrameCodec`, `TcpTransport`, and `SerialTransport` shared in `core:network` |
|
||||
|
|
@ -127,7 +125,7 @@ Based on the latest codebase investigation, the following steps are proposed to
|
|||
- Firmware remains available as an in-flow route instead of a top-level destination, matching Android information architecture.
|
||||
- Android navigation graphs are decoupled and extracted into their respective feature modules, aligning with the Desktop architecture.
|
||||
- Parity tests exist in `core:navigation/commonTest` (`NavigationParityTest`) and `desktop/test` (`DesktopTopLevelDestinationParityTest`).
|
||||
- Remaining parity work is documented in [`decisions/navigation3-parity-2026-03.md`](./decisions/navigation3-parity-2026-03.md): serializer registration validation and platform exception tracking.
|
||||
- Remaining parity work: serializer registration validation and platform exception tracking.
|
||||
|
||||
## App Module Thinning Status
|
||||
|
||||
|
|
@ -159,19 +157,17 @@ Remaining to be extracted from `:app` or unified in `commonMain`:
|
|||
|
||||
| Dependency | Version | Why |
|
||||
|---|---|---|
|
||||
| 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 |
|
||||
| Compose Multiplatform | `1.11.0-beta02` | Required for JetBrains Adaptive `1.3.0-alpha06` and Material 3 `1.11.0-alpha06` |
|
||||
| Compose Multiplatform Material 3 | `1.11.0-alpha06` | Material 3 components including `NavigationSuiteScaffold` |
|
||||
| Koin | `4.2.1` | Nav3 + K2 compiler plugin support |
|
||||
| JetBrains Lifecycle | `2.11.0-alpha03` | Multiplatform ViewModel/lifecycle; includes `lifecycle-viewmodel-navigation3` for entry-scoped ViewModels |
|
||||
| JetBrains Navigation 3 | `1.1.0-rc01` | 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)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
> Last updated: 2026-04-10
|
||||
|
||||
Forward-looking priorities for the Meshtastic KMP multi-target effort. For current state, see [`kmp-status.md`](./kmp-status.md). For the full gap analysis, see [`decisions/architecture-review-2026-03.md`](./decisions/architecture-review-2026-03.md).
|
||||
Forward-looking priorities for the Meshtastic KMP multi-target effort. For current state, see [`kmp-status.md`](./kmp-status.md).
|
||||
|
||||
## Architecture Health (Immediate)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
# Baseline Test Coverage Report
|
||||
**Date:** Wednesday, March 18, 2026
|
||||
**Overall Project Coverage:** 8.796%
|
||||
**App Module Coverage:** 1.6404%
|
||||
|
||||
This baseline was captured using `./gradlew koverLog` at the start of the 'Expand Testing Coverage' track.
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# Final Test Coverage Report
|
||||
**Date:** Wednesday, March 18, 2026
|
||||
**Overall Project Coverage:** 10.2591% (Baseline: 8.796%)
|
||||
**Absolute Increase:** +1.46%
|
||||
|
||||
## Module Highlights
|
||||
| Module | Coverage | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| `core:domain` | 26.55% | UseCase gap fill complete. |
|
||||
| `feature:intro` | 30.76% | ViewModel tests enabled. |
|
||||
| `feature:map` | 33.33% | BaseMapViewModel tests refactored. |
|
||||
| `feature:node` | 24.70% | Metrics, Detail, Compass, and Filter tests added/refactored. |
|
||||
| `feature:connections` | 26.49% | ScannerViewModel verified. |
|
||||
| `feature:messaging` | 18.54% | MessageViewModel verified. |
|
||||
|
||||
This report concludes the 'Expand Testing Coverage' track.
|
||||
Significant improvements were made in ViewModel testability through interface extraction and Mokkery/Turbine migration.
|
||||
Foundational logic in `core:network` was strengthened with Kotest property-based tests.
|
||||
Loading…
Add table
Add a link
Reference in a new issue