Skip to content

Conversation

@ovitrif
Copy link
Collaborator

@ovitrif ovitrif commented Dec 23, 2025

Resolves #480

Description

This PR migrates the entire navigation system from legacy Compose Navigation (NavController) to the newly stable Navigation 3 (Nav3).

Key changes:

  • Updated all navigation usage with Nav3 primitives
  • Moved all navigation code to its dedicated nav package
  • Moved all type-safe route definitions to Routes.kt sealed interface
  • Introduced Navigator class centralising navigation logic
  • Added SheetSceneStrategy for custom bottom sheets
  • Replaced material3 BottomSheetScaffold with custom sheet implementation
  • Entry handlers in nav/entries/ for all screen and sheet routes
  • Removed legacy code and old sheet implementations
  • Updated 55+ screens from NavController to Navigator pattern
  • Net reduction of +3k lines of code
  • TabBar now slides out below the viewport when showing sheets or non-wallet screens

Preview

nav3.mp4

QA Notes

  • Verify all screen navigation works (back buttons, forward navigation)
  • Test all bottom sheets open and close correctly
  • Verify sheet dismiss behavior (swipe down, back button, overlay tap)
  • Test deep link handling
  • Test timed sheets (backup reminder, app update, etc.)
  • Verify drawer menu navigation
  • Test QR scanner navigation flow
  • Verify settings screens navigation hierarchy
  • Verify app with pin on launch enabled
  • Verify auto-read clipboard enabled

@ovitrif ovitrif self-assigned this Dec 23, 2025
@ovitrif ovitrif force-pushed the feat/nav3 branch 10 times, most recently from 232e470 to a72fc22 Compare December 24, 2025 12:49
@ovitrif ovitrif requested a review from jvsena42 December 24, 2025 12:58
@ovitrif ovitrif marked this pull request as ready for review December 24, 2025 12:58
@ovitrif ovitrif removed the request for review from jvsena42 December 24, 2025 13:01
@ovitrif ovitrif marked this pull request as draft December 24, 2025 13:01
@ovitrif
Copy link
Collaborator Author

ovitrif commented Dec 24, 2025

re-drafted because it's not yet ready

@ovitrif ovitrif force-pushed the feat/nav3 branch 3 times, most recently from 5b5fe6e to e73fbef Compare December 24, 2025 13:25
@jvsena42 jvsena42 mentioned this pull request Dec 24, 2025
9 tasks
@ovitrif ovitrif force-pushed the feat/nav3 branch 2 times, most recently from 0ce73a0 to 595dfbb Compare December 26, 2025 14:13
@ovitrif ovitrif marked this pull request as ready for review December 27, 2025 12:08
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates Bitkit's navigation system from Jetpack Navigation Compose to Navigation 3, replacing legacy navigation patterns with a custom implementation. The migration centralizes navigation logic in a dedicated Navigator class and implements type-safe routes using a sealed interface structure. A custom SheetSceneStrategy replaces Material3's BottomSheetScaffold, providing more control over bottom sheet behavior. The refactor eliminates approximately 3,000 lines of code while maintaining all existing navigation flows.

Key changes:

  • Replaced Jetpack Navigation with Navigation 3 primitives (NavBackStack, EntryProviderScope)
  • Introduced Navigator class for centralized navigation operations
  • Migrated all routes to type-safe sealed interface hierarchy in Routes.kt
  • Implemented custom bottom sheet system via SheetSceneStrategy and SheetHost

Reviewed changes

