1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 01:39:44 +01:00

UX: Multichain: Disable network and account picker when necessary (#18909)

This commit is contained in:
David Walsh 2023-05-08 12:32:39 -05:00 committed by GitHub
parent c4e7b5532d
commit b981377304
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 18 deletions

View File

@ -19,7 +19,7 @@ import {
Size, Size,
} from '../../../helpers/constants/design-system'; } from '../../../helpers/constants/design-system';
export const AccountPicker = ({ address, name, onClick }) => { export const AccountPicker = ({ address, name, onClick, disabled }) => {
const useBlockie = useSelector((state) => state.metamask.useBlockie); const useBlockie = useSelector((state) => state.metamask.useBlockie);
return ( return (
@ -34,6 +34,7 @@ export const AccountPicker = ({ address, name, onClick }) => {
gap: 2, gap: 2,
alignItems: AlignItems.center, alignItems: AlignItems.center,
}} }}
disabled={disabled}
> >
<AvatarAccount <AvatarAccount
variant={ variant={
@ -70,4 +71,8 @@ AccountPicker.propTypes = {
* Action to perform when the account picker is clicked * Action to perform when the account picker is clicked
*/ */
onClick: PropTypes.func.isRequired, onClick: PropTypes.func.isRequired,
/**
* Represents if the AccountPicker should be actionable
*/
disabled: PropTypes.bool.isRequired,
}; };

View File

@ -3,15 +3,18 @@ import classnames from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import browser from 'webextension-polyfill'; import browser from 'webextension-polyfill';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom'; import { useHistory, matchPath } from 'react-router-dom';
import { MetaMetricsContext } from '../../../contexts/metametrics'; import { MetaMetricsContext } from '../../../contexts/metametrics';
import { import {
MetaMetricsEventCategory, MetaMetricsEventCategory,
MetaMetricsEventName, MetaMetricsEventName,
} from '../../../../shared/constants/metametrics'; } from '../../../../shared/constants/metametrics';
import { import {
BUILD_QUOTE_ROUTE,
CONFIRM_TRANSACTION_ROUTE,
CONNECTED_ACCOUNTS_ROUTE, CONNECTED_ACCOUNTS_ROUTE,
DEFAULT_ROUTE, DEFAULT_ROUTE,
SWAPS_ROUTE,
} from '../../../helpers/constants/routes'; } from '../../../helpers/constants/routes';
import { import {
@ -53,8 +56,9 @@ import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
import ConnectedStatusIndicator from '../../app/connected-status-indicator'; import ConnectedStatusIndicator from '../../app/connected-status-indicator';
import { useI18nContext } from '../../../hooks/useI18nContext'; import { useI18nContext } from '../../../hooks/useI18nContext';
import { getCompletedOnboarding } from '../../../ducks/metamask/metamask'; import { getCompletedOnboarding } from '../../../ducks/metamask/metamask';
import { getSendStage, SEND_STAGES } from '../../../ducks/send';
export const AppHeader = ({ onClick }) => { export const AppHeader = ({ location }) => {
const trackEvent = useContext(MetaMetricsContext); const trackEvent = useContext(MetaMetricsContext);
const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false); const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false);
const [multichainProductTourStep, setMultichainProductTourStep] = useState(1); const [multichainProductTourStep, setMultichainProductTourStep] = useState(1);
@ -87,6 +91,33 @@ export const AppHeader = ({ onClick }) => {
.querySelector('[dir]') .querySelector('[dir]')
?.getAttribute('dir'); ?.getAttribute('dir');
// Disable the network and account pickers if the user is in
// a critical flow
const sendStage = useSelector(getSendStage);
const isConfirmationPage = Boolean(
matchPath(location.pathname, {
path: CONFIRM_TRANSACTION_ROUTE,
exact: false,
}),
);
const isTransactionEditPage = [
SEND_STAGES.EDIT,
SEND_STAGES.DRAFT,
SEND_STAGES.ADD_RECIPIENT,
].includes(sendStage);
const isSwapsPage = Boolean(
matchPath(location.pathname, { path: SWAPS_ROUTE, exact: false }),
);
const isSwapsBuildQuotePage = Boolean(
matchPath(location.pathname, { path: BUILD_QUOTE_ROUTE, exact: false }),
);
const disablePickers =
isConfirmationPage ||
isTransactionEditPage ||
(isSwapsPage && !isSwapsBuildQuotePage);
const disableNetworkPicker = isSwapsPage || disablePickers;
// Callback for network dropdown // Callback for network dropdown
const networkOpenCallback = useCallback(() => { const networkOpenCallback = useCallback(() => {
dispatch(toggleNetworkMenu()); dispatch(toggleNetworkMenu());
@ -113,12 +144,7 @@ export const AppHeader = ({ onClick }) => {
> >
<MetafoxLogo <MetafoxLogo
unsetIconHeight unsetIconHeight
onClick={async () => { onClick={async () => history.push(DEFAULT_ROUTE)}
if (onClick) {
await onClick();
}
history.push(DEFAULT_ROUTE);
}}
/> />
</Box> </Box>
) : null} ) : null}
@ -160,6 +186,7 @@ export const AppHeader = ({ onClick }) => {
size={Size.SM} size={Size.SM}
onClick={networkOpenCallback} onClick={networkOpenCallback}
display={[DISPLAY.FLEX, DISPLAY.NONE]} // show on popover hide on desktop display={[DISPLAY.FLEX, DISPLAY.NONE]} // show on popover hide on desktop
disabled={disableNetworkPicker}
/> />
{popupStatus ? null : ( {popupStatus ? null : (
<div> <div>
@ -170,6 +197,7 @@ export const AppHeader = ({ onClick }) => {
onClick={networkOpenCallback} onClick={networkOpenCallback}
display={[DISPLAY.NONE, DISPLAY.FLEX]} // show on desktop hide on popover display={[DISPLAY.NONE, DISPLAY.FLEX]} // show on desktop hide on popover
className="multichain-app-header__contents__network-picker" className="multichain-app-header__contents__network-picker"
disabled={disableNetworkPicker}
/> />
</div> </div>
)} )}
@ -205,6 +233,7 @@ export const AppHeader = ({ onClick }) => {
}, },
}); });
}} }}
disabled={disablePickers}
/> />
<Box <Box
display={DISPLAY.FLEX} display={DISPLAY.FLEX}
@ -334,9 +363,6 @@ export const AppHeader = ({ onClick }) => {
<MetafoxLogo <MetafoxLogo
unsetIconHeight unsetIconHeight
onClick={async () => { onClick={async () => {
if (onClick) {
await onClick();
}
history.push(DEFAULT_ROUTE); history.push(DEFAULT_ROUTE);
}} }}
/> />
@ -350,7 +376,7 @@ export const AppHeader = ({ onClick }) => {
AppHeader.propTypes = { AppHeader.propTypes = {
/** /**
* The onClick handler to be passed to the MetaMask Logo in the App Header * The location object for the application
*/ */
onClick: PropTypes.func, location: PropTypes.object,
}; };

View File

@ -11,10 +11,13 @@ export default {
decorators: [(story) => <Provider store={store}>{story()}</Provider>], decorators: [(story) => <Provider store={store}>{story()}</Provider>],
component: AppHeader, component: AppHeader,
argTypes: { argTypes: {
onClick: { location: {
action: 'onClick', control: 'object',
}, },
}, },
args: {
location: { pathname: '' },
},
}; };
const customNetworkUnlockedData = { const customNetworkUnlockedData = {
...testData, ...testData,

View File

@ -2,6 +2,7 @@ import React from 'react';
import configureStore from 'redux-mock-store'; import configureStore from 'redux-mock-store';
import { CHAIN_IDS } from '../../../../shared/constants/network'; import { CHAIN_IDS } from '../../../../shared/constants/network';
import { renderWithProvider } from '../../../../test/lib/render-helpers'; import { renderWithProvider } from '../../../../test/lib/render-helpers';
import { SEND_STAGES } from '../../../ducks/send';
import { AppHeader } from '.'; import { AppHeader } from '.';
describe('App Header', () => { describe('App Header', () => {
@ -100,11 +101,17 @@ describe('App Header', () => {
appState: { appState: {
onboardedInThisUISession: false, onboardedInThisUISession: false,
}, },
send: {
stage: SEND_STAGES.INACTIVE,
},
}; };
const mockStore = configureStore(); const mockStore = configureStore();
const store = mockStore(mockState); const store = mockStore(mockState);
const { container } = renderWithProvider(<AppHeader />, store); const { container } = renderWithProvider(
<AppHeader location={{ pathname: '' }} />,
store,
);
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
}); });
}); });

View File

@ -498,6 +498,7 @@ export default class Routes extends Component {
isNetworkMenuOpen, isNetworkMenuOpen,
toggleNetworkMenu, toggleNetworkMenu,
accountDetailsAddress, accountDetailsAddress,
location,
} = this.props; } = this.props;
const loadMessage = const loadMessage =
loadingMessage || isNetworkLoading loadingMessage || isNetworkLoading
@ -542,7 +543,7 @@ export default class Routes extends Component {
<Alert visible={this.props.alertOpen} msg={alertMessage} /> <Alert visible={this.props.alertOpen} msg={alertMessage} />
{!this.hideAppHeader() && {!this.hideAppHeader() &&
(process.env.MULTICHAIN ? ( (process.env.MULTICHAIN ? (
<MultichainAppHeader /> <MultichainAppHeader location={location} />
) : ( ) : (
<AppHeader <AppHeader
hideNetworkIndicator={this.onInitializationUnlockPage()} hideNetworkIndicator={this.onInitializationUnlockPage()}