import React, { useContext } from 'react'; import { useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import Identicon from '../../../../components/ui/identicon'; import UrlIcon from '../../../../components/ui/url-icon'; import Button from '../../../../components/ui/button'; import ActionableMessage from '../../../../components/ui/actionable-message/actionable-message'; import { I18nContext } from '../../../../contexts/i18n'; import { getCurrentChainId, getRpcPrefsForCurrentProvider, } from '../../../../selectors'; import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../shared/constants/swaps'; import { useNewMetricEvent } from '../../../../hooks/useMetricEvent'; import { getURLHostName } from '../../../../helpers/utils/util'; export default function ItemList({ results = [], onClickItem, onOpenImportTokenModalClick, Placeholder, listTitle, maxListItems = 6, searchQuery = '', containerRef, hideRightLabels, hideItemIf, listContainerClassName, }) { const t = useContext(I18nContext); const chainId = useSelector(getCurrentChainId); const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); const blockExplorerLink = rpcPrefs.blockExplorerUrl ?? SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? null; const blockExplorerLabel = rpcPrefs.blockExplorerUrl ? getURLHostName(blockExplorerLink) : t('etherscan'); const blockExplorerLinkClickedEvent = useNewMetricEvent({ category: 'Swaps', event: 'Clicked Block Explorer Link', properties: { link_type: 'Token Tracker', action: 'Verify Contract Address', block_explorer_domain: getURLHostName(blockExplorerLink), }, }); // If there is a token for import based on a contract address, it's the only one in the list. const hasTokenForImport = results.length === 1 && results[0].notImported; return results.length === 0 ? ( Placeholder && ) : (
{listTitle && (
{listTitle}
)}
{results.slice(0, maxListItems).map((result, i) => { if (hideItemIf?.(result)) { return null; } const onClick = () => { if (result.notImported) { onOpenImportTokenModalClick(result); } else { onClickItem?.(result); } }; const { iconUrl, identiconAddress, selected, disabled, primaryLabel, secondaryLabel, rightPrimaryLabel, rightSecondaryLabel, IconComponent, } = result; return (
e.key === 'Enter' && onClick()} key={`searchable-item-list-item-${i}`} > {(iconUrl || primaryLabel) && ( )} {!(iconUrl || primaryLabel) && identiconAddress && (
)} {IconComponent && }
{primaryLabel && ( {primaryLabel} )} {secondaryLabel && ( {secondaryLabel} )}
{!hideRightLabels && (rightPrimaryLabel || rightSecondaryLabel) && (
{rightPrimaryLabel && ( {rightPrimaryLabel} )} {rightSecondaryLabel && ( {rightSecondaryLabel} )}
)}
{result.notImported && ( )}
); })} {!hasTokenForImport && (
{ blockExplorerLinkClickedEvent(); global.platform.openTab({ url: blockExplorerLink, }); }} target="_blank" rel="noopener noreferrer" > {blockExplorerLabel} , ]) } />
)}
); } ItemList.propTypes = { results: PropTypes.arrayOf( PropTypes.shape({ iconUrl: PropTypes.string, selected: PropTypes.bool, disabled: PropTypes.bool, primaryLabel: PropTypes.string, secondaryLabel: PropTypes.string, rightPrimaryLabel: PropTypes.string, rightSecondaryLabel: PropTypes.string, }), ), onClickItem: PropTypes.func, onOpenImportTokenModalClick: PropTypes.func, Placeholder: PropTypes.func, listTitle: PropTypes.string, maxListItems: PropTypes.number, searchQuery: PropTypes.string, containerRef: PropTypes.shape({ current: PropTypes.instanceOf(window.Element), }), hideRightLabels: PropTypes.bool, hideItemIf: PropTypes.func, listContainerClassName: PropTypes.string, };