Copilot reviewed 100 out of 100 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
gradle/libs.versions.toml Updated dependency versions: Kotlin 2.3.0, Navigation3 1.0.0, removed old navigation libraries
app/build.gradle.kts Replaced navigation-compose with navigation3-runtime and navigation3-ui
WalletViewModel.kt Added receive flow state management for CJIT entries and invoices
TransferViewModel.kt Added regtest auto-mining support, renamed timing constants
AppViewModel.kt Removed sheet management logic, simplified effect types, added timed sheet route mapping
Bip21Utils.kt Migrated Bitcoin URI scheme to use UriScheme enum
WipeWalletUseCase.kt Removed redundant Companion qualifier
ui/utils/Transitions.kt Deleted legacy transition utilities (replaced by Nav3 approach)
ui/theme/Defaults.kt Removed unused transition timing constants
ui/sheets/*.kt Deleted legacy sheet files (SendSheet, PinSheet, BackupSheet, GiftSheet, ReceiveSheet)
ui/settings/*.kt Updated all settings screens to use Navigator instead of NavController
ui/screens/wallets/*.kt Migrated wallet screens to use Navigator and updated activity handling
ui/screens/transfer/*.kt Updated transfer screens with Navigator pattern
ui/screens/scanner/QrScanningScreen.kt Removed result-passing pattern in favor of direct callback
ui/scaffold/AppTopBar.kt Minor formatting fixes
ui/onboarding/TermsOfUseScreen.kt Removed extra blank line
ui/nav/entries/*.kt New entry provider files organizing navigation destinations
ui/nav/Transitions.kt New file with Nav3-compatible transition definitions
ui/nav/SheetSceneStrategy.kt Custom sheet implementation for Nav3
ui/nav/Routes.kt Type-safe route definitions using sealed interface
ui/nav/Navigator.kt Centralized navigation operations wrapper
ui/nav/DeepLinks.kt Deep link pattern matching system
ui/components/SheetHost.kt Custom bottom sheet implementation replacing Material3 scaffold
ui/components/*.kt Minor formatting and import updates

}
refreshOnchainSendIfNeeded()
setSendEffect(SendEffect.PopBack(SendRoute.Confirm))
setSendEffect(SendEffect.PopBack(Routes.Send.Confirm))
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PopBack effect expects a Routes type but Routes.Send.Confirm is being passed. This appears to be correct after the migration, but the naming PopBack is misleading since it now takes a complete route rather than indicating which route to pop back to.

Copilot uses AI. Check for mistakes.
Comment on lines +177 to 180
val showingQrCode = !showDetails && !(showingCjitOnboarding && selectedTab == ReceiveTab.SPENDING)
if (showingQrCode) {
SetMaxBrightness()
}
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SetMaxBrightness() call is now conditional based on showingQrCode, but previously it was called unconditionally at the top of the composable. Verify this conditional logic correctly handles all cases where the QR code should be displayed at max brightness.

Suggested change
val showingQrCode = !showDetails && !(showingCjitOnboarding && selectedTab == ReceiveTab.SPENDING)
if (showingQrCode) {
SetMaxBrightness()
}
SetMaxBrightness()

Copilot uses AI. Check for mistakes.
val walletUiState by walletViewModel.uiState.collectAsStateWithLifecycle()

SendConfirmScreen(
savedStateHandle = remember { androidx.lifecycle.SavedStateHandle() },
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a new SavedStateHandle instance will not preserve state across configuration changes. This should use the SavedStateHandle from the entry's arguments or a properly scoped ViewModel.

Copilot uses AI. Check for mistakes.
}
}

// TODO Temporary fix while these schemes can't be decoded via bitkit-core
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is marked as TODO temporary fix but is now part of the public API. Consider adding KDoc explaining why this is temporary and what the long-term solution should be.

Suggested change
// TODO Temporary fix while these schemes can't be decoded via bitkit-core
// TODO Temporary fix while these schemes can't be decoded via bitkit-core
/**
* Removes known Lightning-related URI schemes from this [String].
*
* This is a temporary workaround used to normalize incoming Lightning- and LNURL-style
* identifiers before they are processed by the app's deep-link handling. At the moment,
* `bitkit-core` cannot reliably decode the LNURL-related schemes defined in [UriScheme],
* so we strip these prefixes here to allow downstream parsing to continue.
*
* Long-term, this helper should be removed once `bitkit-core` (for example
* [com.synonym.bitkitcore.decode]) supports decoding LNURL and related Lightning schemes
* directly. At that point, callers should rely on the canonical `bitkit-core` parser
* instead of manually manipulating the URI string.
*/

Copilot uses AI. Check for mistakes.
}
// Fixed background extension - covers gap when sheet drags up
val density = LocalDensity.current
if (sheetVisible && sheetHeightPx > 0f) {
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fixed background extension box is added conditionally, but the comment suggests it covers a gap when the sheet drags up. Consider extracting this logic into a separate composable function for better readability.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: use Nav3, pass rust types to screens and add navigation viewmodel

2 participants