Skip to content

Commit aa9b535

Browse files
chore(runway): cherry-pick feat(settings): cp-7.66.0 add feature flag to toggle between Account Menu and legacy Settings (#26073)
- feat(settings): cp-7.66.0 add feature flag to toggle between Account Menu and legacy Settings (#26032) ## **Description** This PR introduces the `mobileUxAccountMenu` feature flag to enable gradual rollout of the Account Menu feature. Originally we wanted to ship for this RC as is in this [PR](#25611) but we found some UI refinements were needed. The feature is being moved behind a feature flag and be hidden from this current RC and to allow for final design refinements for the next RC. **Why is this change required?** The Account Menu feature requires additional refinements before full release. A feature flag allows us to: - Control rollout via LaunchDarkly - Maintain backward compatibility with existing Settings flow - Iterate on design improvements without blocking the next release **What does this PR do?** Adds `selectAccountMenuEnabled` selector and `useAccountMenuEnabled` hook using the `mobileUxAccountMenu` remote feature flag - Implements conditional navigation: enabled → `AccountsMenuView`, disabled → legacy `Settings` - Hides duplicate sections in Settings when Account Menu is enabled (Permissions, Contacts, About MetaMask, Request Feature, Contact Support, Lock) - Hides SDK section in `SecuritySettings` when Account Menu is enabled - Adds unit tests for both enabled/disabled states - Reverts E2E spec files to pre-Account Menu state to avoid test skipping (4 files: account-syncing-settings-toggle, contact-sync-toggle, sync-users-contacts, test-snap-management). The E2E tests will be added again once the feature is ready ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Added feature flag mobileUxAccountMenu to control Account Menu rollout ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-397 ## **Manual testing steps** ```gherkin Scenario 1: Feature flag disabled (default behavior) Given the mobileUxAccountMenu feature flag is disabled When I tap the Settings tab in TabBar Then I should navigate to the legacy Settings screen And I should see all sections including Permissions, Contacts, About MetaMask, Request Feature, Contact Support, and Lock And I should see the SDK section in Security Settings Scenario 2: Feature flag enabled (new behavior) Given the mobileUxAccountMenu feature flag is enabled When I tap the Settings tab in TabBar Then I should navigate to the AccountsMenuView screen And the legacy Settings screen should hide duplicate sections (Permissions, Contacts, About MetaMask, Request Feature, Contact Support, Lock) And the SDK section should be hidden in Security Settings ``` ## **Screenshots/Recordings** Feature Flag Off https://github.com/user-attachments/assets/65e9a0a2-8c70-4d84-9f26-302d27d5b1c9 Feature Flag On https://github.com/user-attachments/assets/12503ba2-5219-4783-95c6-0fdef0ac8ecb ### **Before** `~` ### **After** `~` ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] 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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes Settings entry routing and conditional visibility of multiple Settings sections, which could break navigation paths or regress discoverability if the flag state is mis-evaluated. > > **Overview** > Introduces a new version-gated remote feature flag (`mobileUxAccountMenu`) via `selectAccountMenuEnabled` and `useAccountMenuEnabled` to control rollout of the Account Menu experience. > > Wires the flag into navigation so the Settings tab and `SettingsFlow` initial route switch between `AccountsMenu` and the legacy `Settings` screen, and conditionally hides legacy Settings/Security Settings sections (e.g., Permissions/Contacts/About/Support/Lock and the SDK connections section) when the account menu is enabled. > > Updates unit snapshots/tests and adjusts smoke/E2E flows to navigate into Settings without relying on Account Menu page objects. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 1c5dabc. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [3ef936b](3ef936b) Co-authored-by: Vince Howard <vincenguyenhoward@gmail.com>
1 parent 65a4ede commit aa9b535

18 files changed

Lines changed: 1101 additions & 217 deletions

File tree

app/component-library/components/Navigation/TabBar/TabBar.test.tsx

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import TabBar from './TabBar';
1616
import { TabBarIconKey, ExtendedBottomTabDescriptor } from './TabBar.types';
1717
import Routes from '../../../../constants/navigation/Routes';
1818
import { selectAssetsTrendingTokensEnabled } from '../../../../selectors/featureFlagController/assetsTrendingTokens';
19+
import { useAccountMenuEnabled } from '../../../../selectors/featureFlagController/accountMenu/useAccountMenuEnabled';
1920

2021
// Minimal descriptor interface for tests - only includes what TabBar component uses
2122
interface TestTabDescriptor {
@@ -33,6 +34,14 @@ interface TestDescriptors {
3334
// Mock trending tokens feature flag selector
3435
jest.mock('../../../../selectors/featureFlagController/assetsTrendingTokens');
3536

37+
// Mock account menu feature flag hook
38+
jest.mock(
39+
'../../../../selectors/featureFlagController/accountMenu/useAccountMenuEnabled',
40+
() => ({
41+
useAccountMenuEnabled: jest.fn(() => false),
42+
}),
43+
);
44+
3645
// Mock the navigation object with proper typing
3746
const navigation: NavigationHelpers<ParamListBase> = {
3847
navigate: jest.fn(),
@@ -124,7 +133,10 @@ describe('TabBar', () => {
124133
expect(toJSON()).toMatchSnapshot();
125134
});
126135

127-
it('navigates to the correct screen when a tab is pressed', () => {
136+
it('navigates to the correct screen when a tab is pressed and account menu is disabled', () => {
137+
// Explicitly disable the account menu feature flag for this test
138+
jest.mocked(useAccountMenuEnabled).mockReturnValue(false);
139+
128140
const { getByTestId } = renderWithProvider(
129141
<TabBar
130142
state={state as TabNavigationState<ParamListBase>}
@@ -160,7 +172,7 @@ describe('TabBar', () => {
160172

161173
fireEvent.press(getByTestId(`tab-bar-item-${TabBarIconKey.Setting}`));
162174
expect(navigation.navigate).toHaveBeenCalledWith(Routes.SETTINGS_VIEW, {
163-
screen: Routes.ACCOUNTS_MENU_VIEW,
175+
screen: 'Settings',
164176
});
165177
});
166178

@@ -255,4 +267,23 @@ describe('TabBar', () => {
255267
fireEvent.press(getByTestId(`tab-bar-item-${TabBarIconKey.Trending}`));
256268
expect(navigation.navigate).not.toHaveBeenCalledWith(Routes.TRENDING_VIEW);
257269
});
270+
271+
it('navigates to Accounts Menu when settings tab is pressed and account menu is enabled', () => {
272+
// Enable the account menu feature flag for this test
273+
jest.mocked(useAccountMenuEnabled).mockReturnValue(true);
274+
275+
const { getByTestId } = renderWithProvider(
276+
<TabBar
277+
state={state as TabNavigationState<ParamListBase>}
278+
descriptors={descriptors as Record<string, ExtendedBottomTabDescriptor>}
279+
navigation={navigation}
280+
/>,
281+
{ state: mockInitialState },
282+
);
283+
284+
fireEvent.press(getByTestId(`tab-bar-item-${TabBarIconKey.Setting}`));
285+
expect(navigation.navigate).toHaveBeenCalledWith(Routes.SETTINGS_VIEW, {
286+
screen: Routes.ACCOUNTS_MENU_VIEW,
287+
});
288+
});
258289
});

app/component-library/components/Navigation/TabBar/TabBar.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
} from './TabBar.constants';
2929
import { selectChainId } from '../../../../selectors/networkController';
3030
import { selectAssetsTrendingTokensEnabled } from '../../../../selectors/featureFlagController/assetsTrendingTokens';
31+
import { useAccountMenuEnabled } from '../../../../selectors/featureFlagController/accountMenu/useAccountMenuEnabled';
3132

3233
const TabBar = ({ state, descriptors, navigation }: TabBarProps) => {
3334
const { trackEvent, createEventBuilder } = useMetrics();
@@ -36,6 +37,7 @@ const TabBar = ({ state, descriptors, navigation }: TabBarProps) => {
3637
const isAssetsTrendingTokensEnabled = useSelector(
3738
selectAssetsTrendingTokensEnabled,
3839
);
40+
const isAccountMenuEnabled = useAccountMenuEnabled();
3941
const tabBarRef = useRef(null);
4042
const previousTabIndexRef = useRef<number>(state.index);
4143
const tw = useTailwind();
@@ -98,7 +100,9 @@ const TabBar = ({ state, descriptors, navigation }: TabBarProps) => {
98100
break;
99101
case Routes.SETTINGS_VIEW:
100102
navigation.navigate(Routes.SETTINGS_VIEW, {
101-
screen: Routes.ACCOUNTS_MENU_VIEW,
103+
screen: isAccountMenuEnabled
104+
? Routes.ACCOUNTS_MENU_VIEW
105+
: 'Settings',
102106
});
103107
break;
104108
case Routes.TRENDING_VIEW:
@@ -138,6 +142,7 @@ const TabBar = ({ state, descriptors, navigation }: TabBarProps) => {
138142
createEventBuilder,
139143
tw,
140144
isAssetsTrendingTokensEnabled,
145+
isAccountMenuEnabled,
141146
],
142147
);
143148

0 commit comments

Comments
 (0)