From 2f33dd5808995f146af27df1bffa25d02abd26b2 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Fri, 11 Oct 2024 10:03:30 -1000 Subject: [PATCH 01/28] feat: Init network filter --- .../asset-list-control-bar.tsx | 97 ++++++++++++++----- .../asset-list/network-filter/index.scss | 27 ++++++ .../assets/asset-list/network-filter/index.ts | 1 + .../network-filter/network-filter.tsx | 62 ++++++++++++ 4 files changed, 162 insertions(+), 25 deletions(-) create mode 100644 ui/components/app/assets/asset-list/network-filter/index.scss create mode 100644 ui/components/app/assets/asset-list/network-filter/index.ts create mode 100644 ui/components/app/assets/asset-list/network-filter/network-filter.tsx diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index 696c3ca7c89f..3e3fde694205 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -25,6 +25,7 @@ import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP, } from '../../../../../../shared/constants/app'; +import NetworkFilter from '../network-filter'; type AssetListControlBarProps = { showTokensLinks?: boolean; @@ -32,55 +33,101 @@ type AssetListControlBarProps = { const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { const t = useI18nContext(); - const controlBarRef = useRef(null); // Create a ref - const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const tokenSortPopoverRef = useRef(null); + const networkFilterPopoverRef = useRef(null); + const [isTokenSortPopoverOpen, setIsTokenSortPopoverOpen] = useState(false); + const [isNetworkFilterPopoverOpen, setIsNetworkFilterPopoverOpen] = + useState(false); const windowType = getEnvironmentType(); const isFullScreen = windowType !== ENVIRONMENT_TYPE_NOTIFICATION && windowType !== ENVIRONMENT_TYPE_POPUP; - const handleOpenPopover = () => { - setIsPopoverOpen(!isPopoverOpen); + const toggleTokenSortPopover = () => { + setIsTokenSortPopoverOpen(!isTokenSortPopoverOpen); + }; + + const toggleNetworkFilterPopover = () => { + setIsNetworkFilterPopoverOpen(!isNetworkFilterPopoverOpen); }; const closePopover = () => { - setIsPopoverOpen(false); + setIsTokenSortPopoverOpen(false); + setIsNetworkFilterPopoverOpen(false); }; return ( - - {t('sortBy')} - + + + Network + + + + + + {t('sortBy')} + + + + + + void; +}; + +const NetworkFilter = ({ handleClose }: SortControlProps) => { + const t = useI18nContext(); + // const trackEvent = useContext(MetaMetricsContext); + // const { tokenSortConfig } = useSelector(getPreferences); + // const currentCurrency = useSelector(getCurrentCurrency); + + // const dispatch = useDispatch(); + + const handleFilter = () => { + console.log('filter'); + // dispatch(setNetworkFilter()); TODO Add dispatcher + + // TODO Add metrics + // trackEvent({ + // category: MetaMetricsEventCategory.Settings, + // event: MetaMetricsEventName.TokenSortPreference, + // properties: { + // [MetaMetricsUserTrait.TokenSortPreference]: key, + // }, + // }); + handleClose(); + }; + return ( + <> + + All Networks + + + Current Network + + + ); +}; + +export default NetworkFilter; From 317cb448455d7c14a05ad8ead1a41e584f71ba99 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Fri, 11 Oct 2024 11:25:04 -1000 Subject: [PATCH 02/28] chore: Add tokenNetworkFilter action --- .../controllers/preferences-controller.ts | 2 + .../asset-list-control-bar.tsx | 26 ++++++---- .../network-filter/network-filter.tsx | 51 ++++++------------- ui/store/actions.ts | 4 ++ 4 files changed, 37 insertions(+), 46 deletions(-) diff --git a/app/scripts/controllers/preferences-controller.ts b/app/scripts/controllers/preferences-controller.ts index eb126b176a41..bb99d4eff044 100644 --- a/app/scripts/controllers/preferences-controller.ts +++ b/app/scripts/controllers/preferences-controller.ts @@ -111,6 +111,7 @@ export type Preferences = { order: string; sortCallback: string; }; + tokenNetworkFilter: Record; shouldShowAggregatedBalancePopover: boolean; }; @@ -247,6 +248,7 @@ export default class PreferencesController { order: 'dsc', sortCallback: 'stringNumeric', }, + tokenNetworkFilter: {}, shouldShowAggregatedBalancePopover: true, // by default user should see popover; }, // ENS decentralized website resolution diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index 3e3fde694205..72936db0f2c7 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -33,8 +33,7 @@ type AssetListControlBarProps = { const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { const t = useI18nContext(); - const tokenSortPopoverRef = useRef(null); - const networkFilterPopoverRef = useRef(null); + const popoverRef = useRef(null); const [isTokenSortPopoverOpen, setIsTokenSortPopoverOpen] = useState(false); const [isNetworkFilterPopoverOpen, setIsNetworkFilterPopoverOpen] = useState(false); @@ -45,10 +44,12 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { windowType !== ENVIRONMENT_TYPE_POPUP; const toggleTokenSortPopover = () => { + setIsNetworkFilterPopoverOpen(false); setIsTokenSortPopoverOpen(!isTokenSortPopoverOpen); }; const toggleNetworkFilterPopover = () => { + setIsTokenSortPopoverOpen(false); setIsNetworkFilterPopoverOpen(!isNetworkFilterPopoverOpen); }; @@ -60,13 +61,17 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { return ( - + { borderColor={BorderColor.borderMuted} borderStyle={BorderStyle.solid} color={TextColor.textDefault} + marginRight={isFullScreen ? 2 : null} > Network - - { borderColor={BorderColor.borderMuted} borderStyle={BorderStyle.solid} color={TextColor.textDefault} + marginRight={isFullScreen ? 2 : null} > {t('sortBy')} + + - { onClickOutside={closePopover} isOpen={isTokenSortPopoverOpen} position={PopoverPosition.BottomStart} - referenceElement={tokenSortPopoverRef.current} + referenceElement={popoverRef.current} matchWidth={!isFullScreen} style={{ zIndex: 10, diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index f2740e6fd667..ceec7b0db20d 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -1,24 +1,8 @@ -import React, { ReactNode, useContext } from 'react'; +import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import classnames from 'classnames'; -import { Box, Text } from '../../../../component-library'; -import { SortOrder, SortingCallbacksT } from '../../util/sort'; -import { - BackgroundColor, - BorderRadius, - TextColor, - TextVariant, -} from '../../../../../helpers/constants/design-system'; -import { setTokenSortConfig } from '../../../../../store/actions'; -import { MetaMetricsContext } from '../../../../../contexts/metametrics'; -import { - MetaMetricsEventCategory, - MetaMetricsEventName, - MetaMetricsUserTrait, -} from '../../../../../../shared/constants/metametrics'; -import { getCurrentCurrency, getPreferences } from '../../../../../selectors'; +import { setTokenNetworkFilter } from '../../../../../store/actions'; +import { getCurrentChainId, getPreferences } from '../../../../../selectors'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; -import { getCurrencySymbol } from '../../../../../helpers/utils/common.util'; import { SelectableListItem } from '../sort-control/sort-control'; type SortControlProps = { @@ -27,32 +11,27 @@ type SortControlProps = { const NetworkFilter = ({ handleClose }: SortControlProps) => { const t = useI18nContext(); - // const trackEvent = useContext(MetaMetricsContext); - // const { tokenSortConfig } = useSelector(getPreferences); - // const currentCurrency = useSelector(getCurrentCurrency); + const dispatch = useDispatch(); + const chainId = useSelector(getCurrentChainId); + const { tokenNetworkFilter } = useSelector(getPreferences); - // const dispatch = useDispatch(); - - const handleFilter = () => { - console.log('filter'); - // dispatch(setNetworkFilter()); TODO Add dispatcher + const handleFilter = (chainFilters: Record) => { + console.log('filter', chainFilters); + dispatch(setTokenNetworkFilter(chainFilters)); // TODO Add metrics - // trackEvent({ - // category: MetaMetricsEventCategory.Settings, - // event: MetaMetricsEventName.TokenSortPreference, - // properties: { - // [MetaMetricsUserTrait.TokenSortPreference]: key, - // }, - // }); handleClose(); }; + return ( <> - + handleFilter({})}> All Networks - + handleFilter({ chainId })} + > Current Network diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 91453590791c..898cd55602d9 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -3090,6 +3090,10 @@ export function setTokenSortConfig(value: SortCriteria) { return setPreference('tokenSortConfig', value, false); } +export function setTokenNetworkFilter(value: Record) { + return setPreference('tokenNetworkFilter', value, false); +} + export function setSmartTransactionsOptInStatus( value: boolean, ): ThunkAction { From 99ae62096a1ba5a3ee0c744e748fb762a16b919f Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Fri, 11 Oct 2024 11:39:33 -1000 Subject: [PATCH 03/28] chore: Add selected indicator on TokenNetworkList controls --- .../network-filter/network-filter.tsx | 20 ++++++++++++------- ui/store/actions.ts | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index ceec7b0db20d..9507af3b3c0a 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -4,6 +4,8 @@ import { setTokenNetworkFilter } from '../../../../../store/actions'; import { getCurrentChainId, getPreferences } from '../../../../../selectors'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { SelectableListItem } from '../sort-control/sort-control'; +import { Box } from '../../../../component-library/box/box'; +import { Text } from '../../../../component-library/text/text'; type SortControlProps = { handleClose: () => void; @@ -15,8 +17,7 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { const chainId = useSelector(getCurrentChainId); const { tokenNetworkFilter } = useSelector(getPreferences); - const handleFilter = (chainFilters: Record) => { - console.log('filter', chainFilters); + const handleFilter = (chainFilters: Record) => { dispatch(setTokenNetworkFilter(chainFilters)); // TODO Add metrics @@ -25,14 +26,19 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { return ( <> - handleFilter({})}> - All Networks + handleFilter({})} + > + All Networks + 12,000 handleFilter({ chainId })} + isSelected={tokenNetworkFilter[chainId]} + onClick={() => handleFilter({ [chainId]: true })} > - Current Network + Current Network + 2,000 ); diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 898cd55602d9..7813b078958d 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -3090,7 +3090,7 @@ export function setTokenSortConfig(value: SortCriteria) { return setPreference('tokenSortConfig', value, false); } -export function setTokenNetworkFilter(value: Record) { +export function setTokenNetworkFilter(value: Record) { return setPreference('tokenNetworkFilter', value, false); } From ab6189f0f04e3174b54132ca7ae2f641c61b0abf Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Fri, 11 Oct 2024 11:46:21 -1000 Subject: [PATCH 04/28] chore: Subscribe to tokenNetworkFilter in token-list --- .../asset-list/network-filter/network-filter.tsx | 10 ++++------ ui/components/app/assets/token-list/token-list.tsx | 4 +++- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index 9507af3b3c0a..1e97146d6e13 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -4,8 +4,8 @@ import { setTokenNetworkFilter } from '../../../../../store/actions'; import { getCurrentChainId, getPreferences } from '../../../../../selectors'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { SelectableListItem } from '../sort-control/sort-control'; -import { Box } from '../../../../component-library/box/box'; -import { Text } from '../../../../component-library/text/text'; +// import { Text } from '../../../../component-library/text/text'; +// import { Box } from '../../../../component-library/box/box'; type SortControlProps = { handleClose: () => void; @@ -30,15 +30,13 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { isSelected={!Object.keys(tokenNetworkFilter).length} onClick={() => handleFilter({})} > - All Networks - 12,000 + All Networks 12,000 handleFilter({ [chainId]: true })} > - Current Network - 2,000 + Current Network 2,000 ); diff --git a/ui/components/app/assets/token-list/token-list.tsx b/ui/components/app/assets/token-list/token-list.tsx index 8a107b154fb9..c784f2579189 100644 --- a/ui/components/app/assets/token-list/token-list.tsx +++ b/ui/components/app/assets/token-list/token-list.tsx @@ -30,7 +30,7 @@ export default function TokenList({ nativeToken, }: TokenListProps) { const t = useI18nContext(); - const { tokenSortConfig } = useSelector(getPreferences); + const { tokenSortConfig, tokenNetworkFilter } = useSelector(getPreferences); const selectedAccount = useSelector(getSelectedAccount); const conversionRate = useSelector(getConversionRate); const nativeTokenWithBalance = useNativeTokenBalance(); @@ -52,6 +52,7 @@ export default function TokenList({ }; const sortedTokens = useMemo(() => { + console.log('filter assets', tokenNetworkFilter); return sortAssets( [nativeTokenWithBalance, ...tokensWithBalances], tokenSortConfig, @@ -59,6 +60,7 @@ export default function TokenList({ }, [ tokensWithBalances, tokenSortConfig, + tokenNetworkFilter, conversionRate, contractExchangeRates, ]); From 90c9b0eaa550401fb9239f0d76aa29b4effbe184 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Fri, 11 Oct 2024 13:04:44 -1000 Subject: [PATCH 05/28] chore: Display multiAccountBalance, and selectedAccountBalance --- .../network-filter/network-filter.tsx | 39 ++++++++++++++++--- .../app/assets/token-list/token-list.tsx | 10 +++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index 1e97146d6e13..015884bd4fa6 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -1,9 +1,19 @@ -import React from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import React, { useMemo } from 'react'; +import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { setTokenNetworkFilter } from '../../../../../store/actions'; -import { getCurrentChainId, getPreferences } from '../../../../../selectors'; +import { + InternalAccountWithBalance, + getCurrentChainId, + getMetaMaskAccountsOrdered, + getPreferences, + getSelectedInternalAccount, + getShouldHideZeroBalanceTokens, + getTokenExchangeRates, +} from '../../../../../selectors'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { SelectableListItem } from '../sort-control/sort-control'; +import { useAccountTotalFiatBalance } from '../../../../../hooks/useAccountTotalFiatBalance'; +import { getConversionRate } from '../../../../../ducks/metamask/metamask'; // import { Text } from '../../../../component-library/text/text'; // import { Box } from '../../../../component-library/box/box'; @@ -15,7 +25,26 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { const t = useI18nContext(); const dispatch = useDispatch(); const chainId = useSelector(getCurrentChainId); + const selectedAccount = useSelector(getSelectedInternalAccount); const { tokenNetworkFilter } = useSelector(getPreferences); + const accounts: InternalAccountWithBalance[] = useSelector( + getMetaMaskAccountsOrdered, + ); + const shouldHideZeroBalanceTokens = useSelector( + getShouldHideZeroBalanceTokens, + ); + + const { totalFiatBalance: selectedAccountBalance, loading } = + useAccountTotalFiatBalance(selectedAccount, shouldHideZeroBalanceTokens); + + let multiAccountBalance = 0; + accounts.forEach((account) => { + const { totalFiatBalance } = useAccountTotalFiatBalance( + account, + shouldHideZeroBalanceTokens, + ); + multiAccountBalance = multiAccountBalance + parseFloat(totalFiatBalance); + }); const handleFilter = (chainFilters: Record) => { dispatch(setTokenNetworkFilter(chainFilters)); @@ -30,13 +59,13 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { isSelected={!Object.keys(tokenNetworkFilter).length} onClick={() => handleFilter({})} > - All Networks 12,000 + All Networks {!loading && multiAccountBalance} handleFilter({ [chainId]: true })} > - Current Network 2,000 + Current Network {selectedAccountBalance} ); diff --git a/ui/components/app/assets/token-list/token-list.tsx b/ui/components/app/assets/token-list/token-list.tsx index c784f2579189..cbb2e44d4bfb 100644 --- a/ui/components/app/assets/token-list/token-list.tsx +++ b/ui/components/app/assets/token-list/token-list.tsx @@ -11,6 +11,8 @@ import { import { TokenWithBalance } from '../asset-list/asset-list'; import { sortAssets } from '../util/sort'; import { + InternalAccountWithBalance, + getMetaMaskAccountsOrdered, getPreferences, getSelectedAccount, getShouldHideZeroBalanceTokens, @@ -19,6 +21,14 @@ import { import { useAccountTotalFiatBalance } from '../../../../hooks/useAccountTotalFiatBalance'; import { getConversionRate } from '../../../../ducks/metamask/metamask'; import { useNativeTokenBalance } from '../asset-list/native-token/use-native-token-balance'; +import { useMultichainSelector } from '../../../../hooks/useMultichainSelector'; +import { + getMultichainCurrentCurrency, + getMultichainNativeCurrency, + getMultichainShouldShowFiat, +} from '../../../../selectors/multichain'; +import { ETH_DEFAULT_DECIMALS } from '../../../../constants'; +import { EtherDenomination } from '../../../../../shared/constants/common'; type TokenListProps = { onTokenClick: (arg: string) => void; From a66c9993743db9d24c4bdc2794cc798653d83975 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Fri, 11 Oct 2024 13:09:40 -1000 Subject: [PATCH 06/28] chore: Optimize multiAccountBalance with reduce function --- .../assets/asset-list/network-filter/network-filter.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index 015884bd4fa6..dfb8c4354837 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -37,14 +37,13 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { const { totalFiatBalance: selectedAccountBalance, loading } = useAccountTotalFiatBalance(selectedAccount, shouldHideZeroBalanceTokens); - let multiAccountBalance = 0; - accounts.forEach((account) => { + const multiAccountBalance = accounts.reduce((acc, account) => { const { totalFiatBalance } = useAccountTotalFiatBalance( account, shouldHideZeroBalanceTokens, ); - multiAccountBalance = multiAccountBalance + parseFloat(totalFiatBalance); - }); + return acc + parseFloat(totalFiatBalance); + }, 0); const handleFilter = (chainFilters: Record) => { dispatch(setTokenNetworkFilter(chainFilters)); From 7dd5a2c8927170d267129932f2db3c6790d0cc87 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Tue, 15 Oct 2024 14:06:32 -1000 Subject: [PATCH 07/28] chore: Cross chain balances do not yet exist, add todo --- .../network-filter/network-filter.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index dfb8c4354837..b43f99258beb 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -14,6 +14,8 @@ import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { SelectableListItem } from '../sort-control/sort-control'; import { useAccountTotalFiatBalance } from '../../../../../hooks/useAccountTotalFiatBalance'; import { getConversionRate } from '../../../../../ducks/metamask/metamask'; +import { useMultichainAccountTotalFiatBalance } from '../../../../../hooks/useMultichainAccountTotalFiatBalance'; +import { getMultichainBalances } from '../../../../../selectors/multichain'; // import { Text } from '../../../../component-library/text/text'; // import { Box } from '../../../../component-library/box/box'; @@ -34,16 +36,14 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { getShouldHideZeroBalanceTokens, ); + const balances = useSelector(getMultichainBalances); + console.log('BALANCES: ', balances); + const { totalFiatBalance: selectedAccountBalance, loading } = useAccountTotalFiatBalance(selectedAccount, shouldHideZeroBalanceTokens); - const multiAccountBalance = accounts.reduce((acc, account) => { - const { totalFiatBalance } = useAccountTotalFiatBalance( - account, - shouldHideZeroBalanceTokens, - ); - return acc + parseFloat(totalFiatBalance); - }, 0); + // TODO: fetch balances across networks + // const multiNetworkAccountBalance = useMultichainAccountBalance() const handleFilter = (chainFilters: Record) => { dispatch(setTokenNetworkFilter(chainFilters)); @@ -58,13 +58,13 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { isSelected={!Object.keys(tokenNetworkFilter).length} onClick={() => handleFilter({})} > - All Networks {!loading && multiAccountBalance} + All Networks handleFilter({ [chainId]: true })} > - Current Network {selectedAccountBalance} + Current Network {!loading && selectedAccountBalance} ); From a838c74f122035340c4bb133221edaa738455d20 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Tue, 15 Oct 2024 14:42:34 -1000 Subject: [PATCH 08/28] chore: Polish styling of list items in dropdown --- .../network-filter/network-filter.tsx | 104 ++++++++++++++---- .../asset-list/sort-control/sort-control.tsx | 4 +- 2 files changed, 86 insertions(+), 22 deletions(-) diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index b43f99258beb..de2098165af2 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -1,23 +1,29 @@ -import React, { useMemo } from 'react'; -import { shallowEqual, useDispatch, useSelector } from 'react-redux'; +import React from 'react'; +import { useDispatch, useSelector } from 'react-redux'; import { setTokenNetworkFilter } from '../../../../../store/actions'; import { - InternalAccountWithBalance, getCurrentChainId, - getMetaMaskAccountsOrdered, + getCurrentNetwork, + getIsTestnet, getPreferences, getSelectedInternalAccount, getShouldHideZeroBalanceTokens, - getTokenExchangeRates, + getNetworkConfigurationsByChainId, } from '../../../../../selectors'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { SelectableListItem } from '../sort-control/sort-control'; import { useAccountTotalFiatBalance } from '../../../../../hooks/useAccountTotalFiatBalance'; -import { getConversionRate } from '../../../../../ducks/metamask/metamask'; -import { useMultichainAccountTotalFiatBalance } from '../../../../../hooks/useMultichainAccountTotalFiatBalance'; -import { getMultichainBalances } from '../../../../../selectors/multichain'; -// import { Text } from '../../../../component-library/text/text'; -// import { Box } from '../../../../component-library/box/box'; +import { Text } from '../../../../component-library/text/text'; +import { + Display, + JustifyContent, + TextColor, + TextVariant, +} from '../../../../../helpers/constants/design-system'; +import { Box } from '../../../../component-library/box/box'; +import { AvatarNetwork } from '../../../../component-library'; +import UserPreferencedCurrencyDisplay from '../../../user-preferenced-currency-display'; +import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../../../shared/constants/network'; type SortControlProps = { handleClose: () => void; @@ -28,17 +34,15 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { const dispatch = useDispatch(); const chainId = useSelector(getCurrentChainId); const selectedAccount = useSelector(getSelectedInternalAccount); - const { tokenNetworkFilter } = useSelector(getPreferences); - const accounts: InternalAccountWithBalance[] = useSelector( - getMetaMaskAccountsOrdered, - ); + const currentNetwork = useSelector(getCurrentNetwork); + const allNetworks = useSelector(getNetworkConfigurationsByChainId); + const isTestnet = useSelector(getIsTestnet); + const { tokenNetworkFilter, showNativeTokenAsMainBalance } = + useSelector(getPreferences); const shouldHideZeroBalanceTokens = useSelector( getShouldHideZeroBalanceTokens, ); - const balances = useSelector(getMultichainBalances); - console.log('BALANCES: ', balances); - const { totalFiatBalance: selectedAccountBalance, loading } = useAccountTotalFiatBalance(selectedAccount, shouldHideZeroBalanceTokens); @@ -58,13 +62,75 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { isSelected={!Object.keys(tokenNetworkFilter).length} onClick={() => handleFilter({})} > - All Networks + + + + All Networks + + + $1,000.00 + + + + {Object.values(allNetworks).map((network, index) => { + if (index >= 5) return null; // only show a max of 5 icons overlapping + const chainId = + network.chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP; + return ( + + ); + })} + + handleFilter({ [chainId]: true })} > - Current Network {!loading && selectedAccountBalance} + + + + Current Network + + + + + ); diff --git a/ui/components/app/assets/asset-list/sort-control/sort-control.tsx b/ui/components/app/assets/asset-list/sort-control/sort-control.tsx index c45a5488f1a6..69622bc73495 100644 --- a/ui/components/app/assets/asset-list/sort-control/sort-control.tsx +++ b/ui/components/app/assets/asset-list/sort-control/sort-control.tsx @@ -45,9 +45,7 @@ export const SelectableListItem = ({ })} onClick={onClick} > - - {children} - + {children} {isSelected && ( Date: Tue, 15 Oct 2024 14:44:15 -1000 Subject: [PATCH 09/28] chore: Cleanup --- ui/components/app/assets/token-list/token-list.tsx | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/ui/components/app/assets/token-list/token-list.tsx b/ui/components/app/assets/token-list/token-list.tsx index cbb2e44d4bfb..11190c68f267 100644 --- a/ui/components/app/assets/token-list/token-list.tsx +++ b/ui/components/app/assets/token-list/token-list.tsx @@ -11,8 +11,6 @@ import { import { TokenWithBalance } from '../asset-list/asset-list'; import { sortAssets } from '../util/sort'; import { - InternalAccountWithBalance, - getMetaMaskAccountsOrdered, getPreferences, getSelectedAccount, getShouldHideZeroBalanceTokens, @@ -21,14 +19,6 @@ import { import { useAccountTotalFiatBalance } from '../../../../hooks/useAccountTotalFiatBalance'; import { getConversionRate } from '../../../../ducks/metamask/metamask'; import { useNativeTokenBalance } from '../asset-list/native-token/use-native-token-balance'; -import { useMultichainSelector } from '../../../../hooks/useMultichainSelector'; -import { - getMultichainCurrentCurrency, - getMultichainNativeCurrency, - getMultichainShouldShowFiat, -} from '../../../../selectors/multichain'; -import { ETH_DEFAULT_DECIMALS } from '../../../../constants'; -import { EtherDenomination } from '../../../../../shared/constants/common'; type TokenListProps = { onTokenClick: (arg: string) => void; @@ -62,7 +52,7 @@ export default function TokenList({ }; const sortedTokens = useMemo(() => { - console.log('filter assets', tokenNetworkFilter); + // TODO filter assets by networkTokenFilter before sorting return sortAssets( [nativeTokenWithBalance, ...tokensWithBalances], tokenSortConfig, From bf5913c22292b3d5ff7a79e30f61390d69735a73 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Mon, 21 Oct 2024 14:57:40 -0700 Subject: [PATCH 10/28] fix: Update unit tests in preferences-controller --- app/scripts/controllers/preferences-controller.test.ts | 2 ++ app/scripts/controllers/preferences-controller.ts | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/scripts/controllers/preferences-controller.test.ts b/app/scripts/controllers/preferences-controller.test.ts index 9c28ed7c43a0..6468c7772fa2 100644 --- a/app/scripts/controllers/preferences-controller.test.ts +++ b/app/scripts/controllers/preferences-controller.test.ts @@ -749,6 +749,7 @@ describe('preferences controller', () => { order: 'dsc', sortCallback: 'stringNumeric', }, + tokenNetworkFilter: {}, }); }); @@ -777,6 +778,7 @@ describe('preferences controller', () => { order: 'dsc', sortCallback: 'stringNumeric', }, + tokenNetworkFilter: {}, }); }); }); diff --git a/app/scripts/controllers/preferences-controller.ts b/app/scripts/controllers/preferences-controller.ts index a9a2ffafa8cd..4475d06bfefc 100644 --- a/app/scripts/controllers/preferences-controller.ts +++ b/app/scripts/controllers/preferences-controller.ts @@ -221,6 +221,7 @@ export const getDefaultPreferencesControllerState = order: 'dsc', sortCallback: 'stringNumeric', }, + tokenNetworkFilter: {}, }, // ENS decentralized website resolution ipfsGateway: IPFS_DEFAULT_GATEWAY_URL, @@ -471,8 +472,6 @@ export class PreferencesController extends BaseController< ...addedNonMainNetwork, ...testNetworks, }, - tokenNetworkFilter: {}, - shouldShowAggregatedBalancePopover: true, // by default user should see popover; ...state, }, }); From 85d51611c29fd83984979416c345be02b7ca80fd Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Mon, 21 Oct 2024 15:30:14 -0700 Subject: [PATCH 11/28] feat: Add filterAssets function --- ui/components/app/assets/util/filter.test.ts | 57 ++++++++++++++++++++ ui/components/app/assets/util/filter.ts | 27 ++++++++++ 2 files changed, 84 insertions(+) create mode 100644 ui/components/app/assets/util/filter.test.ts create mode 100644 ui/components/app/assets/util/filter.ts diff --git a/ui/components/app/assets/util/filter.test.ts b/ui/components/app/assets/util/filter.test.ts new file mode 100644 index 000000000000..d285b09efcdb --- /dev/null +++ b/ui/components/app/assets/util/filter.test.ts @@ -0,0 +1,57 @@ +import { filterAssets, FilterCriteria } from './filter'; // Assuming the filter function is in a file named 'filter.ts' + +type MockToken = { + name: string; + symbol: string; + chainId: number; +}; + +const mockTokens: MockToken[] = [ + { name: 'Token1', symbol: 'T1', chainId: 1 }, + { name: 'Token2', symbol: 'T2', chainId: 2 }, + { name: 'Token3', symbol: 'T3', chainId: 1 }, + { name: 'Token4', symbol: 'T4', chainId: 3 }, +]; + +// Define the filtering tests for chainId +describe('filterAssets function - chainId', () => { + test('filters by chainId including chainId 1 and 3', () => { + const criteria: FilterCriteria[] = [ + { key: 'chainId', values: { '1': 'true', '3': 'true' } }, // Only include chainId 1 and 3 + ]; + + const filtered = filterAssets(mockTokens, criteria); + + expect(filtered.length).toBe(3); + expect(filtered.map((token) => token.chainId)).toEqual([1, 1, 3]); + }); + + test('filters by chainId including only chainId 2', () => { + const criteria: FilterCriteria[] = [ + { key: 'chainId', values: { '2': 'true' } }, // Only include chainId 2 + ]; + + const filtered = filterAssets(mockTokens, criteria); + + expect(filtered.length).toBe(1); + expect(filtered[0].chainId).toBe(2); + }); + + test('returns all tokens if criteria is empty', () => { + const criteria: FilterCriteria[] = []; // No criteria, should return all tokens + + const filtered = filterAssets(mockTokens, criteria); + + expect(filtered.length).toBe(mockTokens.length); + }); + + test('filters by chainId excluding all tokens', () => { + const criteria: FilterCriteria[] = [ + { key: 'chainId', values: { '4': 'true' } }, // No token with chainId 4, should return empty array + ]; + + const filtered = filterAssets(mockTokens, criteria); + + expect(filtered.length).toBe(0); + }); +}); diff --git a/ui/components/app/assets/util/filter.ts b/ui/components/app/assets/util/filter.ts new file mode 100644 index 000000000000..04b3a054a9ef --- /dev/null +++ b/ui/components/app/assets/util/filter.ts @@ -0,0 +1,27 @@ +import { get } from 'lodash'; + +export type FilterCriteria = { + key: string; + values: Record; +}; + +function getNestedValue(obj: T, keyPath: string): any { + return get(obj, keyPath); +} + +export function filterAssets(array: T[], criteria: FilterCriteria[]): T[] { + // If no criteria, return all tokens + if (criteria.length === 0) { + return array; + } + + return array.filter((item) => { + return criteria.every((criterion) => { + // key is the value of the objects to be sorted by (for instance chainId of each token) + // criterion is the Record to evaluate each token, and whether it should be included in the list. If true, include + const { key, values } = criterion; + const nestedValue = getNestedValue(item, key); + return values[nestedValue]; + }); + }); +} From 72ea2cf5dbbcd676bea8af8d6da303f8125e194f Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Mon, 21 Oct 2024 16:04:52 -0700 Subject: [PATCH 12/28] chore: Polish filters to be layerable in order of importance, allowing custom filter logic --- ui/components/app/assets/util/filter.test.ts | 95 ++++++++++++++------ ui/components/app/assets/util/filter.ts | 49 ++++++++-- 2 files changed, 108 insertions(+), 36 deletions(-) diff --git a/ui/components/app/assets/util/filter.test.ts b/ui/components/app/assets/util/filter.test.ts index d285b09efcdb..c4badf7eb2a7 100644 --- a/ui/components/app/assets/util/filter.test.ts +++ b/ui/components/app/assets/util/filter.test.ts @@ -1,23 +1,27 @@ -import { filterAssets, FilterCriteria } from './filter'; // Assuming the filter function is in a file named 'filter.ts' - -type MockToken = { - name: string; - symbol: string; - chainId: number; -}; - -const mockTokens: MockToken[] = [ - { name: 'Token1', symbol: 'T1', chainId: 1 }, - { name: 'Token2', symbol: 'T2', chainId: 2 }, - { name: 'Token3', symbol: 'T3', chainId: 1 }, - { name: 'Token4', symbol: 'T4', chainId: 3 }, -]; - -// Define the filtering tests for chainId -describe('filterAssets function - chainId', () => { - test('filters by chainId including chainId 1 and 3', () => { +import { filterAssets, FilterCriteria } from './filter'; + +describe('filterAssets function - balance and chainId filtering', () => { + type MockToken = { + name: string; + symbol: string; + chainId: number; + balance: number; + }; + + const mockTokens: MockToken[] = [ + { name: 'Token1', symbol: 'T1', chainId: 1, balance: 100 }, + { name: 'Token2', symbol: 'T2', chainId: 2, balance: 50 }, + { name: 'Token3', symbol: 'T3', chainId: 1, balance: 200 }, + { name: 'Token4', symbol: 'T4', chainId: 3, balance: 150 }, + ]; + + test('filters by inclusive chainId', () => { const criteria: FilterCriteria[] = [ - { key: 'chainId', values: { '1': 'true', '3': 'true' } }, // Only include chainId 1 and 3 + { + key: 'chainId', + opts: { '1': true, '3': true }, // ChainId must be 1 or 3 + filterCallback: 'inclusive', + }, ]; const filtered = filterAssets(mockTokens, criteria); @@ -26,32 +30,65 @@ describe('filterAssets function - chainId', () => { expect(filtered.map((token) => token.chainId)).toEqual([1, 1, 3]); }); - test('filters by chainId including only chainId 2', () => { + test('filters tokens with balance between 100 and 150 inclusive', () => { + const criteria: FilterCriteria[] = [ + { + key: 'balance', + opts: { min: 100, max: 150 }, // Balance between 100 and 150 + filterCallback: 'range', + }, + ]; + + const filtered = filterAssets(mockTokens, criteria); + + expect(filtered.length).toBe(2); // Token1 and Token4 + expect(filtered.map((token) => token.balance)).toEqual([100, 150]); + }); + + test('filters by inclusive chainId and balance range', () => { const criteria: FilterCriteria[] = [ - { key: 'chainId', values: { '2': 'true' } }, // Only include chainId 2 + { + key: 'chainId', + opts: { '1': true, '3': true }, // ChainId must be 1 or 3 + filterCallback: 'inclusive', + }, + { + key: 'balance', + opts: { min: 100, max: 150 }, // Balance between 100 and 150 + filterCallback: 'range', + }, ]; const filtered = filterAssets(mockTokens, criteria); - expect(filtered.length).toBe(1); - expect(filtered[0].chainId).toBe(2); + expect(filtered.length).toBe(2); }); - test('returns all tokens if criteria is empty', () => { - const criteria: FilterCriteria[] = []; // No criteria, should return all tokens + test('returns no tokens if no chainId matches', () => { + const criteria: FilterCriteria[] = [ + { + key: 'chainId', + opts: { '4': true }, // No token with chainId 4 + filterCallback: 'inclusive', + }, + ]; const filtered = filterAssets(mockTokens, criteria); - expect(filtered.length).toBe(mockTokens.length); + expect(filtered.length).toBe(0); // No matching tokens }); - test('filters by chainId excluding all tokens', () => { + test('returns no tokens if balance is not within range', () => { const criteria: FilterCriteria[] = [ - { key: 'chainId', values: { '4': 'true' } }, // No token with chainId 4, should return empty array + { + key: 'balance', + opts: { min: 300, max: 400 }, // No token with balance between 300 and 400 + filterCallback: 'range', + }, ]; const filtered = filterAssets(mockTokens, criteria); - expect(filtered.length).toBe(0); + expect(filtered.length).toBe(0); // No matching tokens }); }); diff --git a/ui/components/app/assets/util/filter.ts b/ui/components/app/assets/util/filter.ts index 04b3a054a9ef..d7b0090e365b 100644 --- a/ui/components/app/assets/util/filter.ts +++ b/ui/components/app/assets/util/filter.ts @@ -2,26 +2,61 @@ import { get } from 'lodash'; export type FilterCriteria = { key: string; - values: Record; + opts?: Record; // Use opts for range, inclusion, etc. + filterCallback?: keyof FilterCallbacksT; // Specify the type of filter: 'range', 'inclusive', etc. }; -function getNestedValue(obj: T, keyPath: string): any { +export type FilterType = string | number | boolean | Date; +export type FilterCallbacksT = { + inclusive: (value: any, opts: Record) => boolean; + range: (value: number, opts: Record) => boolean; +}; + +const filterCallbacks: FilterCallbacksT = { + inclusive: (value: any, opts: Record) => opts[value], + range: (value: number, opts: Record) => + value >= opts.min && value <= opts.max, +}; + +function getNestedValue(obj: T, keyPath: string): FilterType { return get(obj, keyPath); } export function filterAssets(array: T[], criteria: FilterCriteria[]): T[] { - // If no criteria, return all tokens if (criteria.length === 0) { return array; } return array.filter((item) => { return criteria.every((criterion) => { - // key is the value of the objects to be sorted by (for instance chainId of each token) - // criterion is the Record to evaluate each token, and whether it should be included in the list. If true, include - const { key, values } = criterion; + const { key, opts, filterCallback } = criterion; const nestedValue = getNestedValue(item, key); - return values[nestedValue]; + + if (filterCallback && opts) { + switch (filterCallback) { + case 'inclusive': + return filterCallbacks.inclusive( + nestedValue, + opts as Record, + ); + case 'range': + // Type guard to ensure nestedValue is a number + if (typeof nestedValue === 'number') { + return filterCallbacks.range( + nestedValue, + opts as { + min: number; + max: number; + }, + ); + } + return false; // If not a number, range filtering cannot be applied + default: + return true; + } + } + + return true; // Default case, return true to include item if no conditions are met }); }); } From 8b5278002103cda8f52747e44d0905360c50a542 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Mon, 21 Oct 2024 16:21:01 -0700 Subject: [PATCH 13/28] fix: Lint tsc, specifiy chain indication rather than arbitrary number --- ui/components/app/assets/util/filter.test.ts | 26 +++++++++++--------- ui/components/app/assets/util/filter.ts | 19 ++++++++------ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/ui/components/app/assets/util/filter.test.ts b/ui/components/app/assets/util/filter.test.ts index c4badf7eb2a7..fd5a612d590b 100644 --- a/ui/components/app/assets/util/filter.test.ts +++ b/ui/components/app/assets/util/filter.test.ts @@ -4,30 +4,34 @@ describe('filterAssets function - balance and chainId filtering', () => { type MockToken = { name: string; symbol: string; - chainId: number; + chainId: string; // Updated to string (e.g., '0x01', '0x89') balance: number; }; const mockTokens: MockToken[] = [ - { name: 'Token1', symbol: 'T1', chainId: 1, balance: 100 }, - { name: 'Token2', symbol: 'T2', chainId: 2, balance: 50 }, - { name: 'Token3', symbol: 'T3', chainId: 1, balance: 200 }, - { name: 'Token4', symbol: 'T4', chainId: 3, balance: 150 }, + { name: 'Token1', symbol: 'T1', chainId: '0x01', balance: 100 }, + { name: 'Token2', symbol: 'T2', chainId: '0x02', balance: 50 }, + { name: 'Token3', symbol: 'T3', chainId: '0x01', balance: 200 }, + { name: 'Token4', symbol: 'T4', chainId: '0x89', balance: 150 }, ]; test('filters by inclusive chainId', () => { const criteria: FilterCriteria[] = [ { key: 'chainId', - opts: { '1': true, '3': true }, // ChainId must be 1 or 3 + opts: { '0x01': true, '0x89': true }, // ChainId must be '0x01' or '0x89' filterCallback: 'inclusive', }, ]; const filtered = filterAssets(mockTokens, criteria); - expect(filtered.length).toBe(3); - expect(filtered.map((token) => token.chainId)).toEqual([1, 1, 3]); + expect(filtered.length).toBe(3); // Should include 3 tokens with chainId '0x01' and '0x89' + expect(filtered.map((token) => token.chainId)).toEqual([ + '0x01', + '0x01', + '0x89', + ]); }); test('filters tokens with balance between 100 and 150 inclusive', () => { @@ -49,7 +53,7 @@ describe('filterAssets function - balance and chainId filtering', () => { const criteria: FilterCriteria[] = [ { key: 'chainId', - opts: { '1': true, '3': true }, // ChainId must be 1 or 3 + opts: { '0x01': true, '0x89': true }, // ChainId must be '0x01' or '0x89' filterCallback: 'inclusive', }, { @@ -61,14 +65,14 @@ describe('filterAssets function - balance and chainId filtering', () => { const filtered = filterAssets(mockTokens, criteria); - expect(filtered.length).toBe(2); + expect(filtered.length).toBe(2); // Token1 and Token4 meet both criteria }); test('returns no tokens if no chainId matches', () => { const criteria: FilterCriteria[] = [ { key: 'chainId', - opts: { '4': true }, // No token with chainId 4 + opts: { '0x04': true }, // No token with chainId '0x04' filterCallback: 'inclusive', }, ]; diff --git a/ui/components/app/assets/util/filter.ts b/ui/components/app/assets/util/filter.ts index d7b0090e365b..a5693490b4a1 100644 --- a/ui/components/app/assets/util/filter.ts +++ b/ui/components/app/assets/util/filter.ts @@ -3,17 +3,19 @@ import { get } from 'lodash'; export type FilterCriteria = { key: string; opts?: Record; // Use opts for range, inclusion, etc. - filterCallback?: keyof FilterCallbacksT; // Specify the type of filter: 'range', 'inclusive', etc. + filterCallback?: FilterCallbackKeys; // Specify the type of filter: 'range', 'inclusive', etc. }; export type FilterType = string | number | boolean | Date; +type FilterCallbackKeys = keyof FilterCallbacksT; + export type FilterCallbacksT = { - inclusive: (value: any, opts: Record) => boolean; + inclusive: (value: string, opts: Record) => boolean; range: (value: number, opts: Record) => boolean; }; const filterCallbacks: FilterCallbacksT = { - inclusive: (value: any, opts: Record) => opts[value], + inclusive: (value: string, opts: Record) => opts[value], range: (value: number, opts: Record) => value >= opts.min && value <= opts.max, }; @@ -35,10 +37,13 @@ export function filterAssets(array: T[], criteria: FilterCriteria[]): T[] { if (filterCallback && opts) { switch (filterCallback) { case 'inclusive': - return filterCallbacks.inclusive( - nestedValue, - opts as Record, - ); + if (typeof nestedValue === 'string') { + return filterCallbacks.inclusive( + nestedValue, + opts as Record, + ); + } + return false; case 'range': // Type guard to ensure nestedValue is a number if (typeof nestedValue === 'number') { From 4349f4f6bf4d9eed4de5fbd4c02cc47d446e62c2 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Mon, 21 Oct 2024 16:40:11 -0700 Subject: [PATCH 14/28] chore: Localize strings --- app/_locales/en/messages.json | 8 ++++++++ .../network-filter/network-filter.tsx | 17 +++++++++++------ .../asset-list/sort-control/sort-control.tsx | 4 +--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 70cb4da8cfb6..fafb20b32e73 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -508,6 +508,10 @@ "allCustodianAccountsConnectedTitle": { "message": "No accounts available to connect" }, + "allNetworks": { + "message": "All Networks", + "description": "Speicifies to token network filter to filter by all Networks" + }, "allOfYour": { "message": "All of your $1", "description": "$1 is the symbol or name of the token that the user is approving spending" @@ -1362,6 +1366,10 @@ "currentLanguage": { "message": "Current language" }, + "currentNetwork": { + "message": "Current Network", + "description": "Specifies to network filter to filter tokens by current network" + }, "currentRpcUrlDeprecated": { "message": "The current rpc url for this network has been deprecated." }, diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index de2098165af2..62d8e11c6767 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -43,7 +43,7 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { getShouldHideZeroBalanceTokens, ); - const { totalFiatBalance: selectedAccountBalance, loading } = + const { totalFiatBalance: selectedAccountBalance } = useAccountTotalFiatBalance(selectedAccount, shouldHideZeroBalanceTokens); // TODO: fetch balances across networks @@ -71,7 +71,7 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { variant={TextVariant.bodyMdMedium} color={TextColor.textDefault} > - All Networks + {t('allNetworks')} { {Object.values(allNetworks).map((network, index) => { - if (index >= 5) return null; // only show a max of 5 icons overlapping - const chainId = + if (index >= 5) { + return null; // only show a max of 5 icons overlapping + } + const networkChainId = network.chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP; return ( { variant={TextVariant.bodyMdMedium} color={TextColor.textDefault} > - Current Network + {t('currentNetwork')} Date: Tue, 22 Oct 2024 10:26:53 -0700 Subject: [PATCH 15/28] chore: Add localized Network string --- app/_locales/en/messages.json | 3 +++ .../asset-list-control-bar/asset-list-control-bar.tsx | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index fafb20b32e73..f699dc10636d 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -3115,6 +3115,9 @@ "networkFee": { "message": "Network fee" }, + "networkFilter": { + "message": "Network" + }, "networkIsBusy": { "message": "Network is busy. Gas prices are high and estimates are less accurate." }, diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index 72936db0f2c7..679565b64b2e 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -88,7 +88,7 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { color={TextColor.textDefault} marginRight={isFullScreen ? 2 : null} > - Network + {t('networkFilter')} Date: Tue, 22 Oct 2024 10:32:17 -0700 Subject: [PATCH 16/28] chore: Add FILTER_TOKENS_TOGGLE feature flag --- builds.yml | 2 + .../asset-list-control-bar.tsx | 38 ++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/builds.yml b/builds.yml index bcd035b56bc1..2bedec76b74a 100644 --- a/builds.yml +++ b/builds.yml @@ -267,6 +267,8 @@ env: - BARAD_DUR: '' # Determines if feature flagged Chain permissions - CHAIN_PERMISSIONS: '' + # Determines if feature flagged Chain permissions + - FILTER_TOKENS_TOGGLE: '' # Enables use of test gas fee flow to debug gas fee estimation - TEST_GAS_FEE_FLOWS: false # Temporary mechanism to enable security alerts API prior to release diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index 679565b64b2e..c15bb8cce132 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -72,24 +72,26 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { isFullScreen ? JustifyContent.flexStart : JustifyContent.spaceBetween } > - - {t('networkFilter')} - + {process.env.FILTER_TOKENS_TOGGLE && ( + + {t('networkFilter')} + + )} Date: Tue, 22 Oct 2024 11:14:23 -0700 Subject: [PATCH 17/28] fix: Show current selection on Network filter, and ellipsize when overflowing --- app/_locales/en/messages.json | 7 ++++--- .../asset-list-control-bar.tsx | 17 ++++++++++++++++- .../asset-list-control-bar/index.scss | 5 +++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 4a6102cce19d..73b6166b261c 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1353,6 +1353,10 @@ "message": "Current Network", "description": "Specifies to network filter to filter tokens by current network" }, + "currentNetwork": { + "message": "Current Network", + "description": "Speicifies to token network filter to filter by current Network. Will render when network nickname is not available" + }, "currentRpcUrlDeprecated": { "message": "The current rpc url for this network has been deprecated." }, @@ -3098,9 +3102,6 @@ "networkFee": { "message": "Network fee" }, - "networkFilter": { - "message": "Network" - }, "networkIsBusy": { "message": "Network is busy. Gas prices are high and estimates are less accurate." }, diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index c15bb8cce132..fda8fb20e957 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -1,4 +1,10 @@ import React, { useRef, useState } from 'react'; +import { useSelector } from 'react-redux'; +import { + getCurrentChainId, + getCurrentNetwork, + getPreferences, +} from '../../../../../selectors'; import { Box, ButtonBase, @@ -14,6 +20,7 @@ import { BorderStyle, Display, JustifyContent, + OverflowWrap, TextColor, } from '../../../../../helpers/constants/design-system'; import ImportControl from '../import-control'; @@ -34,6 +41,9 @@ type AssetListControlBarProps = { const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { const t = useI18nContext(); const popoverRef = useRef(null); + const chainId = useSelector(getCurrentChainId); + const currentNetwork = useSelector(getCurrentNetwork); + const { tokenNetworkFilter } = useSelector(getPreferences); const [isTokenSortPopoverOpen, setIsTokenSortPopoverOpen] = useState(false); const [isNetworkFilterPopoverOpen, setIsNetworkFilterPopoverOpen] = useState(false); @@ -58,6 +68,8 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { setIsNetworkFilterPopoverOpen(false); }; + console.log(tokenNetworkFilter, currentNetwork); + return ( { borderStyle={BorderStyle.solid} color={TextColor.textDefault} marginRight={isFullScreen ? 2 : null} + ellipsis > - {t('networkFilter')} + {tokenNetworkFilter[chainId] + ? currentNetwork?.nickname ?? t('currentNetwork') + : t('allNetworks')} )} diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/index.scss b/ui/components/app/assets/asset-list/asset-list-control-bar/index.scss index 3ed7ae082766..b6dfacce0082 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/index.scss +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/index.scss @@ -2,6 +2,11 @@ padding-top: 8px; padding-bottom: 8px; + &__button { + // using percentage here to allow for full network name to show when full screen, but ellipsize on extension view + max-width: 35%; + } + &__button:hover { background-color: var(--color-background-hover); } From ae96cea9714cf7ce9dee04faaf5bca5d3e8d44b1 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Tue, 22 Oct 2024 11:18:27 -0700 Subject: [PATCH 18/28] fix: Lint --- .../asset-list-control-bar/asset-list-control-bar.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index fda8fb20e957..e565b94ba1c7 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -20,7 +20,6 @@ import { BorderStyle, Display, JustifyContent, - OverflowWrap, TextColor, } from '../../../../../helpers/constants/design-system'; import ImportControl from '../import-control'; @@ -68,8 +67,6 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { setIsNetworkFilterPopoverOpen(false); }; - console.log(tokenNetworkFilter, currentNetwork); - return ( Date: Tue, 22 Oct 2024 12:18:41 -0700 Subject: [PATCH 19/28] fix: Remove duplicate locale string --- app/_locales/en/messages.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 73b6166b261c..fcf01e425462 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1349,10 +1349,6 @@ "currentLanguage": { "message": "Current language" }, - "currentNetwork": { - "message": "Current Network", - "description": "Specifies to network filter to filter tokens by current network" - }, "currentNetwork": { "message": "Current Network", "description": "Speicifies to token network filter to filter by current Network. Will render when network nickname is not available" From f7f09dadac3a2bfe14e43e5e67980a4709428e95 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Tue, 22 Oct 2024 13:15:26 -0700 Subject: [PATCH 20/28] fix: Cleanup --- app/scripts/controllers/preferences-controller.ts | 2 +- builds.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/controllers/preferences-controller.ts b/app/scripts/controllers/preferences-controller.ts index 4475d06bfefc..448f2727f26b 100644 --- a/app/scripts/controllers/preferences-controller.ts +++ b/app/scripts/controllers/preferences-controller.ts @@ -119,7 +119,7 @@ export type Preferences = { order: string; sortCallback: string; }; - tokenNetworkFilter: Record; + tokenNetworkFilter: Record; shouldShowAggregatedBalancePopover: boolean; }; diff --git a/builds.yml b/builds.yml index 2bedec76b74a..b366aa9f584a 100644 --- a/builds.yml +++ b/builds.yml @@ -267,7 +267,7 @@ env: - BARAD_DUR: '' # Determines if feature flagged Chain permissions - CHAIN_PERMISSIONS: '' - # Determines if feature flagged Chain permissions + # Determines if feature flagged Filter toggle - FILTER_TOKENS_TOGGLE: '' # Enables use of test gas fee flow to debug gas fee estimation - TEST_GAS_FEE_FLOWS: false From 693443487c8d196647dbdb47fedc98445dba602b Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Thu, 24 Oct 2024 09:27:33 -0700 Subject: [PATCH 21/28] fix: Clean up filterAssets logic --- ui/components/app/assets/util/filter.ts | 62 +++++++++++-------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/ui/components/app/assets/util/filter.ts b/ui/components/app/assets/util/filter.ts index a5693490b4a1..772d16ad1fcb 100644 --- a/ui/components/app/assets/util/filter.ts +++ b/ui/components/app/assets/util/filter.ts @@ -2,8 +2,8 @@ import { get } from 'lodash'; export type FilterCriteria = { key: string; - opts?: Record; // Use opts for range, inclusion, etc. - filterCallback?: FilterCallbackKeys; // Specify the type of filter: 'range', 'inclusive', etc. + opts: Record; // Use opts for range, inclusion, etc. + filterCallback: FilterCallbackKeys; // Specify the type of filter: 'range', 'inclusive', etc. }; export type FilterType = string | number | boolean | Date; @@ -24,44 +24,34 @@ function getNestedValue(obj: T, keyPath: string): FilterType { return get(obj, keyPath); } -export function filterAssets(array: T[], criteria: FilterCriteria[]): T[] { +export function filterAssets(assets: T[], criteria: FilterCriteria[]): T[] { if (criteria.length === 0) { - return array; + return assets; } - return array.filter((item) => { - return criteria.every((criterion) => { - const { key, opts, filterCallback } = criterion; - const nestedValue = getNestedValue(item, key); + return assets.filter((asset) => + criteria.every(({ key, opts, filterCallback }) => { + const nestedValue = getNestedValue(asset, key); - if (filterCallback && opts) { - switch (filterCallback) { - case 'inclusive': - if (typeof nestedValue === 'string') { - return filterCallbacks.inclusive( - nestedValue, - opts as Record, - ); - } - return false; - case 'range': - // Type guard to ensure nestedValue is a number - if (typeof nestedValue === 'number') { - return filterCallbacks.range( - nestedValue, - opts as { - min: number; - max: number; - }, - ); - } - return false; // If not a number, range filtering cannot be applied - default: - return true; - } + // If there's no callback or options, exit early and don't filter based on this criterion. + if (!filterCallback || !opts) { + return true; } - return true; // Default case, return true to include item if no conditions are met - }); - }); + switch (filterCallback) { + case 'inclusive': + return filterCallbacks.inclusive( + nestedValue as string, + opts as Record, + ); + case 'range': + return filterCallbacks.range( + nestedValue as number, + opts as { min: number; max: number }, + ); + default: + return true; + } + }), + ); } From a2074cd2456cb99db7f3622f316f3bcf220ca70d Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Thu, 24 Oct 2024 09:40:53 -0700 Subject: [PATCH 22/28] fix: Update network-filter Avatar rendering logic --- .../network-filter/network-filter.tsx | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index 62d8e11c6767..14d349a9c5b6 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -43,6 +43,9 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { getShouldHideZeroBalanceTokens, ); + const chainIdImgMappingKey = + chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP; + const { totalFiatBalance: selectedAccountBalance } = useAccountTotalFiatBalance(selectedAccount, shouldHideZeroBalanceTokens); @@ -77,31 +80,29 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { variant={TextVariant.bodyMdMedium} color={TextColor.textDefault} > + {/* TODO: Should query cross chain account balance */} $1,000.00 - {Object.values(allNetworks).map((network, index) => { - if (index >= 5) { - return null; // only show a max of 5 icons overlapping - } - const networkChainId = - network.chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP; - return ( - - ); - })} + {Object.values(allNetworks) + .slice(0, 5) // only show a max of 5 icons overlapping + .map((_, index) => { + const networkImageUrl = + CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[chainIdImgMappingKey] ?? + undefined; + return ( + + ); + })} From 836a11b90f5fc4e640d5cfe8dbc99418d90e5c4a Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Thu, 24 Oct 2024 12:05:39 -0700 Subject: [PATCH 23/28] fix: Duplicate chainId --- .../asset-list/network-filter/network-filter.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index 14d349a9c5b6..cc2d0f38210e 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -43,9 +43,6 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { getShouldHideZeroBalanceTokens, ); - const chainIdImgMappingKey = - chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP; - const { totalFiatBalance: selectedAccountBalance } = useAccountTotalFiatBalance(selectedAccount, shouldHideZeroBalanceTokens); @@ -87,14 +84,16 @@ const NetworkFilter = ({ handleClose }: SortControlProps) => { {Object.values(allNetworks) .slice(0, 5) // only show a max of 5 icons overlapping - .map((_, index) => { + .map((network, index) => { const networkImageUrl = - CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[chainIdImgMappingKey] ?? - undefined; + CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[ + network.chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP + ]; return ( Date: Mon, 28 Oct 2024 13:56:42 -0700 Subject: [PATCH 24/28] chore: Ensure correct isSelected boolean is present in ListItemSelector --- .../asset-list-control-bar/asset-list-control-bar.tsx | 10 ++++++---- ui/components/app/assets/util/filter.ts | 5 ++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index e565b94ba1c7..fa35e9f52ce1 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -3,6 +3,7 @@ import { useSelector } from 'react-redux'; import { getCurrentChainId, getCurrentNetwork, + getNetworkConfigurationsByChainId, getPreferences, } from '../../../../../selectors'; import { @@ -40,7 +41,7 @@ type AssetListControlBarProps = { const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { const t = useI18nContext(); const popoverRef = useRef(null); - const chainId = useSelector(getCurrentChainId); + const allNetworks = useSelector(getNetworkConfigurationsByChainId); const currentNetwork = useSelector(getCurrentNetwork); const { tokenNetworkFilter } = useSelector(getPreferences); const [isTokenSortPopoverOpen, setIsTokenSortPopoverOpen] = useState(false); @@ -99,9 +100,10 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { marginRight={isFullScreen ? 2 : null} ellipsis > - {tokenNetworkFilter[chainId] - ? currentNetwork?.nickname ?? t('currentNetwork') - : t('allNetworks')} + {Object.keys(tokenNetworkFilter).length === + Object.keys(allNetworks).length + ? t('allNetworks') + : currentNetwork?.nickname ?? t('currentNetwork')} )} diff --git a/ui/components/app/assets/util/filter.ts b/ui/components/app/assets/util/filter.ts index 772d16ad1fcb..a908acbcdfc7 100644 --- a/ui/components/app/assets/util/filter.ts +++ b/ui/components/app/assets/util/filter.ts @@ -15,7 +15,10 @@ export type FilterCallbacksT = { }; const filterCallbacks: FilterCallbacksT = { - inclusive: (value: string, opts: Record) => opts[value], + inclusive: (value: string, opts: Record) => { + if (Object.entries(opts).length === 0) return false; + return opts[value]; + }, range: (value: number, opts: Record) => value >= opts.min && value <= opts.max, }; From 1a44e12fb4b0dc0c8e7ac49b8fd5241d38fbe243 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Mon, 28 Oct 2024 14:07:47 -0700 Subject: [PATCH 25/28] fix: Lint --- ui/components/app/assets/util/filter.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/components/app/assets/util/filter.ts b/ui/components/app/assets/util/filter.ts index a908acbcdfc7..20ca7cebcc58 100644 --- a/ui/components/app/assets/util/filter.ts +++ b/ui/components/app/assets/util/filter.ts @@ -16,7 +16,9 @@ export type FilterCallbacksT = { const filterCallbacks: FilterCallbacksT = { inclusive: (value: string, opts: Record) => { - if (Object.entries(opts).length === 0) return false; + if (Object.entries(opts).length === 0) { + return false; + } return opts[value]; }, range: (value: number, opts: Record) => From 1cdaa662257806df2df1f68177ed826760557834 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Mon, 28 Oct 2024 14:58:00 -0700 Subject: [PATCH 26/28] Fix: Lint unused variable import --- .../asset-list/asset-list-control-bar/asset-list-control-bar.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index fa35e9f52ce1..557b44448c2b 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -1,7 +1,6 @@ import React, { useRef, useState } from 'react'; import { useSelector } from 'react-redux'; import { - getCurrentChainId, getCurrentNetwork, getNetworkConfigurationsByChainId, getPreferences, From 7bfb306d0a556e1e6f787206480fdba7c227fca5 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Mon, 28 Oct 2024 15:05:30 -0700 Subject: [PATCH 27/28] fix: Lint, simplify logic of selector comparison --- .../asset-list-control-bar.tsx | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index 557b44448c2b..2b675df96f0e 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -1,10 +1,6 @@ import React, { useRef, useState } from 'react'; import { useSelector } from 'react-redux'; -import { - getCurrentNetwork, - getNetworkConfigurationsByChainId, - getPreferences, -} from '../../../../../selectors'; +import { getCurrentNetwork, getPreferences } from '../../../../../selectors'; import { Box, ButtonBase, @@ -40,7 +36,6 @@ type AssetListControlBarProps = { const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { const t = useI18nContext(); const popoverRef = useRef(null); - const allNetworks = useSelector(getNetworkConfigurationsByChainId); const currentNetwork = useSelector(getCurrentNetwork); const { tokenNetworkFilter } = useSelector(getPreferences); const [isTokenSortPopoverOpen, setIsTokenSortPopoverOpen] = useState(false); @@ -99,10 +94,9 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { marginRight={isFullScreen ? 2 : null} ellipsis > - {Object.keys(tokenNetworkFilter).length === - Object.keys(allNetworks).length - ? t('allNetworks') - : currentNetwork?.nickname ?? t('currentNetwork')} + {Object.keys(tokenNetworkFilter)?.length + ? currentNetwork?.nickname ?? t('currentNetwork') + : t('allNetworks')} )} From cf78624a3a08bae025c9cd0deae415ff54e48ee1 Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Mon, 28 Oct 2024 15:11:04 -0700 Subject: [PATCH 28/28] fix: Handle edge case where tokeNetworkFilter is undefined, this should not break the app --- .../asset-list-control-bar/asset-list-control-bar.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index 2b675df96f0e..de771976e677 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -42,6 +42,8 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { const [isNetworkFilterPopoverOpen, setIsNetworkFilterPopoverOpen] = useState(false); + const allNetworksFilterShown = Object.keys(tokenNetworkFilter ?? {}).length; + const windowType = getEnvironmentType(); const isFullScreen = windowType !== ENVIRONMENT_TYPE_NOTIFICATION && @@ -94,7 +96,7 @@ const AssetListControlBar = ({ showTokensLinks }: AssetListControlBarProps) => { marginRight={isFullScreen ? 2 : null} ellipsis > - {Object.keys(tokenNetworkFilter)?.length + {allNetworksFilterShown ? currentNetwork?.nickname ?? t('currentNetwork') : t('allNetworks')}