mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
UX: Multichain: App header (#18363)
* UX: Multichain: App header * Export app header, provide required information, put feature flag in place * Provide available data * Implement account picker -- centered and opens account popover * Remove backgrounds, use isUnlocked * Fix placement of the global menu * Show logo when unlocked * Add selector for getting current network, provide props to AvatarNetwork and PickerNetwork * Wire up the network menu to the header * fixed ui for all the screens * updated story for header * fixed import and header settings * updated lint error * fixed tests * updated header * removed test * updated snapshot test * updated network menu * updated changes * removed comment from menu bar * updated css * updated test for network list menu * updated stylesheet * updated ButtonIcon import --------- Co-authored-by: NidhiKJha <menidhikjha@gmail.com>
This commit is contained in:
parent
643a89f24d
commit
eb51460cae
@ -208,6 +208,7 @@ browser.runtime.onConnectExternal.addListener(async (...args) => {
|
|||||||
* @property {boolean} isInitialized - Whether the first vault has been created.
|
* @property {boolean} isInitialized - Whether the first vault has been created.
|
||||||
* @property {boolean} isUnlocked - Whether the vault is currently decrypted and accounts are available for selection.
|
* @property {boolean} isUnlocked - Whether the vault is currently decrypted and accounts are available for selection.
|
||||||
* @property {boolean} isAccountMenuOpen - Represents whether the main account selection UI is currently displayed.
|
* @property {boolean} isAccountMenuOpen - Represents whether the main account selection UI is currently displayed.
|
||||||
|
* @property {boolean} isNetworkMenuOpen - Represents whether the main network selection UI is currently displayed.
|
||||||
* @property {object} identities - An object matching lower-case hex addresses to Identity objects with "address" and "name" (nickname) keys.
|
* @property {object} identities - An object matching lower-case hex addresses to Identity objects with "address" and "name" (nickname) keys.
|
||||||
* @property {object} unapprovedTxs - An object mapping transaction hashes to unapproved transactions.
|
* @property {object} unapprovedTxs - An object mapping transaction hashes to unapproved transactions.
|
||||||
* @property {object} networkConfigurations - A list of network configurations, containing RPC provider details (eg chainId, rpcUrl, rpcPreferences).
|
* @property {object} networkConfigurations - A list of network configurations, containing RPC provider details (eg chainId, rpcUrl, rpcPreferences).
|
||||||
|
@ -16,7 +16,6 @@ import { getOriginOfCurrentTab } from '../../../selectors';
|
|||||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||||
import { ButtonIcon } from '../../component-library/button-icon/deprecated';
|
import { ButtonIcon } from '../../component-library/button-icon/deprecated';
|
||||||
import { ICON_NAMES } from '../../component-library/icon/deprecated';
|
import { ICON_NAMES } from '../../component-library/icon/deprecated';
|
||||||
import { GlobalMenu } from '../../multichain/global-menu';
|
|
||||||
import AccountOptionsMenu from './account-options-menu';
|
import AccountOptionsMenu from './account-options-menu';
|
||||||
|
|
||||||
export default function MenuBar() {
|
export default function MenuBar() {
|
||||||
@ -34,7 +33,7 @@ export default function MenuBar() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="menu-bar">
|
<div className="menu-bar">
|
||||||
{showStatus ? ( // TODO: Move the connection status menu icon to the correct position in header once we implement the new header
|
{showStatus ? (
|
||||||
<ConnectedStatusIndicator
|
<ConnectedStatusIndicator
|
||||||
onClick={() => history.push(CONNECTED_ACCOUNTS_ROUTE)}
|
onClick={() => history.push(CONNECTED_ACCOUNTS_ROUTE)}
|
||||||
/>
|
/>
|
||||||
@ -58,18 +57,12 @@ export default function MenuBar() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
{accountOptionsMenuOpen &&
|
{accountOptionsMenuOpen && (
|
||||||
(process.env.MULTICHAIN ? (
|
|
||||||
<GlobalMenu
|
|
||||||
anchorElement={ref.current}
|
|
||||||
closeMenu={() => setAccountOptionsMenuOpen(false)}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<AccountOptionsMenu
|
<AccountOptionsMenu
|
||||||
anchorElement={ref.current}
|
anchorElement={ref.current}
|
||||||
onClose={() => setAccountOptionsMenuOpen(false)}
|
onClose={() => setAccountOptionsMenuOpen(false)}
|
||||||
/>
|
/>
|
||||||
))}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,6 @@ export const AccountListMenu = ({ onClose }) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
dispatch(setSelectedAccount(account.address));
|
dispatch(setSelectedAccount(account.address));
|
||||||
onClose();
|
|
||||||
}}
|
}}
|
||||||
identity={account}
|
identity={account}
|
||||||
key={account.address}
|
key={account.address}
|
||||||
|
@ -0,0 +1,224 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`App Header should match snapshot 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="box multichain-app-header multichain-app-header-shadow box--display-flex box--flex-direction-row box--align-items-center box--width-full box--background-color-background-default"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="box multichain-app-header__lock-contents box--padding-2 box--display-flex box--gap-2 box--flex-direction-row box--justify-content-space-between box--align-items-center box--width-full box--background-color-background-default"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="box mm-picker-network box--padding-right-4 box--padding-left-2 box--display-flex box--gap-2 box--flex-direction-row box--align-items-center box--background-color-background-alternative box--rounded-pill"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-picker-network__avatar-network mm-text--body-xs mm-text--text-transform-uppercase box--display-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-text-default box--background-color-background-alternative box--rounded-full box--border-color-transparent box--border-style-solid box--border-width-1"
|
||||||
|
>
|
||||||
|
G
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
class="box mm-text mm-text--body-sm mm-text--ellipsis box--flex-direction-row box--color-text-default"
|
||||||
|
>
|
||||||
|
Goerli
|
||||||
|
</p>
|
||||||
|
<span
|
||||||
|
class="box mm-picker-network__arrow-down-icon mm-icon mm-icon--size-xs box--display-inline-block box--flex-direction-row box--color-icon-default"
|
||||||
|
style="mask-image: url('./images/icons/arrow-down.svg');"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
class="app-header__logo-container app-header__logo-container--clickable"
|
||||||
|
data-testid="app-header-logo"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="app-header__metafox-logo--horizontal"
|
||||||
|
height="30"
|
||||||
|
viewBox="0 0 1311 242"
|
||||||
|
width="162"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
fill="var(--color-text-default)"
|
||||||
|
transform="translate(361 61)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m796.7 60.9c-6.8-4.5-14.3-7.7-21.4-11.7-4.6-2.6-9.5-4.9-13.5-8.2-6.8-5.6-5.4-16.6 1.7-21.4 10.2-6.8 27.1-3 28.9 10.9 0 .3.3.5.6.5h15.4c.4 0 .7-.3.6-.7-.8-9.6-4.5-17.6-11.3-22.7-6.5-4.9-13.9-7.5-21.8-7.5-40.7 0-44.4 43.1-22.5 56.7 2.5 1.6 24 12.4 31.6 17.1s10 13.3 6.7 20.1c-3 6.2-10.8 10.5-18.6 10-8.5-.5-15.1-5.1-17.4-12.3-.4-1.3-.6-3.8-.6-4.9 0-.3-.3-.6-.6-.6h-16.7c-.3 0-.6.3-.6.6 0 12.1 3 18.8 11.2 24.9 7.7 5.8 16.1 8.2 24.8 8.2 22.8 0 34.6-12.9 37-26.3 2.1-13.1-1.8-24.9-13.5-32.7z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m71.6 2.3h-7.4-8.1c-.3 0-.5.2-.6.4l-13.7 45.2c-.2.6-1 .6-1.2 0l-13.7-45.2c-.1-.3-.3-.4-.6-.4h-8.1-7.4-10c-.3 0-.6.3-.6.6v115.4c0 .3.3.6.6.6h16.7c.3 0 .6-.3.6-.6v-87.7c0-.7 1-.8 1.2-.2l13.8 45.5 1 3.2c.1.3.3.4.6.4h12.8c.3 0 .5-.2.6-.4l1-3.2 13.8-45.5c.2-.7 1.2-.5 1.2.2v87.7c0 .3.3.6.6.6h16.7c.3 0 .6-.3.6-.6v-115.4c0-.3-.3-.6-.6-.6z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m541 2.3c-.3 0-.5.2-.6.4l-13.7 45.2c-.2.6-1 .6-1.2 0l-13.7-45.2c-.1-.3-.3-.4-.6-.4h-25.4c-.3 0-.6.3-.6.6v115.4c0 .3.3.6.6.6h16.7c.3 0 .6-.3.6-.6v-87.7c0-.7 1-.8 1.2-.2l13.8 45.5 1 3.2c.1.3.3.4.6.4h12.8c.3 0 .5-.2.6-.4l1-3.2 13.8-45.5c.2-.7 1.2-.5 1.2.2v87.7c0 .3.3.6.6.6h16.7c.3 0 .6-.3.6-.6v-115.4c0-.3-.3-.6-.6-.6z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m325.6 2.3h-31.1-16.7-31.1c-.3 0-.6.3-.6.6v14.4c0 .3.3.6.6.6h30.5v100.4c0 .3.3.6.6.6h16.7c.3 0 .6-.3.6-.6v-100.4h30.5c.3 0 .6-.3.6-.6v-14.4c0-.3-.2-.6-.6-.6z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m424.1 118.9h15.2c.4 0 .7-.4.6-.8l-31.4-115.8c-.1-.3-.3-.4-.6-.4h-5.8-10.2-5.8c-.3 0-.5.2-.6.4l-31.4 115.8c-.1.4.2.8.6.8h15.2c.3 0 .5-.2.6-.4l9.1-33.7c.1-.3.3-.4.6-.4h33.6c.3 0 .5.2.6.4l9.1 33.7c.1.2.4.4.6.4zm-39.9-51 12.2-45.1c.2-.6 1-.6 1.2 0l12.2 45.1c.1.4-.2.8-.6.8h-24.4c-.4 0-.7-.4-.6-.8z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m683.3 118.9h15.2c.4 0 .7-.4.6-.8l-31.4-115.8c-.1-.3-.3-.4-.6-.4h-5.8-10.2-5.8c-.3 0-.5.2-.6.4l-31.4 115.8c-.1.4.2.8.6.8h15.2c.3 0 .5-.2.6-.4l9.1-33.7c.1-.3.3-.4.6-.4h33.6c.3 0 .5.2.6.4l9.1 33.7c.1.2.3.4.6.4zm-39.9-51 12.2-45.1c.2-.6 1-.6 1.2 0l12.2 45.1c.1.4-.2.8-.6.8h-24.4c-.4 0-.7-.4-.6-.8z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m149.8 101.8v-35.8c0-.3.3-.6.6-.6h44.5c.3 0 .6-.3.6-.6v-14.4c0-.3-.3-.6-.6-.6h-44.5c-.3 0-.6-.3-.6-.6v-30.6c0-.3.3-.6.6-.6h50.6c.3 0 .6-.3.6-.6v-14.4c0-.3-.3-.6-.6-.6h-51.2-17.3c-.3 0-.6.3-.6.6v15 31.9 15.6 37 15.8c0 .3.3.6.6.6h17.3 53.3c.3 0 .6-.3.6-.6v-15.2c0-.3-.3-.6-.6-.6h-52.8c-.3-.1-.5-.3-.5-.7z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m949.3 117.9-57.8-59.7c-.2-.2-.2-.6 0-.8l52-54c.4-.4.1-1-.4-1h-21.3c-.2 0-.3.1-.4.2l-44.1 45.8c-.4.4-1 .1-1-.4v-45c0-.3-.3-.6-.6-.6h-16.7c-.3 0-.6.3-.6.6v115.4c0 .3.3.6.6.6h16.7c.3 0 .6-.3.6-.6v-50.8c0-.5.7-.8 1-.4l50 51.6c.1.1.3.2.4.2h21.3c.4-.1.7-.8.3-1.1z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
transform="translate(1 1)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m246.1.2-101.1 75 18.8-44.2z"
|
||||||
|
fill="#e17726"
|
||||||
|
stroke="#e17726"
|
||||||
|
/>
|
||||||
|
<g
|
||||||
|
fill="#e27625"
|
||||||
|
stroke="#e27625"
|
||||||
|
transform="translate(2)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m10.9.2 100.2 75.7-17.9-44.9z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m207.7 174.1-26.9 41.2 57.6 15.9 16.5-56.2z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m.2 175 16.4 56.2 57.5-15.9-26.8-41.2z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m71 104.5-16 24.2 57 2.6-1.9-61.5z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m184 104.5-39.7-35.4-1.3 62.2 57-2.6z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m74.1 215.3 34.5-16.7-29.7-23.2z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m146.4 198.6 34.4 16.7-4.7-39.9z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
fill="#d5bfb2"
|
||||||
|
stroke="#d5bfb2"
|
||||||
|
transform="translate(76 198)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m106.8 17.3-34.4-16.7 2.8 22.4-.3 9.5z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m.1 17.3 32 15.2-.2-9.5 2.7-22.4z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
d="m108.7 160.6-28.6-8.4 20.2-9.3z"
|
||||||
|
fill="#233447"
|
||||||
|
stroke="#233447"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m150.3 160.6 8.4-17.7 20.3 9.3z"
|
||||||
|
fill="#233447"
|
||||||
|
stroke="#233447"
|
||||||
|
/>
|
||||||
|
<g
|
||||||
|
fill="#cc6228"
|
||||||
|
stroke="#cc6228"
|
||||||
|
transform="translate(49 128)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m27.1 87.3 5-41.2-31.8.9z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m128.9 46.1 4.9 41.2 26.9-40.3z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m153 .7-57 2.6 5.3 29.3 8.4-17.7 20.3 9.3z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m31.1 24.2 20.2-9.3 8.4 17.7 5.3-29.3-57-2.6z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
fill="#e27525"
|
||||||
|
stroke="#e27525"
|
||||||
|
transform="translate(57 128)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m0 .7 23.9 46.7-.8-23.2z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m122 24.2-.9 23.2 23.9-46.7z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m57 3.3-5.3 29.3 6.7 34.6 1.5-45.6z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m88 3.3-2.8 18.2 1.4 45.7 6.7-34.6z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
d="m150.3 160.6-6.7 34.6 4.8 3.4 29.7-23.2.9-23.2z"
|
||||||
|
fill="#f5841f"
|
||||||
|
stroke="#f5841f"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m80.1 152.2.8 23.2 29.7 23.2 4.8-3.4-6.7-34.6z"
|
||||||
|
fill="#f5841f"
|
||||||
|
stroke="#f5841f"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m150.9 230.5.3-9.5-2.6-2.2h-38.2l-2.5 2.2.2 9.5-32-15.2 11.2 9.2 22.7 15.7h38.9l22.8-15.7 11.1-9.2z"
|
||||||
|
fill="#c0ac9d"
|
||||||
|
stroke="#c0ac9d"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m148.4 198.6-4.8-3.4h-28.2l-4.8 3.4-2.7 22.4 2.5-2.2h38.2l2.6 2.2z"
|
||||||
|
fill="#161616"
|
||||||
|
stroke="#161616"
|
||||||
|
/>
|
||||||
|
<g
|
||||||
|
fill="#763e1a"
|
||||||
|
stroke="#763e1a"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m250.4 80.1 8.5-41.4-12.8-38.5-97.7 72.5 37.6 31.8 53.1 15.5 11.7-13.7-5.1-3.7 8.1-7.4-6.2-4.8 8.1-6.2z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m.1 38.7 8.6 41.4-5.5 4.1 8.2 6.2-6.2 4.8 8.1 7.4-5.1 3.7 11.7 13.7 53.1-15.5 37.6-31.8-97.7-72.5z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
fill="#f5841f"
|
||||||
|
stroke="#f5841f"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m239.1 120-53.1-15.5 16 24.2-23.9 46.7 31.6-.4h47.2z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m73 104.5-53.1 15.5-17.7 55h47.1l31.6.4-23.9-46.7z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m145 131.3 3.4-58.6 15.4-41.7h-68.6l15.4 41.7 3.4 58.6 1.3 18.4.1 45.5h28.2l.1-45.5z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<img
|
||||||
|
alt=""
|
||||||
|
class="app-header__metafox-logo--icon"
|
||||||
|
src="./images/logo/metamask-fox.svg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
215
ui/components/multichain/app-header/app-header.js
Normal file
215
ui/components/multichain/app-header/app-header.js
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
import React, { useContext, useState, useRef } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import browser from 'webextension-polyfill';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||||
|
import {
|
||||||
|
MetaMetricsEventCategory,
|
||||||
|
MetaMetricsEventName,
|
||||||
|
} from '../../../../shared/constants/metametrics';
|
||||||
|
import {
|
||||||
|
CONNECTED_ACCOUNTS_ROUTE,
|
||||||
|
DEFAULT_ROUTE,
|
||||||
|
} from '../../../helpers/constants/routes';
|
||||||
|
|
||||||
|
import {
|
||||||
|
AlignItems,
|
||||||
|
BackgroundColor,
|
||||||
|
BLOCK_SIZES,
|
||||||
|
DISPLAY,
|
||||||
|
JustifyContent,
|
||||||
|
Size,
|
||||||
|
} from '../../../helpers/constants/design-system';
|
||||||
|
import { AvatarNetwork, Button, PickerNetwork } from '../../component-library';
|
||||||
|
import { ButtonIcon } from '../../component-library/button-icon/deprecated';
|
||||||
|
import { ICON_NAMES } from '../../component-library/icon/deprecated';
|
||||||
|
import {
|
||||||
|
getCurrentNetwork,
|
||||||
|
getOriginOfCurrentTab,
|
||||||
|
getSelectedIdentity,
|
||||||
|
} from '../../../selectors';
|
||||||
|
import { GlobalMenu, AccountPicker } from '..';
|
||||||
|
|
||||||
|
import Box from '../../ui/box/box';
|
||||||
|
import { toggleAccountMenu, toggleNetworkMenu } from '../../../store/actions';
|
||||||
|
import MetafoxLogo from '../../ui/metafox-logo';
|
||||||
|
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
||||||
|
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
|
||||||
|
import ConnectedStatusIndicator from '../../app/connected-status-indicator';
|
||||||
|
|
||||||
|
export const AppHeader = ({ onClick }) => {
|
||||||
|
const trackEvent = useContext(MetaMetricsContext);
|
||||||
|
const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false);
|
||||||
|
const menuRef = useRef(false);
|
||||||
|
const origin = useSelector(getOriginOfCurrentTab);
|
||||||
|
const history = useHistory();
|
||||||
|
const isUnlocked = useSelector((state) => state.metamask.isUnlocked);
|
||||||
|
|
||||||
|
// Used for account picker
|
||||||
|
const identity = useSelector(getSelectedIdentity);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
// Used for network icon / dropdown
|
||||||
|
const currentNetwork = useSelector(getCurrentNetwork);
|
||||||
|
|
||||||
|
// used to get the environment and connection status
|
||||||
|
const popupStatus = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP;
|
||||||
|
const showStatus =
|
||||||
|
getEnvironmentType() === ENVIRONMENT_TYPE_POPUP &&
|
||||||
|
origin &&
|
||||||
|
origin !== browser.runtime.id;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isUnlocked && !popupStatus ? (
|
||||||
|
<Box
|
||||||
|
display={DISPLAY.FLEX}
|
||||||
|
alignItems={AlignItems.center}
|
||||||
|
margin={2}
|
||||||
|
className="multichain-app-header-logo"
|
||||||
|
data-testid="app-header-logo"
|
||||||
|
justifyContent={JustifyContent.center}
|
||||||
|
>
|
||||||
|
<MetafoxLogo
|
||||||
|
unsetIconHeight
|
||||||
|
onClick={async () => {
|
||||||
|
if (onClick) {
|
||||||
|
await onClick();
|
||||||
|
}
|
||||||
|
history.push(DEFAULT_ROUTE);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
<Box
|
||||||
|
display={DISPLAY.FLEX}
|
||||||
|
className={`multichain-app-header ${
|
||||||
|
!isUnlocked || popupStatus ? 'multichain-app-header-shadow' : ''
|
||||||
|
}`}
|
||||||
|
alignItems={AlignItems.center}
|
||||||
|
width={BLOCK_SIZES.FULL}
|
||||||
|
backgroundColor={
|
||||||
|
!isUnlocked || popupStatus
|
||||||
|
? BackgroundColor.backgroundDefault
|
||||||
|
: BackgroundColor.backgroundAlternative
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
{isUnlocked ? (
|
||||||
|
<Box
|
||||||
|
className={`multichain-app-header__contents ${
|
||||||
|
isUnlocked && !popupStatus ? 'multichain-app-header-shadow' : ''
|
||||||
|
}`}
|
||||||
|
alignItems={AlignItems.center}
|
||||||
|
width={BLOCK_SIZES.FULL}
|
||||||
|
backgroundColor={BackgroundColor.backgroundDefault}
|
||||||
|
padding={2}
|
||||||
|
gap={2}
|
||||||
|
>
|
||||||
|
{popupStatus ? (
|
||||||
|
<Button
|
||||||
|
className="multichain-app-header__contents--avatar-network"
|
||||||
|
justifyContent={JustifyContent.flexStart}
|
||||||
|
>
|
||||||
|
<AvatarNetwork
|
||||||
|
name={currentNetwork?.nickname}
|
||||||
|
src={currentNetwork?.rpcPrefs?.imageUrl}
|
||||||
|
size={Size.SM}
|
||||||
|
onClick={() => dispatch(toggleNetworkMenu())}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<PickerNetwork
|
||||||
|
label={currentNetwork?.nickname}
|
||||||
|
src={currentNetwork?.rpcPrefs?.imageUrl}
|
||||||
|
onClick={() => dispatch(toggleNetworkMenu())}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<AccountPicker
|
||||||
|
address={identity.address}
|
||||||
|
name={identity.name}
|
||||||
|
onClick={() => dispatch(toggleAccountMenu())}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
display={DISPLAY.FLEX}
|
||||||
|
alignItems={AlignItems.center}
|
||||||
|
justifyContent={JustifyContent.spaceBetween}
|
||||||
|
>
|
||||||
|
{showStatus ? (
|
||||||
|
<ConnectedStatusIndicator
|
||||||
|
onClick={() => history.push(CONNECTED_ACCOUNTS_ROUTE)}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<Box
|
||||||
|
ref={menuRef}
|
||||||
|
display={DISPLAY.FLEX}
|
||||||
|
justifyContent={JustifyContent.flexEnd}
|
||||||
|
width={BLOCK_SIZES.FULL}
|
||||||
|
>
|
||||||
|
<ButtonIcon
|
||||||
|
iconName={ICON_NAMES.MORE_VERTICAL}
|
||||||
|
data-testid="account-options-menu-button"
|
||||||
|
ariaLabel="NEEDS NEW TRANSLATED LABEL" // TODO: Update the label
|
||||||
|
onClick={() => {
|
||||||
|
trackEvent({
|
||||||
|
event: MetaMetricsEventName.NavAccountMenuOpened,
|
||||||
|
category: MetaMetricsEventCategory.Navigation,
|
||||||
|
properties: {
|
||||||
|
location: 'Home',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setAccountOptionsMenuOpen(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
{accountOptionsMenuOpen ? (
|
||||||
|
<GlobalMenu
|
||||||
|
anchorElement={menuRef.current}
|
||||||
|
closeMenu={() => setAccountOptionsMenuOpen(false)}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Box
|
||||||
|
display={DISPLAY.FLEX}
|
||||||
|
className={`multichain-app-header__lock-contents ${
|
||||||
|
isUnlocked && !popupStatus ? 'multichain-app-header-shadow' : ''
|
||||||
|
}`}
|
||||||
|
alignItems={AlignItems.center}
|
||||||
|
width={BLOCK_SIZES.FULL}
|
||||||
|
justifyContent={JustifyContent.spaceBetween}
|
||||||
|
backgroundColor={BackgroundColor.backgroundDefault}
|
||||||
|
padding={2}
|
||||||
|
gap={2}
|
||||||
|
>
|
||||||
|
<PickerNetwork
|
||||||
|
label={currentNetwork?.nickname}
|
||||||
|
src={currentNetwork?.rpcPrefs?.imageUrl}
|
||||||
|
onClick={() => dispatch(toggleNetworkMenu())}
|
||||||
|
/>
|
||||||
|
<MetafoxLogo
|
||||||
|
unsetIconHeight
|
||||||
|
onClick={async () => {
|
||||||
|
if (onClick) {
|
||||||
|
await onClick();
|
||||||
|
}
|
||||||
|
history.push(DEFAULT_ROUTE);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
AppHeader.propTypes = {
|
||||||
|
/**
|
||||||
|
* The onClick handler to be passed to the MetaMask Logo in the App Header
|
||||||
|
*/
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
};
|
74
ui/components/multichain/app-header/app-header.scss
Normal file
74
ui/components/multichain/app-header/app-header.scss
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
.multichain-app-header {
|
||||||
|
$height-screen-sm-max: 100%;
|
||||||
|
$width-screen-sm-min: 85vw;
|
||||||
|
$width-screen-md-min: 80vw;
|
||||||
|
$width-screen-lg-min: 62vw;
|
||||||
|
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
z-index: 55;
|
||||||
|
min-height: 64px;
|
||||||
|
|
||||||
|
&__contents {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 2fr 1fr;
|
||||||
|
height: 64px;
|
||||||
|
|
||||||
|
@include screen-sm-max {
|
||||||
|
height: $height-screen-sm-max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include screen-sm-min {
|
||||||
|
width: $width-screen-sm-min;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include screen-md-min {
|
||||||
|
width: $width-screen-md-min;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include screen-lg-min {
|
||||||
|
width: $width-screen-lg-min;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--avatar-network {
|
||||||
|
background-color: transparent;
|
||||||
|
width: min-content;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
box-shadow: none;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__lock-contents {
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
height: 64px;
|
||||||
|
|
||||||
|
@include screen-sm-max {
|
||||||
|
height: $height-screen-sm-max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include screen-sm-min {
|
||||||
|
width: $width-screen-sm-min;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include screen-md-min {
|
||||||
|
width: $width-screen-md-min;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include screen-lg-min {
|
||||||
|
width: $width-screen-lg-min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.multichain-app-header-shadow {
|
||||||
|
box-shadow: var(--shadow-size-md) var(--color-shadow-default);
|
||||||
|
}
|
||||||
|
|
||||||
|
.multichain-app-header-logo {
|
||||||
|
height: 75px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
71
ui/components/multichain/app-header/app-header.stories.js
Normal file
71
ui/components/multichain/app-header/app-header.stories.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import configureStore from '../../../store/store';
|
||||||
|
import testData from '../../../../.storybook/test-data';
|
||||||
|
import { AppHeader } from '.';
|
||||||
|
|
||||||
|
const store = configureStore(testData);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Components/Multichain/AppHeader',
|
||||||
|
decorators: [(story) => <Provider store={store}>{story()}</Provider>],
|
||||||
|
component: AppHeader,
|
||||||
|
argTypes: {
|
||||||
|
onClick: {
|
||||||
|
action: 'onClick',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const customNetworkUnlockedData = {
|
||||||
|
...testData,
|
||||||
|
metamask: {
|
||||||
|
...testData.metamask,
|
||||||
|
preferences: {
|
||||||
|
showTestNetworks: true,
|
||||||
|
},
|
||||||
|
isUnlocked: true,
|
||||||
|
networkConfigurations: {
|
||||||
|
...testData.metamask.networkConfigurations,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const customNetworkUnlockedStore = configureStore(customNetworkUnlockedData);
|
||||||
|
|
||||||
|
const customNetworkLockedData = {
|
||||||
|
...testData,
|
||||||
|
metamask: {
|
||||||
|
...testData.metamask,
|
||||||
|
preferences: {
|
||||||
|
showTestNetworks: true,
|
||||||
|
},
|
||||||
|
isUnlocked: false,
|
||||||
|
networkConfigurations: {
|
||||||
|
...testData.metamask.networkConfigurations,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const customNetworkLockedStore = configureStore(customNetworkLockedData);
|
||||||
|
|
||||||
|
const Template = (args) => {
|
||||||
|
return <AppHeader {...args} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FullScreenAndUnlockedStory = Template.bind({});
|
||||||
|
|
||||||
|
FullScreenAndUnlockedStory.decorators = [
|
||||||
|
(Story) => (
|
||||||
|
<Provider store={customNetworkUnlockedStore}>
|
||||||
|
<Story />
|
||||||
|
</Provider>
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
export const FullScreenAndLockedStory = Template.bind({});
|
||||||
|
|
||||||
|
FullScreenAndLockedStory.decorators = [
|
||||||
|
(Story) => (
|
||||||
|
<Provider store={customNetworkLockedStore}>
|
||||||
|
<Story />
|
||||||
|
</Provider>
|
||||||
|
),
|
||||||
|
];
|
107
ui/components/multichain/app-header/app-header.test.js
Normal file
107
ui/components/multichain/app-header/app-header.test.js
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import configureStore from 'redux-mock-store';
|
||||||
|
import { CHAIN_IDS } from '../../../../shared/constants/network';
|
||||||
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
|
import { AppHeader } from '.';
|
||||||
|
|
||||||
|
describe('App Header', () => {
|
||||||
|
it('should match snapshot', () => {
|
||||||
|
const mockState = {
|
||||||
|
activeTab: {
|
||||||
|
title: 'Eth Sign Tests',
|
||||||
|
origin: 'https://remix.ethereum.org',
|
||||||
|
protocol: 'https:',
|
||||||
|
url: 'https://remix.ethereum.org/',
|
||||||
|
},
|
||||||
|
metamask: {
|
||||||
|
provider: {
|
||||||
|
chainId: CHAIN_IDS.GOERLI,
|
||||||
|
},
|
||||||
|
accounts: {
|
||||||
|
'0x7250739de134d33ec7ab1ee592711e15098c9d2d': {
|
||||||
|
address: '0x7250739de134d33ec7ab1ee592711e15098c9d2d',
|
||||||
|
},
|
||||||
|
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5': {
|
||||||
|
address: '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
preferences: {
|
||||||
|
showTestNetworks: true,
|
||||||
|
},
|
||||||
|
cachedBalances: {},
|
||||||
|
subjects: {
|
||||||
|
'https://remix.ethereum.org': {
|
||||||
|
permissions: {
|
||||||
|
eth_accounts: {
|
||||||
|
caveats: [
|
||||||
|
{
|
||||||
|
type: 'restrictReturnedAccounts',
|
||||||
|
value: [
|
||||||
|
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||||
|
'0x7250739de134d33ec7ab1ee592711e15098c9d2d',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
date: 1586359844177,
|
||||||
|
id: '3aa65a8b-3bcb-4944-941b-1baa5fe0ed8b',
|
||||||
|
invoker: 'https://remix.ethereum.org',
|
||||||
|
parentCapability: 'eth_accounts',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'peepeth.com': {
|
||||||
|
permissions: {
|
||||||
|
eth_accounts: {
|
||||||
|
caveats: [
|
||||||
|
{
|
||||||
|
type: 'restrictReturnedAccounts',
|
||||||
|
value: ['0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
date: 1585676177970,
|
||||||
|
id: '840d72a0-925f-449f-830a-1aa1dd5ce151',
|
||||||
|
invoker: 'peepeth.com',
|
||||||
|
parentCapability: 'eth_accounts',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
identities: {
|
||||||
|
'0x7250739de134d33ec7ab1ee592711e15098c9d2d': {
|
||||||
|
address: '0x7250739de134d33ec7ab1ee592711e15098c9d2d',
|
||||||
|
name: 'Really Long Name That Should Be Truncated',
|
||||||
|
},
|
||||||
|
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5': {
|
||||||
|
address: '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||||
|
lastSelected: 1586359844192,
|
||||||
|
name: 'Account 1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
keyrings: [
|
||||||
|
{
|
||||||
|
accounts: [
|
||||||
|
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||||
|
'0x7250739de134d33ec7ab1ee592711e15098c9d2d',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
permissionHistory: {
|
||||||
|
'https://remix.ethereum.org': {
|
||||||
|
eth_accounts: {
|
||||||
|
accounts: {
|
||||||
|
'0x7250739de134d33ec7ab1ee592711e15098c9d2d': 1586359844192,
|
||||||
|
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5': 1586359844192,
|
||||||
|
},
|
||||||
|
lastApproved: 1586359844192,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockStore = configureStore();
|
||||||
|
const store = mockStore(mockState);
|
||||||
|
const { container } = renderWithProvider(<AppHeader />, store);
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
1
ui/components/multichain/app-header/index.js
Normal file
1
ui/components/multichain/app-header/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { AppHeader } from './app-header';
|
@ -2,6 +2,7 @@ export { AccountListItem } from './account-list-item';
|
|||||||
export { AccountListItemMenu } from './account-list-item-menu';
|
export { AccountListItemMenu } from './account-list-item-menu';
|
||||||
export { AccountListMenu } from './account-list-menu';
|
export { AccountListMenu } from './account-list-menu';
|
||||||
export { AccountPicker } from './account-picker';
|
export { AccountPicker } from './account-picker';
|
||||||
|
export { AppHeader } from './app-header';
|
||||||
export { DetectedTokensBanner } from './detected-token-banner';
|
export { DetectedTokensBanner } from './detected-token-banner';
|
||||||
export { GlobalMenu } from './global-menu';
|
export { GlobalMenu } from './global-menu';
|
||||||
export { MultichainImportTokenLink } from './multichain-import-token-link';
|
export { MultichainImportTokenLink } from './multichain-import-token-link';
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
@import 'account-list-item/index';
|
@import 'account-list-item/index';
|
||||||
@import 'account-list-menu/index';
|
@import 'account-list-menu/index';
|
||||||
@import 'account-picker/index';
|
@import 'account-picker/index';
|
||||||
|
@import 'app-header/app-header';
|
||||||
@import 'multichain-connected-site-menu/index';
|
@import 'multichain-connected-site-menu/index';
|
||||||
@import 'account-list-menu/';
|
@import 'account-list-menu/';
|
||||||
@import 'multichain-token-list-item/multichain-token-list-item';
|
@import 'multichain-token-list-item/multichain-token-list-item';
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
showModal,
|
showModal,
|
||||||
setShowTestNetworks,
|
setShowTestNetworks,
|
||||||
setProviderType,
|
setProviderType,
|
||||||
|
toggleNetworkMenu,
|
||||||
} from '../../../store/actions';
|
} from '../../../store/actions';
|
||||||
import { CHAIN_IDS, TEST_CHAINS } from '../../../../shared/constants/network';
|
import { CHAIN_IDS, TEST_CHAINS } from '../../../../shared/constants/network';
|
||||||
import {
|
import {
|
||||||
@ -30,7 +31,7 @@ import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app';
|
|||||||
|
|
||||||
const UNREMOVABLE_CHAIN_IDS = [CHAIN_IDS.MAINNET, ...TEST_CHAINS];
|
const UNREMOVABLE_CHAIN_IDS = [CHAIN_IDS.MAINNET, ...TEST_CHAINS];
|
||||||
|
|
||||||
export const NetworkListMenu = ({ closeMenu }) => {
|
export const NetworkListMenu = ({ onClose }) => {
|
||||||
const t = useI18nContext();
|
const t = useI18nContext();
|
||||||
const networks = useSelector(getAllNetworks);
|
const networks = useSelector(getAllNetworks);
|
||||||
const showTestNetworks = useSelector(getShowTestNetworks);
|
const showTestNetworks = useSelector(getShowTestNetworks);
|
||||||
@ -42,7 +43,7 @@ export const NetworkListMenu = ({ closeMenu }) => {
|
|||||||
const isFullScreen = environmentType === ENVIRONMENT_TYPE_FULLSCREEN;
|
const isFullScreen = environmentType === ENVIRONMENT_TYPE_FULLSCREEN;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover onClose={closeMenu} centerTitle title={t('networkMenuHeading')}>
|
<Popover onClose={onClose} centerTitle title={t('networkMenuHeading')}>
|
||||||
<>
|
<>
|
||||||
<Box className="multichain-network-list-menu">
|
<Box className="multichain-network-list-menu">
|
||||||
{networks.map((network) => {
|
{networks.map((network) => {
|
||||||
@ -58,16 +59,17 @@ export const NetworkListMenu = ({ closeMenu }) => {
|
|||||||
key={network.id || network.chainId}
|
key={network.id || network.chainId}
|
||||||
selected={isCurrentNetwork}
|
selected={isCurrentNetwork}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
dispatch(toggleNetworkMenu());
|
||||||
if (network.providerType) {
|
if (network.providerType) {
|
||||||
dispatch(setProviderType(network.providerType));
|
dispatch(setProviderType(network.providerType));
|
||||||
} else {
|
} else {
|
||||||
dispatch(setActiveNetwork(network.id));
|
dispatch(setActiveNetwork(network.id));
|
||||||
}
|
}
|
||||||
closeMenu();
|
|
||||||
}}
|
}}
|
||||||
onDeleteClick={
|
onDeleteClick={
|
||||||
canDeleteNetwork
|
canDeleteNetwork
|
||||||
? () => {
|
? () => {
|
||||||
|
dispatch(toggleNetworkMenu());
|
||||||
dispatch(
|
dispatch(
|
||||||
showModal({
|
showModal({
|
||||||
name: 'CONFIRM_DELETE_NETWORK',
|
name: 'CONFIRM_DELETE_NETWORK',
|
||||||
@ -75,7 +77,6 @@ export const NetworkListMenu = ({ closeMenu }) => {
|
|||||||
onConfirm: () => undefined,
|
onConfirm: () => undefined,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
closeMenu();
|
|
||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
@ -104,6 +105,7 @@ export const NetworkListMenu = ({ closeMenu }) => {
|
|||||||
: global.platform.openExtensionInBrowser(
|
: global.platform.openExtensionInBrowser(
|
||||||
ADD_POPULAR_CUSTOM_NETWORK,
|
ADD_POPULAR_CUSTOM_NETWORK,
|
||||||
);
|
);
|
||||||
|
dispatch(toggleNetworkMenu());
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('addNetwork')}
|
{t('addNetwork')}
|
||||||
@ -118,5 +120,5 @@ NetworkListMenu.propTypes = {
|
|||||||
/**
|
/**
|
||||||
* Executes when the menu should be closed
|
* Executes when the menu should be closed
|
||||||
*/
|
*/
|
||||||
closeMenu: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
@ -42,8 +42,8 @@ export default {
|
|||||||
title: 'Components/Multichain/NetworkListMenu',
|
title: 'Components/Multichain/NetworkListMenu',
|
||||||
component: NetworkListMenu,
|
component: NetworkListMenu,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
closeMenu: {
|
onClose: {
|
||||||
action: 'closeMenu',
|
action: 'onClose',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -11,9 +11,11 @@ import { NetworkListMenu } from '.';
|
|||||||
|
|
||||||
const mockSetShowTestNetworks = jest.fn();
|
const mockSetShowTestNetworks = jest.fn();
|
||||||
const mockSetProviderType = jest.fn();
|
const mockSetProviderType = jest.fn();
|
||||||
|
const mockToggleNetworkMenu = jest.fn();
|
||||||
jest.mock('../../../store/actions.ts', () => ({
|
jest.mock('../../../store/actions.ts', () => ({
|
||||||
setShowTestNetworks: () => mockSetShowTestNetworks,
|
setShowTestNetworks: () => mockSetShowTestNetworks,
|
||||||
setProviderType: () => mockSetProviderType,
|
setProviderType: () => mockSetProviderType,
|
||||||
|
toggleNetworkMenu: () => mockToggleNetworkMenu,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const render = (showTestNetworks = false) => {
|
const render = (showTestNetworks = false) => {
|
||||||
@ -25,7 +27,7 @@ const render = (showTestNetworks = false) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return renderWithProvider(<NetworkListMenu closeMenu={jest.fn()} />, store);
|
return renderWithProvider(<NetworkListMenu onClose={jest.fn()} />, store);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('NetworkListMenu', () => {
|
describe('NetworkListMenu', () => {
|
||||||
@ -56,6 +58,7 @@ describe('NetworkListMenu', () => {
|
|||||||
it('switches networks when an item is clicked', () => {
|
it('switches networks when an item is clicked', () => {
|
||||||
const { getByText } = render();
|
const { getByText } = render();
|
||||||
fireEvent.click(getByText(MAINNET_DISPLAY_NAME));
|
fireEvent.click(getByText(MAINNET_DISPLAY_NAME));
|
||||||
|
expect(mockToggleNetworkMenu).toHaveBeenCalled();
|
||||||
expect(mockSetProviderType).toHaveBeenCalled();
|
expect(mockSetProviderType).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -26,6 +26,7 @@ const initialState = {
|
|||||||
isInitialized: false,
|
isInitialized: false,
|
||||||
isUnlocked: false,
|
isUnlocked: false,
|
||||||
isAccountMenuOpen: false,
|
isAccountMenuOpen: false,
|
||||||
|
isNetworkMenuOpen: false,
|
||||||
identities: {},
|
identities: {},
|
||||||
unapprovedTxs: {},
|
unapprovedTxs: {},
|
||||||
networkConfigurations: {},
|
networkConfigurations: {},
|
||||||
@ -102,6 +103,12 @@ export default function reduceMetamask(state = initialState, action) {
|
|||||||
isAccountMenuOpen: !metamaskState.isAccountMenuOpen,
|
isAccountMenuOpen: !metamaskState.isAccountMenuOpen,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
case actionConstants.TOGGLE_NETWORK_MENU:
|
||||||
|
return {
|
||||||
|
...metamaskState,
|
||||||
|
isNetworkMenuOpen: !metamaskState.isNetworkMenuOpen,
|
||||||
|
};
|
||||||
|
|
||||||
case actionConstants.UPDATE_TRANSACTION_PARAMS: {
|
case actionConstants.UPDATE_TRANSACTION_PARAMS: {
|
||||||
const { id: txId, value } = action;
|
const { id: txId, value } = action;
|
||||||
let { currentNetworkTxList } = metamaskState;
|
let { currentNetworkTxList } = metamaskState;
|
||||||
|
@ -157,6 +157,17 @@ describe('MetaMask Reducers', () => {
|
|||||||
expect(state.isAccountMenuOpen).toStrictEqual(true);
|
expect(state.isAccountMenuOpen).toStrictEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('toggles network menu', () => {
|
||||||
|
const state = reduceMetamask(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
type: actionConstants.TOGGLE_NETWORK_MENU,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(state.isNetworkMenuOpen).toStrictEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
it('updates value of tx by id', () => {
|
it('updates value of tx by id', () => {
|
||||||
const oldState = {
|
const oldState = {
|
||||||
currentNetworkTxList: [
|
currentNetworkTxList: [
|
||||||
|
@ -641,7 +641,7 @@ export default class Home extends PureComponent {
|
|||||||
? this.renderPopover()
|
? this.renderPopover()
|
||||||
: null}
|
: null}
|
||||||
<div className="home__main-view">
|
<div className="home__main-view">
|
||||||
<MenuBar />
|
{process.env.MULTICHAIN ? null : <MenuBar />}
|
||||||
<div className="home__balance-wrapper">
|
<div className="home__balance-wrapper">
|
||||||
<EthOverview />
|
<EthOverview />
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,6 +31,11 @@ import AccountMenu from '../../components/app/account-menu';
|
|||||||
import { Modal } from '../../components/app/modals';
|
import { Modal } from '../../components/app/modals';
|
||||||
import Alert from '../../components/ui/alert';
|
import Alert from '../../components/ui/alert';
|
||||||
import AppHeader from '../../components/app/app-header';
|
import AppHeader from '../../components/app/app-header';
|
||||||
|
import {
|
||||||
|
AppHeader as MultichainAppHeader,
|
||||||
|
AccountListMenu,
|
||||||
|
NetworkListMenu,
|
||||||
|
} from '../../components/multichain';
|
||||||
import UnlockPage from '../unlock-page';
|
import UnlockPage from '../unlock-page';
|
||||||
import Alerts from '../../components/app/alerts';
|
import Alerts from '../../components/app/alerts';
|
||||||
import Asset from '../asset';
|
import Asset from '../asset';
|
||||||
@ -90,7 +95,6 @@ import { SEND_STAGES } from '../../ducks/send';
|
|||||||
import DeprecatedTestNetworks from '../../components/ui/deprecated-test-networks/deprecated-test-networks';
|
import DeprecatedTestNetworks from '../../components/ui/deprecated-test-networks/deprecated-test-networks';
|
||||||
import NewNetworkInfo from '../../components/ui/new-network-info/new-network-info';
|
import NewNetworkInfo from '../../components/ui/new-network-info/new-network-info';
|
||||||
import { ThemeType } from '../../../shared/constants/preferences';
|
import { ThemeType } from '../../../shared/constants/preferences';
|
||||||
import { AccountListMenu } from '../../components/multichain';
|
|
||||||
|
|
||||||
export default class Routes extends Component {
|
export default class Routes extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -128,6 +132,8 @@ export default class Routes extends Component {
|
|||||||
completedOnboarding: PropTypes.bool,
|
completedOnboarding: PropTypes.bool,
|
||||||
isAccountMenuOpen: PropTypes.bool,
|
isAccountMenuOpen: PropTypes.bool,
|
||||||
toggleAccountMenu: PropTypes.func,
|
toggleAccountMenu: PropTypes.func,
|
||||||
|
isNetworkMenuOpen: PropTypes.bool,
|
||||||
|
toggleNetworkMenu: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -436,6 +442,8 @@ export default class Routes extends Component {
|
|||||||
completedOnboarding,
|
completedOnboarding,
|
||||||
isAccountMenuOpen,
|
isAccountMenuOpen,
|
||||||
toggleAccountMenu,
|
toggleAccountMenu,
|
||||||
|
isNetworkMenuOpen,
|
||||||
|
toggleNetworkMenu,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const loadMessage =
|
const loadMessage =
|
||||||
loadingMessage || isNetworkLoading
|
loadingMessage || isNetworkLoading
|
||||||
@ -478,7 +486,10 @@ export default class Routes extends Component {
|
|||||||
<QRHardwarePopover />
|
<QRHardwarePopover />
|
||||||
<Modal />
|
<Modal />
|
||||||
<Alert visible={this.props.alertOpen} msg={alertMessage} />
|
<Alert visible={this.props.alertOpen} msg={alertMessage} />
|
||||||
{!this.hideAppHeader() && (
|
{!this.hideAppHeader() &&
|
||||||
|
(process.env.MULTICHAIN ? (
|
||||||
|
<MultichainAppHeader />
|
||||||
|
) : (
|
||||||
<AppHeader
|
<AppHeader
|
||||||
hideNetworkIndicator={this.onInitializationUnlockPage()}
|
hideNetworkIndicator={this.onInitializationUnlockPage()}
|
||||||
disableNetworkIndicator={this.onSwapsPage()}
|
disableNetworkIndicator={this.onSwapsPage()}
|
||||||
@ -489,13 +500,16 @@ export default class Routes extends Component {
|
|||||||
(this.onSwapsPage() && !this.onSwapsBuildQuotePage())
|
(this.onSwapsPage() && !this.onSwapsBuildQuotePage())
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
))}
|
||||||
{this.showOnboardingHeader() && <OnboardingAppHeader />}
|
{this.showOnboardingHeader() && <OnboardingAppHeader />}
|
||||||
{completedOnboarding ? <NetworkDropdown /> : null}
|
{completedOnboarding ? <NetworkDropdown /> : null}
|
||||||
{process.env.MULTICHAIN ? null : <AccountMenu />}
|
{process.env.MULTICHAIN ? null : <AccountMenu />}
|
||||||
{process.env.MULTICHAIN && isAccountMenuOpen ? (
|
{process.env.MULTICHAIN && isAccountMenuOpen ? (
|
||||||
<AccountListMenu onClose={() => toggleAccountMenu()} />
|
<AccountListMenu onClose={() => toggleAccountMenu()} />
|
||||||
) : null}
|
) : null}
|
||||||
|
{process.env.MULTICHAIN && isNetworkMenuOpen ? (
|
||||||
|
<NetworkListMenu onClose={() => toggleNetworkMenu()} />
|
||||||
|
) : null}
|
||||||
<div className="main-container-wrapper">
|
<div className="main-container-wrapper">
|
||||||
{isLoading ? <Loading loadingMessage={loadMessage} /> : null}
|
{isLoading ? <Loading loadingMessage={loadMessage} /> : null}
|
||||||
{!isLoading && isNetworkLoading ? <LoadingNetwork /> : null}
|
{!isLoading && isNetworkLoading ? <LoadingNetwork /> : null}
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
setLastActiveTime,
|
setLastActiveTime,
|
||||||
setMouseUserState,
|
setMouseUserState,
|
||||||
toggleAccountMenu,
|
toggleAccountMenu,
|
||||||
|
toggleNetworkMenu,
|
||||||
} from '../../store/actions';
|
} from '../../store/actions';
|
||||||
import { pageChanged } from '../../ducks/history/history';
|
import { pageChanged } from '../../ducks/history/history';
|
||||||
import { prepareToLeaveSwaps } from '../../ducks/swaps/swaps';
|
import { prepareToLeaveSwaps } from '../../ducks/swaps/swaps';
|
||||||
@ -57,6 +58,7 @@ function mapStateToProps(state) {
|
|||||||
isCurrentProviderCustom: isCurrentProviderCustom(state),
|
isCurrentProviderCustom: isCurrentProviderCustom(state),
|
||||||
completedOnboarding,
|
completedOnboarding,
|
||||||
isAccountMenuOpen: state.metamask.isAccountMenuOpen,
|
isAccountMenuOpen: state.metamask.isAccountMenuOpen,
|
||||||
|
isNetworkMenuOpen: state.metamask.isNetworkMenuOpen,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +72,7 @@ function mapDispatchToProps(dispatch) {
|
|||||||
pageChanged: (path) => dispatch(pageChanged(path)),
|
pageChanged: (path) => dispatch(pageChanged(path)),
|
||||||
prepareToLeaveSwaps: () => dispatch(prepareToLeaveSwaps()),
|
prepareToLeaveSwaps: () => dispatch(prepareToLeaveSwaps()),
|
||||||
toggleAccountMenu: () => dispatch(toggleAccountMenu()),
|
toggleAccountMenu: () => dispatch(toggleAccountMenu()),
|
||||||
|
toggleNetworkMenu: () => dispatch(toggleNetworkMenu()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,6 +1111,13 @@ export function getNetworkConfigurations(state) {
|
|||||||
return state.metamask.networkConfigurations;
|
return state.metamask.networkConfigurations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCurrentNetwork(state) {
|
||||||
|
const allNetworks = getAllNetworks(state);
|
||||||
|
const currentChainId = getCurrentChainId(state);
|
||||||
|
|
||||||
|
return allNetworks.find((network) => network.chainId === currentChainId);
|
||||||
|
}
|
||||||
|
|
||||||
export function getAllNetworks(state) {
|
export function getAllNetworks(state) {
|
||||||
const networkConfigurations = getNetworkConfigurations(state) || {};
|
const networkConfigurations = getNetworkConfigurations(state) || {};
|
||||||
const showTestnetNetworks = getShowTestNetworks(state);
|
const showTestnetNetworks = getShowTestNetworks(state);
|
||||||
|
@ -48,6 +48,7 @@ export const SHOW_LOADING = 'SHOW_LOADING_INDICATION';
|
|||||||
export const HIDE_LOADING = 'HIDE_LOADING_INDICATION';
|
export const HIDE_LOADING = 'HIDE_LOADING_INDICATION';
|
||||||
|
|
||||||
export const TOGGLE_ACCOUNT_MENU = 'TOGGLE_ACCOUNT_MENU';
|
export const TOGGLE_ACCOUNT_MENU = 'TOGGLE_ACCOUNT_MENU';
|
||||||
|
export const TOGGLE_NETWORK_MENU = 'TOGGLE_NETWORK_MENU';
|
||||||
|
|
||||||
// preferences
|
// preferences
|
||||||
export const UPDATE_CUSTOM_NONCE = 'UPDATE_CUSTOM_NONCE';
|
export const UPDATE_CUSTOM_NONCE = 'UPDATE_CUSTOM_NONCE';
|
||||||
|
@ -3122,6 +3122,12 @@ export function toggleAccountMenu() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toggleNetworkMenu() {
|
||||||
|
return {
|
||||||
|
type: actionConstants.TOGGLE_NETWORK_MENU,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function setParticipateInMetaMetrics(
|
export function setParticipateInMetaMetrics(
|
||||||
participationPreference: boolean,
|
participationPreference: boolean,
|
||||||
): ThunkAction<
|
): ThunkAction<
|
||||||
|
Loading…
Reference in New Issue
Block a user