Skip to content

refactor(nav): split AppRoute by how a route arrives - #1418

Open
bmc08gt wants to merge 2 commits into
feat/transaction-detailsfrom
refactor/app-route-presentation
Open

refactor(nav): split AppRoute by how a route arrives#1418
bmc08gt wants to merge 2 commits into
feat/transaction-detailsfrom
refactor/app-route-presentation

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #1417 — review that first.

AppRoute.Sheets held three unrelated populations: the four nav-bar tab homes, screens that are only ever pushed (ActivityHistory, TransactionDetails, Give), and actual modals. resolveRoutes wrapped every member in Main.Sheet, so the tab homes needed an asNavBarTab() carve-out to escape it and the pushed screens had no escape at all — a deeplink naming one landed in a modal instead of on the screen the rest of the app pushes.

Three groupings now say how a route arrives:

  • Tabs — the four nav-bar homes (Scanner, Wallet, Tips, Menu). navBarButton() is exhaustive over the type, so a new tab home fails to compile until it is given a button rather than silently behaving as an ordinary push.
  • Sheets — modals that host an inner backstack (TokenSelection, TipAmountEntry, ShareApp). That Main.Sheet packing is the only thing membership buys, so a modal needing no nested navigation implements com.getcode.navigation.Sheet directly instead — that marker, not this grouping, is what ModalBottomSheetSceneStrategy reads to present a route as a sheet.
  • Main — ordinary pushes onto whatever stack the user is on.

resolveRoutes drops the carve-out and wraps on membership alone; leadsWithTab becomes routes.firstOrNull() is AppRoute.Tabs.

Behaviour

Unchanged in-app. Every entry to the three moved screens already goes through navigator.push (WalletScreen.kt:53, TokenInfoScreen.kt:195, CurrencyInfoExpansion.kt:123, ActivityHistoryScreen.kt:69), and AppRouter only ever feeds tab homes into navigateAll. The one change is the fix: a deeplink naming one of the three now lands on the pushed screen.

Route class names change, so a back stack saved by an older build will not restore across the update — inherent to any route rename. Maestro tags derive from simpleName, all of which are preserved, so the flows are untouched.

Three scanner destinations the new type made visible

Second commit. Once the tab homes are their own type, code that treats one as an ordinary push reads as a mistake rather than as a convention.

  • The wallet's new-user tutorial dispatched "scan a tip card" as OpenScreen, which WalletScreen handles with navigator.push — the scanner arrived stacked on the wallet, and Back returned to the wallet instead of behaving like the nav bar. It now dispatches a SwitchTab event handled with replaceAll, the same call AppNavigationBar makes.
  • PurchaseAccountScreen released to the scanner on account creation rather than to homeRoute, which every other onboarding exit uses.
  • NotificationPermissionScreen.kt was a second copy of the permission screens left behind by the FlowHost migration, navigating to the scanner from both of its composables. Nothing calls them and AppRoute.Onboarding.NotificationPermission has no annotatedEntry to reach them by; the live path is OnboardingFlowScreen's NotificationPermissionStepContent, which releases to homeRoute. Deleted rather than repointed.

AppRoute.Sheets held three unrelated populations: the four nav-bar tab homes,
screens that are only ever pushed (ActivityHistory, TransactionDetails, Give),
and actual modals. resolveRoutes wrapped every member in Main.Sheet, so the tab
homes needed an asNavBarTab() carve-out to escape and the pushed screens had no
escape at all — a deeplink naming one landed in a modal instead of on the screen
the rest of the app pushes.

Three groupings now say how a route arrives:

- Tabs — the four nav-bar homes. navBarButton() is exhaustive over the type, so
  a new tab home fails to compile until it is given a button.
- Sheets — modals that host an inner backstack, which is the only thing the
  Main.Sheet wrapping buys. A modal needing no nested navigation implements
  com.getcode.navigation.Sheet directly; that marker, not this grouping, is what
  ModalBottomSheetSceneStrategy reads.
- Main — ordinary pushes.

resolveRoutes loses the carve-out and wraps on membership alone. In-app
behaviour is unchanged: every entry to the three moved screens already went
through navigator.push, and AppRouter only feeds tab homes into navigateAll.
A deeplink to one of them now lands on the pushed screen.

Route class names change, so a back stack saved by an older build will not
restore across the update. Maestro tags derive from simpleName, all of which
are preserved.
@bmc08gt bmc08gt self-assigned this Sep 4, 2026
@github-actions github-actions Bot added type: refactor Code restructuring, no behavior change area: payments Payments, transfers, intents, billing area: onramp Deposit, purchase, Coinbase, fiat on-ramp area: scanner QR/Kikcode scanning, camera area: tokens Token accounts, balances, token info area: deeplinks Deep link handling, URL routing, and link parsing area: onboarding labels Sep 4, 2026
Three scanner destinations the new AppRoute.Tabs type makes visible as errors:

The wallet's new-user tutorial dispatched "scan a tip card" as OpenScreen, which
WalletScreen handles with navigator.push — so the scanner arrived stacked on the
wallet, and Back returned to the wallet instead of behaving like the nav bar. It
now dispatches SwitchTab, handled with replaceAll, the same call AppNavigationBar
makes.

PurchaseAccountScreen released to the scanner on account creation rather than to
homeRoute, which every other onboarding exit uses.

NotificationPermissionScreen and NotificationPermissionRationaleScreen were a
second copy of the permission screens left behind by the FlowHost migration:
nothing calls them, and AppRoute.Onboarding.NotificationPermission has no
annotatedEntry to reach them by. The live path is OnboardingFlowScreen's
NotificationPermissionStepContent, which releases to homeRoute. Deleted rather
than repointed — the file's only effect was to make the wrong destination look
supported.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: deeplinks Deep link handling, URL routing, and link parsing area: onboarding area: onramp Deposit, purchase, Coinbase, fiat on-ramp area: payments Payments, transfers, intents, billing area: scanner QR/Kikcode scanning, camera area: tokens Token accounts, balances, token info type: refactor Code restructuring, no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant