Skip to content

refactor(MainNavigator): migrate multi-screen leaf flows to native-stack + HeaderStandard#30956

Merged
weitingsun merged 10 commits into
mainfrom
wsun/main-navigator-multi-screen-leaf-flow
Jun 3, 2026
Merged

refactor(MainNavigator): migrate multi-screen leaf flows to native-stack + HeaderStandard#30956
weitingsun merged 10 commits into
mainfrom
wsun/main-navigator-multi-screen-leaf-flow

Conversation

@weitingsun

@weitingsun weitingsun commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Description

This PR migrates the multi-screen leaf flow navigators in MainNavigator from JS Stack to NativeStack, and replaces the old JS-navbar (getOnboardingNavbarOptions / getEditableOptions via navigation.setOptions) on their screens with in-screen HeaderStandard headers from the design system.

Navigators migrated to NativeStack:

  • BrowserFlow (cardStyle→contentStyle, animationEnabled: false→animation: 'none', presentation: 'modal' preserved)
  • ExploreHome
  • NotificationsModeView
  • SetPasswordFlow (navigator-level screenOptions={{ headerShown: false }}; AccountBackupStep1 keeps gestureEnabled: false)

Screens moved to in-screen HeaderStandard:

  • ChoosePassword — back button gated on loading (no back while submitting); BACK_BUTTON_ID test id added.
  • AccountBackupStep1B — MetaMask logo title, no back button.
  • ManualBackupStep1 — header only shown for settingsBackup/backupFlow; hidden during onboarding. Shell + header now render from the first frame (spinner only fills the content area) to avoid the layout shift while ready resolves.
  • ManualBackupStep2 — header with back button.
  • ContactForm — title + back (navigation.pop()); Edit/Cancel moved to header endAccessory (hidden in add mode); setOptions no longer used.

Other:

  • ExploreFeed (TrendingView) — HeaderRoot includesTopInset + SafeAreaView edges={{ bottom: 'additive' }} to fix the double top-inset header shift.
  • NavigationDevPanel — added the "PR3 — Multi-screen leaf flows" and "Set Password Flow (inner screens)" QA groups with mock params (valid 12-word mnemonic so the backup grids render). No tests are added for this Dev Panel

Each screen now owns its header (includesTopInset, SafeAreaView edges={{ bottom: 'additive' }}), so behavior is identical whether the screen is reached via the migrated NativeStack flow or the legacy SettingsFlow JS stack (which now passes headerShown: false).

Changelog

CHANGELOG entry:null

Related issues

Fixes:

Manual testing steps

Feature: Navigation Dev Panel — PR3 routes
  As a developer
  I want to open PR3 flows from the dev panel
  So that I can verify native-stack and in-screen headers without full onboarding
  Background:
    Given the app is running in a dev build
    And I open Settings → Developer Options → Navigation Dev Panel
  
Scenario: Open top-level PR3 flows
    When I tap "Notifications" under "PR3 — Multi-screen leaf flows"
    Then the Notifications flow screen is displayed
    When I go back to the dev panel and tap "Set Password Flow"
    Then the Set Password flow navigator is displayed
    When I go back to the dev panel and tap "Explore Home"
    Then the Explore feed is displayed with a visible explore header
    When I go back to the dev panel and tap "Browser Flow"
    Then the browser flow is displayed
  
Scenario Outline: Open Set Password inner screens via dev panel
    When I tap "<label>" under "PR3 — Set Password Flow (inner screens)"
    Then the "<screen>" screen is displayed without crashing
    Examples:
      | label                              | screen              |
      | Choose Password (step 1 of 3)      | ChoosePassword        |
      | Account Backup Step 1 (step 2 of 3)| AccountBackupStep1  |
      | Account Backup Step 1B             | AccountBackupStep1B |
      | Manual Backup Step 1               | ManualBackupStep1   |
      | Manual Backup Step 2               | ManualBackupStep2   |
      | Manual Backup Step 3               | ManualBackupStep3   |
      | Optin Metrics                      | OptinMetrics          |

