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:
parent
c4e7b5532d
commit
b981377304
@ -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,
|
||||||
};
|
};
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
@ -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,
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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()}
|
||||||
|
Loading…
Reference in New Issue
Block a user