Skip to content

Commit 67d4f18

Browse files
n3psNidhiKJha
andauthored
fix: feature flag sidepanel context menu cp-13.10.3 (#38220)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> fixes #38222 Wraps the sidepanel context menu configuration with the remote feature flag [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/38220?quickstart=1) ## **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: fix: feature flag sidepanel context menu ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Gates the sidepanel context menu behind a remote feature flag and refactors its setup into a dedicated module initialized after background startup. > > - **Background**: > - **Sidepanel context menu**: > - Extracted setup to `app/scripts/lib/sidepanel-context-menu.ts` with `initSidePanelContextMenu(controller)`. > - Creates/removes `openSidePanel` menu based on `IS_SIDEPANEL` and `remoteFeatureFlags.extensionUxSidepanel`; opens side panel on click. > - Subscribes to `RemoteFeatureFlagController:stateChange` to toggle menu dynamically. > - **Initialization**: > - In `app/scripts/background.js`, register sidepanel context menu via `lazyListener.once('runtime','onInstalled')`, calling `handleSidePanelContextMenu()` after `handleOnInstalled`. > - New `handleSidePanelContextMenu` waits for `isInitialized` then invokes `initSidePanelContextMenu(controller)`. > - Removes prior inline context menu registration logic. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit bc69ea7. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: NidhiKJha <[email protected]>
1 parent 12487f7 commit 67d4f18

File tree

2 files changed

+76
-21
lines changed

2 files changed

+76
-21
lines changed

app/scripts/background.js

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import {
5555
CorruptionHandler,
5656
hasVault,
5757
} from './lib/state-corruption/state-corruption-recovery';
58+
import { initSidePanelContextMenu } from './lib/sidepanel-context-menu';
5859
import {
5960
backedUpStateKeys,
6061
PersistenceManager,
@@ -180,7 +181,10 @@ const ONE_SECOND_IN_MILLISECONDS = 1_000;
180181
// Timeout for initializing phishing warning page.
181182
const PHISHING_WARNING_PAGE_TIMEOUT = ONE_SECOND_IN_MILLISECONDS;
182183

183-
lazyListener.once('runtime', 'onInstalled').then(handleOnInstalled);
184+
lazyListener.once('runtime', 'onInstalled').then((details) => {
185+
handleOnInstalled(details);
186+
handleSidePanelContextMenu();
187+
});
184188

185189
/**
186190
* This deferred Promise is used to track whether initialization has finished.
@@ -1657,26 +1661,14 @@ function onInstall() {
16571661
platform.openExtensionInBrowser();
16581662
}
16591663
}
1660-
// Only register sidepanel context menu for browsers that support it (Chrome/Edge/Brave)
1661-
// and when the feature flag is enabled
1662-
if (
1663-
browser.contextMenus &&
1664-
browser.sidePanel &&
1665-
process.env.IS_SIDEPANEL?.toString() === 'true'
1666-
) {
1667-
browser.runtime.onInstalled.addListener(() => {
1668-
browser.contextMenus.create({
1669-
id: 'openSidePanel',
1670-
title: 'MetaMask Sidepanel',
1671-
contexts: ['all'],
1672-
});
1673-
});
1674-
browser.contextMenus.onClicked.addListener((info, tab) => {
1675-
if (info.menuItemId === 'openSidePanel') {
1676-
// This will open the panel in all the pages on the current window.
1677-
browser.sidePanel.open({ windowId: tab.windowId });
1678-
}
1679-
});
1664+
1665+
/**
1666+
* Handles the onInstalled event for sidepanel context menu creation.
1667+
* This is registered via lazyListener to catch the event at module load time.
1668+
*/
1669+
async function handleSidePanelContextMenu() {
1670+
await isInitialized;
1671+
await initSidePanelContextMenu(controller);
16801672
}
16811673

16821674
/**
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import browser from 'webextension-polyfill';
2+
import type { RemoteFeatureFlagControllerState } from '@metamask/remote-feature-flag-controller';
3+
import type MetamaskController from '../metamask-controller';
4+
5+
const MENU_ITEM_ID = 'openSidePanel';
6+
7+
// Type augmentation for sidePanel API (not yet in webextension-polyfill types)
8+
type BrowserWithSidePanel = typeof browser & {
9+
sidePanel?: {
10+
open: (options: { windowId: number }) => Promise<void>;
11+
};
12+
};
13+
14+
export async function initSidePanelContextMenu(
15+
controller: MetamaskController,
16+
): Promise<void> {
17+
const browserWithSidePanel = browser as BrowserWithSidePanel;
18+
19+
if (
20+
!browser.contextMenus ||
21+
!browserWithSidePanel.sidePanel ||
22+
process.env.IS_SIDEPANEL?.toString() !== 'true'
23+
) {
24+
return;
25+
}
26+
27+
const isEnabled = (state?: {
28+
remoteFeatureFlags?: { extensionUxSidepanel?: boolean };
29+
}) => state?.remoteFeatureFlags?.extensionUxSidepanel !== false;
30+
31+
const createMenu = () => {
32+
browser.contextMenus.create({
33+
id: MENU_ITEM_ID,
34+
title: 'MetaMask Sidepanel',
35+
contexts: ['all'],
36+
});
37+
};
38+
39+
const removeMenu = () => {
40+
browser.contextMenus.remove(MENU_ITEM_ID);
41+
};
42+
43+
if (isEnabled(controller?.remoteFeatureFlagController?.state)) {
44+
createMenu();
45+
}
46+
47+
browser.contextMenus.onClicked.addListener((info, tab) => {
48+
if (info.menuItemId === MENU_ITEM_ID && tab?.windowId) {
49+
browserWithSidePanel.sidePanel?.open({ windowId: tab.windowId });
50+
}
51+
});
52+
53+
controller?.controllerMessenger?.subscribe(
54+
'RemoteFeatureFlagController:stateChange',
55+
(state: RemoteFeatureFlagControllerState) => {
56+
if (isEnabled(state)) {
57+
createMenu();
58+
} else {
59+
removeMenu();
60+
}
61+
},
62+
);
63+
}

0 commit comments

Comments
 (0)