Screenshots/Recordings

Notifications

BEFORE AFTER
Notification Before Notification After

Explore

BEFORE AFTER
Explore Before Explore after

Browser

BEFORE AFTER
Browser Before Browser After

Password

BEFORE AFTER
password before Password after

Android test build: https://github.com/MetaMask/metamask-mobile/actions/runs/26853788206
Android screen recordings:
https://github.com/user-attachments/assets/4037a245-1ad3-412f-9415-e9e49804559a
https://github.com/user-attachments/assets/225ea7b8-f08a-4d34-8324-7bac724397d2

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Medium Risk
Touches wallet backup, password, and SRP flows where header/back behavior and safe-area layout matter; changes are mostly presentational but span onboarding and settings entry points.

Overview
This PR continues the native-stack migration for multi-screen leaf flows in MainNavigator and moves headers off React Navigation’s JS stack into in-screen HeaderStandard (and related safe-area tweaks).

Navigators BrowserFlow, ExploreHome, NotificationsModeView, and SetPasswordFlow now use NativeStack (cardStylecontentStyle, animationEnabled: falseanimation: 'none' where needed). Flow-level headerShown: false is set so screens own their chrome; backup routes in Settings and onboarding stacks also hide the native header for the same screens.

Screens drop navigation.setOptions / onboarding navbar helpers in favor of HeaderStandard: ChoosePassword (back disabled while loading), AccountBackupStep1B (MetaMask logo, no back), conditional header on ManualBackupStep1 (settings/backup only), headers on ManualBackupStep2, navbar removal on ManualBackupStep3, and ContactForm (title, back via pop(), Edit/Cancel in endAccessory). AccountBackupStep1 simplifies safe area (no manual status-bar padding). TrendingView uses HeaderRoot with includesTopInset and bottom safe-area edges to fix double top inset.

Dev/QA: NavigationDevPanel adds PR3 flow groups and mock nested SetPasswordFlow params (including a valid 12-word test mnemonic). Tests assert in-screen headers instead of setOptions.

Reviewed by Cursor Bugbot for commit 009549c. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@mm-token-exchange-service mm-token-exchange-service Bot added the team-mobile-platform Mobile Platform team label Jun 2, 2026
@github-actions github-actions Bot added the size-L label Jun 2, 2026
@weitingsun weitingsun marked this pull request as ready for review June 2, 2026 19:19
@weitingsun weitingsun requested review from a team as code owners June 2, 2026 19:19
@weitingsun weitingsun self-assigned this Jun 2, 2026
@github-actions github-actions Bot added the risk:medium AI analysis: medium risk label Jun 2, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.22222% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 82.77%. Comparing base (716c344) to head (4f2b963).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
...ts/Views/NavigationDevPanel/NavigationDevPanel.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #30956   +/-   ##
=======================================
  Coverage   82.77%   82.77%           
=======================================
  Files        5584     5585    +1     
  Lines      144075   144088   +13     
  Branches    33332    33348   +16     
=======================================
+ Hits       119254   119276   +22     
+ Misses      16874    16859   -15     
- Partials     7947     7953    +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e711f66. Configure here.

/>
</Stack.Navigator>
<NativeStack.Screen name="OptinMetrics" component={OptinMetrics} />
</NativeStack.Navigator>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ManualBackupStep3 loses native header

Medium Severity

SetPasswordFlow now uses NativeStack.Navigator with screenOptions={{ headerShown: false }}, but ManualBackupStep3 still configures its MetaMask logo bar only via navigation.setOptions(getTransparentOnboardingNavbarOptions(...)), which never sets headerShown: true. The step’s top branding header no longer appears in the password/backup flow.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e711f66. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This branding header was never there before due to the following code in OnboardingSuccess

  useLayoutEffect(() => {
    navigation.setOptions({
      headerShown: false,
    });
  }, [navigation]);

