Skip to content

Refactor nav3 architecture and enhance adaptive layouts#4944

Merged
jamesarich merged 15 commits intomainfrom
feat/nav-alignment
Mar 27, 2026
Merged

Refactor nav3 architecture and enhance adaptive layouts#4944
jamesarich merged 15 commits intomainfrom
feat/nav-alignment

Conversation

@jamesarich
Copy link
Copy Markdown
Collaborator

This pull request introduces significant improvements to the navigation architecture and documentation for the Meshtastic-Android Kotlin Multiplatform project. The most notable change is the addition of a new MultiBackstack navigation model, enabling independent navigation histories for each top-level tab, along with the integration of new UI components that leverage this model. The documentation is updated to reflect these architectural changes and provide more precise guidance for contributors.

Navigation Architecture Improvements:

  • Added the new MultiBackstack class and rememberMultiBackstack composable to core/navigation, supporting independent backstacks for each top-level tab and "exit through home" navigation behavior.
  • Refactored MainScreen in app/src/main/kotlin/org/meshtastic/app/ui/Main.kt to use MultiBackstack, replacing previous single backstack logic and integrating the new MeshtasticNavDisplay and MeshtasticNavigationSuite components for a more modular and scalable navigation structure. [1] [2]
  • Updated dependency in app/build.gradle.kts to include jetbrains.lifecycle.viewmodel.navigation3, supporting the new navigation model.

UI and ViewModel Handling:

  • Updated usage of koinViewModel in MainActivity and related UI code to align with new navigation and ViewModel scoping, ensuring ViewModels are correctly scoped to navigation entries and cleared on pop. [1] [2]

Documentation Updates:

  • Updated documentation files (AGENTS.md, GEMINI.md, .github/copilot-instructions.md) to describe the new navigation architecture, including the use of MeshtasticNavDisplay, MeshtasticNavigationSuite, and entry-scoped ViewModel handling. Clarified adaptive layout strategies and provided more specific instructions for feature module integration. [1] [2] [3] [4] [5] [6] [7]

These changes modernize the navigation approach, improve modularity, and provide clearer guidance for multiplatform development.

jamesarich and others added 13 commits March 26, 2026 12:23
- Integrate the `material3-adaptive-navigation-suite` library to streamline cross-platform navigation layouts.
- Replace manual branching logic for `NavigationBar` and `NavigationRail` with `NavigationSuiteScaffold` in `MeshtasticNavigationSuite`.
- Implement a `coerceNavigationType` helper to ensure `NavigationRail` is used for expanded widths instead of promoting to a `NavigationDrawer`.
- Utilize `currentWindowAdaptiveInfo` with large-width breakpoint support to improve responsiveness on Desktop and external displays.
- Remove redundant `MeshtasticNavigationBar` and `MeshtasticNavigationRail` private composables in favor of the standard navigation suite item API.
…Models

- 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`.
…nfiguration

- Introduce `MeshtasticNavDisplay` in `core:ui` to encapsulate shared Navigation 3 configuration, including entry decorators, scene strategies, and transitions.
- Integrate `rememberViewModelStoreNavEntryDecorator` to provide entry-scoped `ViewModelStoreOwner` support, ensuring ViewModels are automatically cleared when their backstack entry is popped.
- Configure `DialogSceneStrategy` to enable navigation-driven dialogs that respect backstack lifecycle and predictive back gestures.
- Implement a standardized 350 ms crossfade transition for both forward and pop navigation across all platforms.
- Refactor `app` and `desktop` host modules to utilize `MeshtasticNavDisplay`, removing redundant manual configuration of `NavDisplay` and decorators.
- Update `core:ui` dependencies to include `lifecycle-viewmodel-navigation3` and move it away from platform-specific host modules.
- Update architectural documentation (`AGENTS.md`, `GEMINI.md`, and decision logs) to reflect the adoption of centralized navigation and ViewModel scoping patterns.
- Replace the standard `NavDisplay` with the custom `MeshtasticNavDisplay` in `AppIntroductionScreen` to centralize navigation and backstack handling.
- Update `DesktopMainScreen` to transition from a persistent `NavigationRail` to an adaptive navigation shell.
- Clean up unused imports related to `NavigationRail`, `NavKey`, and `NavDisplay` across desktop and intro features.
- Update `MainScreen` (Android) and `DesktopMainScreen` to manage their own `NavBackStack` initialization internally.
- Refactor `MainScreen` to obtain `UIViewModel` via Koin injection instead of receiving it as a parameter from `MainActivity`.
- Remove default bottom padding from `MeshtasticAppShell` and associated screen-level modifiers to allow for more flexible layout orchestration.
- Simplify `DesktopMainScreen` by moving backstack management inside the composable and cleaning up the navigation provider logic.
- Remove redundant lint suppressions in `Main.kt` following the simplification of the main screen composable structure.
- Clean up imports and normalize the usage of `MeshtasticNavDisplay` and `MeshtasticNavigationSuite` across platforms.
- Replace the custom `AdaptiveListDetailScaffold` with the official `ListDetailSceneStrategy` to manage adaptive layout orchestration.
- Integrate `ListDetailSceneStrategy` into `MeshtasticNavDisplay` to enable native pane switching based on the navigation backstack.
- Update `ContactsNavigation` and `NodesNavigation` graphs to include `listPane()` and `detailPane()` metadata for relevant route entries.
- Simplify `AdaptiveContactsScreen` and `AdaptiveNodeListScreen` by removing manual scaffold navigation logic and delegating to the navigation framework.
- Add the `jetbrains.compose.material3.adaptive.navigation3` library dependency to `core:ui` and relevant feature modules.
- Refactor `DesktopMainScreen` and `Main.kt` with minor formatting and indentation updates for better readability.
This commit refactors the navigation logic across `feature:node` and `feature:messaging` to use more robust backstack manipulation helpers and decouple screen implementations from navigation parameters.

Specific changes include:
- **Navigation Helpers**: Added `replaceLast` and `replaceAll` extensions to `MutableList<NavKey>` in `core:navigation` to allow more granular control over backstack mutations while minimizing structural changes.
- **Node Feature**:
    - Updated `NodesRoutes.NodeDetail` entry to directly instantiate `NodeDetailViewModel` and `CompassViewModel` using Koin, removing the reliance on `AdaptiveNodeListScreen` for detail rendering.
    - Simplified `AdaptiveNodeListScreen` by removing unused navigation and initialization parameters.
- **Messaging Feature**:
    - Refactored `ContactsRoutes.Messages` entry to handle ViewModel lifecycle and contact key initialization directly within the navigation graph.
    - Updated `ShareScreen` to use the new `replaceLast` helper for smoother transitions to message screens.
    - Simplified `AdaptiveContactsScreen` and `ContactsEntryContent` by removing unused `detailPaneCustom` and initialization logic.
- **Deep Linking**: Updated `MeshtasticAppShell` to use `backStack.replaceAll(navKeys)` when handling deep links, ensuring a cleaner backstack state transition.

Signed-off-by: James Rich <[email protected]>
This commit updates the `MeshtasticNavigationSuite` to conditionally show text labels based on the active navigation layout. Labels are now explicitly shown when using a `NavigationRail` and hidden otherwise to improve the visual density and consistency of the navigation UI across different adaptive breakpoints.

Specific changes include:
- Introduced a `showLabels` boolean determined by the current `layoutType`.
- Updated `NavigationSuiteScaffold` to only render the destination `label` if `showLabels` is true.

Signed-off-by: James Rich <[email protected]>
This commit enhances the navigation system to support adaptive layouts by integrating `SupportingPaneSceneStrategy` and marking specific routes to utilize the "extra pane" in list-detail scenarios.

Specific changes include:
- **Navigation Infrastructure**: Added `supportingPaneSceneStrategy` to `MeshtasticNavDisplay` and updated documentation to reflect support for `extraPane()` and supporting pane layouts.
- **Node Feature**: Updated `NodeMap`, `TracerouteLog`, `TracerouteMap`, and generic node detail screens in `NodesNavigation.kt` to use `ListDetailSceneStrategy.extraPane()`.
- **Messaging Feature**: Updated `Share` and `QuickChat` routes in `ContactsNavigation.kt` to use `ListDetailSceneStrategy.extraPane()`.
- **API Integration**: Applied `ExperimentalMaterial3AdaptiveApi` where necessary to support the new adaptive navigation strategies.

Signed-off-by: James Rich <[email protected]>
This commit enhances the adaptive navigation system by adding draggable dividers to the list-detail and supporting pane layouts. This allows users to manually resize panes in multi-pane "Power User" scenes on larger displays.

Specific changes include:
- **Navigation Enhancements**: Updated `MeshtasticNavDisplay` to include `rememberPaneExpansionState` and `VerticalDragHandle` within `ListDetailSceneStrategy` and `SupportingPaneSceneStrategy`.
- **UI Components**: Configured `paneExpansionDraggable` modifiers with a minimum touch target of 48.dp for improved accessibility.
- **Documentation**: Updated `AGENTS.md` to reflect the availability of draggable dividers (`VerticalDragHandle` + `paneExpansionState`) for widths ≥ 1200dp.
- **Code Style**: Applied consistent formatting and line-wrapping across `NavBackStackExt.kt`, `MeshtasticAppShell.kt`, `ContactsNavigation.kt`, and `MeshtasticNavigationSuite.kt`.

Signed-off-by: James Rich <[email protected]>
Refactored the application's multi-tab navigation to strictly align with the official AndroidX `nav3-recipes` for multiple backstacks.

Previously, swapping a single `NavBackStack` list instance caused Navigation 3 to perceive old entries as "popped," leading to the destruction of their associated `ViewModelStore` and UI state.

This commit resolves the issue by:
- Redesigning `MultiBackstack` as a state holder managing independent `NavBackStack` instances per tab.
- Modifying `MeshtasticNavDisplay` to bind a fresh set of decorators (specifically `SaveableStateHolderNavEntryDecorator` and `ViewModelStoreNavEntryDecorator`) to the active backstack dynamically via `remember(backStack)`. This ensures decorators are swapped alongside the stack, preserving state for inactive tabs.
- Implementing the standard "exit through home" back-handling pattern across all platforms.
- Removing legacy manual string keys from `koinViewModel()` injections, as `ViewModelStoreNavEntryDecorator` now correctly isolates ViewModel scope per entry.
- Added `androidx.lifecycle.viewmodel.navigation3` dependencies to the `app` and `desktop` root modules to support the decorator injections at the root composition level.
@github-actions github-actions bot added the enhancement New feature or request label Mar 27, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 27, 2026

Codecov Report

❌ Patch coverage is 31.70732% with 56 lines in your changes missing coverage. Please review.
✅ Project coverage is 19.05%. Comparing base (141b54f) to head (6fbdbf6).
⚠️ Report is 7 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...feature/messaging/navigation/ContactsNavigation.kt 25.00% 12 Missing ⚠️
...htastic/feature/node/navigation/NodesNavigation.kt 37.50% 10 Missing ⚠️
...tic/core/ui/component/MeshtasticNavigationSuite.kt 0.00% 8 Missing ⚠️
...top/src/main/kotlin/org/meshtastic/desktop/Main.kt 0.00% 8 Missing ⚠️
...n/org/meshtastic/core/navigation/MultiBackstack.kt 61.11% 0 Missing and 7 partials ⚠️
.../org/meshtastic/core/navigation/NavBackStackExt.kt 45.45% 4 Missing and 2 partials ⚠️
...shtastic/core/ui/component/MeshtasticNavDisplay.kt 0.00% 5 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4944      +/-   ##
==========================================
+ Coverage   18.97%   19.05%   +0.07%     
==========================================
  Files         572      572              
  Lines       18774    18790      +16     
  Branches     2790     2803      +13     
==========================================
+ Hits         3562     3580      +18     
+ Misses      14688    14677      -11     
- Partials      524      533       +9     
Flag Coverage Δ
host-unit 19.05% <31.70%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...src/main/kotlin/org/meshtastic/app/MainActivity.kt 0.00% <ø> (ø)
...shtastic/core/ui/component/MeshtasticNavDisplay.kt 0.00% <0.00%> (ø)
.../org/meshtastic/core/navigation/NavBackStackExt.kt 38.46% <45.45%> (+38.46%) ⬆️
...n/org/meshtastic/core/navigation/MultiBackstack.kt 61.11% <61.11%> (ø)
...tic/core/ui/component/MeshtasticNavigationSuite.kt 0.00% <0.00%> (ø)
...top/src/main/kotlin/org/meshtastic/desktop/Main.kt 0.00% <0.00%> (ø)
...htastic/feature/node/navigation/NodesNavigation.kt 68.00% <37.50%> (ø)
...feature/messaging/navigation/ContactsNavigation.kt 16.00% <25.00%> (+3.50%) ⬆️

... and 1 file with indirect coverage changes

This commit updates the image loading configuration for the desktop application to improve asset handling and manage cache versioning.

Specific changes include:
- Updated the image disk cache directory path to `image_cache_v3`.
- Configured `SvgDecoder.Factory` with `renderToBitmap = false` to change how SVG assets are processed by the image loader.

Signed-off-by: James Rich <[email protected]>
@jamesarich jamesarich added this pull request to the merge queue Mar 27, 2026
Merged via the queue into main with commit f2d09ff Mar 27, 2026
14 checks passed
@jamesarich jamesarich deleted the feat/nav-alignment branch March 27, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant