feat(ui): ship the new tab-bar UI to everyone - #613
Merged
Conversation
Adds a `.shipped` availability tier to `BetaFlags` and moves `.newUI` onto it. A shipped option reports on from `hasEnabled(_:)` regardless of what is stored, and neither Settings surface lists it — both already filter to `.developer` / `.publicBeta`, so the toggle disappears without either screen changing and no user can opt back out. The flag and its branches stay in place; tearing them out of the call sites is a follow-up.
Shipping the tab-bar UI to everyone retires the v1 scanner chrome the XCUITest suite navigated through: the Settings button, the Cash give button, and the scan-* bottom-bar tabs. Those flows still exist but are reached differently now, so each affected test needs a rewrite verified on a simulator rather than a selector swap. Skip them through a shared `skipPendingTabBarRewrite(_:)` marker — greppable, and each call site says which route moved. `.claude/plans/2026-08-20-ui-test-tab-bar-rewrite.md` maps every old affordance to its replacement. Two tests are repaired outright instead: - `assertMainScreenReached()` now looks for the Wallet tab, the launch tab, which both the native and legacy tab bars label. That keeps the wallet-rooted tests running unchanged. - `ForceLogoutSmokeTests` asserted on the Cash button, which no longer exists anywhere — so the assertion passed vacuously. Point it at the Wallet tab.
bmc08gt
added a commit
that referenced
this pull request
Aug 26, 2026
The tab-bar UI shipped to everyone in #613, so `BetaFlags.Option.newUI` had no readers left that could return false. Collapse every branch it gated and delete the v1 surfaces it was the last route to. Deleted: `BalanceScreen`, `ScanTopBar`/`ScanBottomBar`, the Currency Sell flow (Convert replaces it and calls the same `Session.sell` machinery underneath), `CurrencyInfoHeaderSection`/`CurrencyInfoFooter`, and `CurrencyCreationPromoCard`. Extracted rather than dropped: `ExchangedBalance` and `BalanceHeaderButton` out of `BalanceScreen`, and `RootSheetHost` out of `ScanScreen`. Router: `Stack.isTabHosted` replaces the runtime-registered `AppRouter.tabStacks` set. The old set was published by `HomeTabView`'s `onAppear`, so a deep link arriving before that view appeared fell through to the sheet lookup and was dropped — `.balance` has no sheet of its own. Making it a static fact on the stack fixes the cold-start case, and `AppRouterCrossStackTests` pins it against `HomeTab.pushStack`. `Availability` stays as-is; it is the mechanism for the next rollout, not part of this flag. Also picks up three symbols stranded by the deletions: `Session.canUseTips` (body was `true`), `Image.Symbol.hamburger` with its imageset, and the wallet leg of the token-info funnel. The last one is rewired rather than removed — the tab-bar wallet expands the card in place instead of pushing a screen, so `WalletScreen` now emits `openedFromWallet` on tap and `openedFromDeeplink` on a deep-linked open.
bmc08gt
added a commit
that referenced
this pull request
Aug 26, 2026
The tab-bar UI shipped to everyone in #613, so `BetaFlags.Option.newUI` had no readers left that could return false. Collapse every branch it gated and delete the v1 surfaces it was the last route to. Deleted: `BalanceScreen`, `ScanTopBar`/`ScanBottomBar`, the Currency Sell flow (Convert replaces it and calls the same `Session.sell` machinery underneath), `CurrencyInfoHeaderSection`/`CurrencyInfoFooter`, and `CurrencyCreationPromoCard`. Extracted rather than dropped: `ExchangedBalance` and `BalanceHeaderButton` out of `BalanceScreen`, and `RootSheetHost` out of `ScanScreen`. Router: `Stack.isTabHosted` replaces the runtime-registered `AppRouter.tabStacks` set. The old set was published by `HomeTabView`'s `onAppear`, so a deep link arriving before that view appeared fell through to the sheet lookup and was dropped — `.balance` has no sheet of its own. Making it a static fact on the stack fixes the cold-start case, and `AppRouterCrossStackTests` pins it against `HomeTab.pushStack`. `Availability` stays as-is; it is the mechanism for the next rollout, not part of this flag. Also picks up three symbols stranded by the deletions: `Session.canUseTips` (body was `true`), `Image.Symbol.hamburger` with its imageset, and the wallet leg of the token-info funnel. The last one is rewired rather than removed — the tab-bar wallet expands the card in place instead of pushing a screen, so `WalletScreen` now emits `openedFromWallet` on tap and `openedFromDeeplink` on a deep-linked open.
bmc08gt
added a commit
that referenced
this pull request
Aug 26, 2026
The tab-bar UI shipped to everyone in #613, so `BetaFlags.Option.newUI` had no readers left that could return false. Collapse every branch it gated and delete the v1 surfaces it was the last route to. Deleted: `BalanceScreen`, `ScanTopBar`/`ScanBottomBar`, the Currency Sell flow (Convert replaces it and calls the same `Session.sell` machinery underneath), `CurrencyInfoHeaderSection`/`CurrencyInfoFooter`, and `CurrencyCreationPromoCard`. Extracted rather than dropped: `ExchangedBalance` and `BalanceHeaderButton` out of `BalanceScreen`, and `RootSheetHost` out of `ScanScreen`. Router: `Stack.isTabHosted` replaces the runtime-registered `AppRouter.tabStacks` set. The old set was published by `HomeTabView`'s `onAppear`, so a deep link arriving before that view appeared fell through to the sheet lookup and was dropped — `.balance` has no sheet of its own. Making it a static fact on the stack fixes the cold-start case, and `AppRouterCrossStackTests` pins it against `HomeTab.pushStack`. `Availability` stays as-is; it is the mechanism for the next rollout, not part of this flag. Also picks up three symbols stranded by the deletions: `Session.canUseTips` (body was `true`), `Image.Symbol.hamburger` with its imageset, and the wallet leg of the token-info funnel. The last one is rewired rather than removed — the tab-bar wallet expands the card in place instead of pushing a screen, so `WalletScreen` now emits `openedFromWallet` on tap and `openedFromDeeplink` on a deep-linked open. Deleting the sell flow also removed the only `swapType: .sell` call site, so `SwapType` loses the case and the arms it fed in title, subtitle, navigationTitle, and trackTransaction. Convert keeps reporting through `Analytics.tokenSell` — it still disposes of the source token.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Flips
BetaFlags.Option.newUIto a new.shippedavailability tier and makeshasEnabled(_:)report.shippedoptions as on for everyone.Why a new tier rather than deleting the flag
.shippedneeds no call-site edits and no Settings-screen edits — both beta-flag screens already filter by availability (.developer/.publicBeta), so the row disappears on its own. It also means--beta-flags=can no longer switch the new UI off, and any previously stored opt-out is inert.The flag itself, the 13 branch sites, the orphaned v1 chrome (
ScanTopBar,ScanBottomBar,ScanScreen.isEmbedded), and the deadincludingDollars:parameter chain come out in a follow-up.UI tests
The v1 scanner chrome the XCUITest suite navigated through is now unreachable: the Settings button, the Cash give button, and the
scan-*bottom-bar tabs. Those flows still exist but are entered differently, so the affected tests are skipped behind a sharedskipPendingTabBarRewrite(_:)marker rather than rewritten blind — each skip names the route that moved, and.claude/plans/2026-08-20-ui-test-tab-bar-rewrite.mdmaps every old affordance to its replacement.Two are repaired outright:
assertMainScreenReached()now looks for the Wallet tab — the launch tab, labelled by both the native and legacy tab bars. This keeps every wallet-rooted test running unchanged.ForceLogoutSmokeTestsasserted the Cash button was absent, which is now vacuously true. It asserts on the Wallet tab instead.