import React, { useState, useContext, useRef, useEffect } from 'react'; import PropTypes from 'prop-types'; import { useHistory } from 'react-router-dom'; import Fuse from 'fuse.js'; import { useDispatch, useSelector } from 'react-redux'; import { IconName, ButtonLink, TextFieldSearch, Text, Box, } from '../../component-library'; import { AccountListItem, CreateAccount, ImportAccount } from '..'; import { BLOCK_SIZES, Size, TextColor, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import Popover from '../../ui/popover'; import { getSelectedAccount, getMetaMaskAccountsOrdered, getConnectedSubjectsForAllAddresses, getOriginOfCurrentTab, } from '../../../selectors'; import { toggleAccountMenu, setSelectedAccount } from '../../../store/actions'; import { MetaMetricsEventAccountType, MetaMetricsEventCategory, MetaMetricsEventName, } from '../../../../shared/constants/metametrics'; import { CONNECT_HARDWARE_ROUTE, ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) CUSTODY_ACCOUNT_ROUTE, ///: END:ONLY_INCLUDE_IN } from '../../../helpers/constants/routes'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; export const AccountListMenu = ({ onClose }) => { const t = useI18nContext(); const trackEvent = useContext(MetaMetricsContext); const accounts = useSelector(getMetaMaskAccountsOrdered); const selectedAccount = useSelector(getSelectedAccount); const connectedSites = useSelector(getConnectedSubjectsForAllAddresses); const currentTabOrigin = useSelector(getOriginOfCurrentTab); const history = useHistory(); const dispatch = useDispatch(); const inputRef = useRef(); const [searchQuery, setSearchQuery] = useState(''); const [actionMode, setActionMode] = useState(''); let searchResults = accounts; if (searchQuery) { const fuse = new Fuse(accounts, { threshold: 0.2, location: 0, distance: 100, maxPatternLength: 32, minMatchCharLength: 1, keys: ['name', 'address'], }); fuse.setCollection(accounts); searchResults = fuse.search(searchQuery); } // Focus on the search box when the popover is opened useEffect(() => { if (inputRef.current) { inputRef.current.rootNode.querySelector('input[type=search]')?.focus(); } }, [inputRef]); let title = t('selectAnAccount'); if (actionMode === 'add') { title = t('addAccount'); } else if (actionMode === 'import') { title = t('importAccount'); } return ( setActionMode('')} className="multichain-account-menu-popover" > {actionMode === 'add' ? ( { if (confirmed) { dispatch(toggleAccountMenu()); } else { setActionMode(''); } }} /> ) : null} {actionMode === 'import' ? ( { if (confirmed) { dispatch(toggleAccountMenu()); } else { setActionMode(''); } }} /> ) : null} {actionMode === '' ? ( {/* Search box */} {accounts.length > 1 ? ( setSearchQuery(e.target.value)} clearButtonOnClick={() => setSearchQuery('')} clearButtonProps={{ size: Size.SM, }} /> ) : null} {/* Account list block */} {searchResults.length === 0 && searchQuery !== '' ? ( {t('noAccountsFound')} ) : null} {searchResults.map((account) => { const connectedSite = connectedSites[account.address]?.find( ({ origin }) => origin === currentTabOrigin, ); return ( { dispatch(toggleAccountMenu()); trackEvent({ category: MetaMetricsEventCategory.Navigation, event: MetaMetricsEventName.NavAccountSwitched, properties: { location: 'Main Menu', }, }); dispatch(setSelectedAccount(account.address)); }} identity={account} key={account.address} selected={selectedAccount.address === account.address} closeMenu={onClose} connectedAvatar={connectedSite?.iconUrl} connectedAvatarName={connectedSite?.name} /> ); })} {/* Add / Import / Hardware */} { trackEvent({ category: MetaMetricsEventCategory.Navigation, event: MetaMetricsEventName.AccountAddSelected, properties: { account_type: MetaMetricsEventAccountType.Default, location: 'Main Menu', }, }); setActionMode('add'); }} data-testid="multichain-account-menu-popover-add-account" > {t('addAccount')} { trackEvent({ category: MetaMetricsEventCategory.Navigation, event: MetaMetricsEventName.AccountAddSelected, properties: { account_type: MetaMetricsEventAccountType.Imported, location: 'Main Menu', }, }); setActionMode('import'); }} > {t('importAccount')} { dispatch(toggleAccountMenu()); trackEvent({ category: MetaMetricsEventCategory.Navigation, event: MetaMetricsEventName.AccountAddSelected, properties: { account_type: MetaMetricsEventAccountType.Hardware, location: 'Main Menu', }, }); if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) { global.platform.openExtensionInBrowser( CONNECT_HARDWARE_ROUTE, ); } else { history.push(CONNECT_HARDWARE_ROUTE); } }} > {t('hardwareWallet')} { ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) { dispatch(toggleAccountMenu()); trackEvent({ category: MetaMetricsEventCategory.Navigation, event: MetaMetricsEventName.UserClickedConnectCustodialAccount, }); if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) { global.platform.openExtensionInBrowser( CUSTODY_ACCOUNT_ROUTE, ); } else { history.push(CUSTODY_ACCOUNT_ROUTE); } }} > {t('connectCustodialAccountMenu')} ///: END:ONLY_INCLUDE_IN } ) : null} ); }; AccountListMenu.propTypes = { /** * Function that executes when the menu closes */ onClose: PropTypes.func.isRequired, };