@github-actions github-actions Bot added risk:high AI analysis: high risk and removed risk:medium AI analysis: medium risk labels Jun 2, 2026
@github-actions github-actions Bot added risk:medium AI analysis: medium risk and removed risk:high AI analysis: high risk labels Jun 2, 2026
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts, SmokeWalletPlatform, SmokeIdentity, SmokeSeedlessOnboarding, SmokeBrowser, SmokeSnaps, SmokeNetworkAbstractions, SmokeNetworkExpansion, SmokeMultiChainAPI
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: high
  • AI Confidence: 82%
click to see 🤖 AI reasoning details

E2E Test Selection:

This PR is a navigation architecture migration (PR3 of a native-stack migration series) that touches several critical navigation flows:

  1. Onboarding flow refactoring (ChoosePassword, AccountBackupStep1/1B, ManualBackupStep1/2/3): All these screens had their navigation header management moved from navigation.setOptions() with getOnboardingNavbarOptions to inline HeaderStandard components. The navigator wrappers (SetPasswordFlow, OnboardingNav) were migrated from Stack to NativeStack. This affects:

    • New wallet creation (SmokeAccounts, SmokeWalletPlatform)
    • SRP backup flows from both onboarding and settings (SmokeAccounts, SmokeWalletPlatform)
    • Seedless onboarding flows that go through ChoosePassword (SmokeSeedlessOnboarding)
    • Multi-SRP import flows (SmokeIdentity, SmokeWalletPlatform)
  2. BrowserFlow migrated to NativeStack: The browser navigator was migrated from Stack.Navigator to NativeStack.Navigator with animation options changed (animationEnabled→animation:'none'). This is a critical change as the browser is used by:

    • SmokeBrowser (direct browser tests)
    • SmokeSnaps (snap installation and interaction via browser)
    • SmokeNetworkExpansion (Solana dApp connections via browser)
    • SmokeMultiChainAPI (CAIP-25 session tests via browser)
  3. ExploreHome/TrendingView migrated to NativeStack with SafeAreaView edge changes: Affects SmokeWalletPlatform (Trending tab).

  4. NotificationsModeView migrated to NativeStack: Affects SmokeNetworkAbstractions (notification settings).

  5. ContactForm in SettingsFlow: Header replaced with HeaderStandard, affects contact management which is tested in SmokeIdentity.

The navigation stack migration is high-risk because NativeStack behaves differently from Stack (different gesture handling, header rendering, animation behavior), and these changes span multiple critical user flows. Back navigation, header visibility, and screen transitions could all be affected.

Tags NOT selected:

  • SmokeConfirmations: No changes to confirmation screens or transaction flows
  • SmokeSwap/SmokeStake/SmokeMoney/SmokePerps/SmokePredictions: No changes to trading/financial flows

Performance Test Selection:
The changes are primarily navigation architecture refactoring (Stack to NativeStack migration) and UI header component replacements. While NativeStack can have different performance characteristics than Stack, these changes don't directly impact the specific performance metrics measured by the available performance tests (account list rendering, onboarding flow timing, login performance, swap flows, app launch, asset loading, predict markets, or perps). The changes are structural/architectural rather than data-loading or rendering-intensive changes that would meaningfully affect measured performance benchmarks.

View GitHub Actions results

@ieow ieow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm

@weitingsun weitingsun added this pull request to the merge queue Jun 3, 2026
Merged via the queue into main with commit 7833f7c Jun 3, 2026
217 checks passed
@weitingsun weitingsun deleted the wsun/main-navigator-multi-screen-leaf-flow branch June 3, 2026 16:51
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 3, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.81.0 Issue or pull request that will be included in release 7.81.0 label Jun 3, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.81.0 Issue or pull request that will be included in release 7.81.0 risk:medium AI analysis: medium risk size-L team-mobile-platform Mobile Platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants