diff --git a/components/brave_wallet_ui/components/desktop/network-filter-selector/index.tsx b/components/brave_wallet_ui/components/desktop/network-filter-selector/index.tsx index 6feebb79cc42..f3801b6a3182 100644 --- a/components/brave_wallet_ui/components/desktop/network-filter-selector/index.tsx +++ b/components/brave_wallet_ui/components/desktop/network-filter-selector/index.tsx @@ -4,13 +4,12 @@ // you can obtain one at https://mozilla.org/MPL/2.0/. import * as React from 'react' -import { useSelector, useDispatch } from 'react-redux' +import { useDispatch } from 'react-redux' // Types import { BraveWallet, SupportedTestNetworks, - WalletState } from '../../../constants/types' import { LOCAL_STORAGE_KEYS } from '../../../common/constants/local-storage-keys' @@ -18,6 +17,9 @@ import { LOCAL_STORAGE_KEYS } from '../../../common/constants/local-storage-keys import NetworkFilterItem from './network-filter-item' import { CreateNetworkIcon } from '../../shared/create-network-icon/index' +// Hooks +import { useGetVisibleNetworksQuery } from '../../../common/slices/api.slice' + // Utils import { WalletActions } from '../../../common/actions' import { getLocale } from '../../../../common/locale' @@ -27,7 +29,9 @@ import { AllNetworksOption, SupportedTopLevelChainIds } from '../../../options/network-filter-options' -import { applySelectedAccountFilter } from '../../../options/account-filter-options' +import { + AllAccountsOptionUniqueKey +} from '../../../options/account-filter-options' // Styled Components import { @@ -39,11 +43,6 @@ import { SecondaryNetworkText, ClickAwayArea } from './style' -import { - useGetNetworkQuery, - useGetVisibleNetworksQuery -} from '../../../common/slices/api.slice' -import { skipToken } from '@reduxjs/toolkit/dist/query' interface Props { networkListSubset?: BraveWallet.NetworkInfo[] @@ -60,81 +59,72 @@ interface Props { export const NetworkFilterSelector = ({ networkListSubset, onSelectNetwork, - selectedNetwork: networkProp, - selectedAccount: accountProp, - isV2 + selectedNetwork = AllNetworksOption, + isV2, + selectedAccount }: Props) => { // state const [showNetworkFilter, setShowNetworkFilter] = React.useState(false) // redux const dispatch = useDispatch() - const accounts = useSelector(({ wallet }: { wallet: WalletState }) => wallet.accounts) - const selectedNetworkFilter = useSelector(({ wallet }: { wallet: WalletState }) => wallet.selectedNetworkFilter) - const selectedAccountFilter = useSelector(({ wallet }: { wallet: WalletState }) => wallet.selectedAccountFilter) // queries const { data: reduxNetworkList } = useGetVisibleNetworksQuery(undefined, { - skip: !!networkListSubset + skip: !!networkListSubset?.length }) - const { data: selectedNetworkFromFilter } = useGetNetworkQuery( - !!networkProp || - !selectedNetworkFilter || - selectedNetworkFilter.chainId === AllNetworksOption.chainId - ? skipToken - : selectedNetworkFilter - ) - const selectedNetwork = - networkProp || - (selectedNetworkFilter.chainId === AllNetworksOption.chainId - ? AllNetworksOption - : selectedNetworkFromFilter || AllNetworksOption) - - const oneFilteredAccount = React.useMemo(() => { - return ( - accountProp || - applySelectedAccountFilter(accounts, selectedAccountFilter).oneAccount - ) - }, [accountProp, accounts, selectedAccountFilter]) + const networks = networkListSubset?.length + ? networkListSubset + : reduxNetworkList // memos const filteredNetworks: BraveWallet.NetworkInfo[] = React.useMemo(() => { // Filters networks by coinType if a selectedAccountFilter is selected - const networks = !oneFilteredAccount - ? networkListSubset - : networkListSubset?.filter( - (network) => network.coin === oneFilteredAccount.accountId.coin + return selectedAccount && + selectedAccount.accountId.uniqueKey !== AllAccountsOptionUniqueKey + ? networks?.filter( + (network) => network.coin === selectedAccount.accountId.coin ) - return networks || reduxNetworkList - }, [networkListSubset, reduxNetworkList, oneFilteredAccount]) - - const sortedNetworks = React.useMemo(() => { - const onlyMainnets = filteredNetworks.filter((network) => - SupportedTopLevelChainIds.includes(network.chainId) - ) - const removedMainnets = filteredNetworks.filter( - (network) => !SupportedTopLevelChainIds.includes(network.chainId) - ) - return [AllNetworksOption, ...onlyMainnets, ...removedMainnets] - }, [filteredNetworks]) + : networks + }, [networks, selectedAccount]) + + const { + primaryNetworks, + secondaryNetworks, + testNetworks + } = React.useMemo(() => { + const primaryNetworks: BraveWallet.NetworkInfo[] = [AllNetworksOption] + const secondaryNetworks: BraveWallet.NetworkInfo[] = [] + const testNetworks: BraveWallet.NetworkInfo[] = [] + + for (const network of filteredNetworks) { + switch (true) { + case SupportedTopLevelChainIds.includes(network.chainId): { + primaryNetworks.push(network) + break + } + + case SupportedTestNetworks.includes(network.chainId): { + testNetworks.push(network) + break + } + + case network.chainId === AllNetworksOption.chainId: + break // pre-sorted + + default: { + secondaryNetworks.push(network) + break + } + } + } - const primaryNetworks = React.useMemo(() => { - const onlyMainnets = filteredNetworks.filter((network) => - SupportedTopLevelChainIds.includes(network.chainId) - ) - return [AllNetworksOption, ...onlyMainnets] - }, [sortedNetworks]) - - const secondaryNetworks = React.useMemo(() => { - const primaryList = [AllNetworksOption.chainId, ...SupportedTopLevelChainIds, ...SupportedTestNetworks] - return sortedNetworks.filter((network) => !primaryList.includes(network.chainId)) - }, [sortedNetworks]) - - const testNetworks = React.useMemo(() => { - return filteredNetworks.filter((network) => - SupportedTestNetworks.includes(network.chainId) - ) + return { + primaryNetworks, + secondaryNetworks, + testNetworks + } }, [filteredNetworks]) const toggleShowNetworkFilter = React.useCallback(() => { @@ -163,64 +153,78 @@ export const NetworkFilterSelector = ({ // render return ( - + - {selectedNetwork.chainId !== AllNetworksOption.chainId && - - } + {selectedNetwork.chainId !== AllNetworksOption.chainId && ( + + )} {selectedNetwork.chainName} - {showNetworkFilter && + {showNetworkFilter && ( - {primaryNetworks.map((network: BraveWallet.NetworkInfo) => + {primaryNetworks.map((network: BraveWallet.NetworkInfo) => ( - - )} - - {secondaryNetworks.length > 0 && + isSelected={ + network.chainId === selectedNetwork.chainId && + network.symbol.toLowerCase() === + selectedNetwork.symbol.toLowerCase() + } + > + ))} + + {secondaryNetworks.length > 0 && ( <> - {getLocale('braveWalletNetworkFilterSecondary')} - {secondaryNetworks.map((network) => + + {getLocale('braveWalletNetworkFilterSecondary')} + + {secondaryNetworks.map((network) => ( - )} + ))} - } + )} - {testNetworks.length > 0 && + {testNetworks.length > 0 && ( <> - {getLocale('braveWalletNetworkFilterTestNetworks')} - {testNetworks.map((network) => + + {getLocale('braveWalletNetworkFilterTestNetworks')} + + {testNetworks.map((network) => ( - )} + ))} - } + )} - } - {showNetworkFilter && - - } - + )} + {showNetworkFilter && } + ) } diff --git a/components/brave_wallet_ui/components/desktop/network-filter-selector/network-filter-item.tsx b/components/brave_wallet_ui/components/desktop/network-filter-selector/network-filter-item.tsx index a3ef4093c1e4..3bed5ce8f01c 100644 --- a/components/brave_wallet_ui/components/desktop/network-filter-selector/network-filter-item.tsx +++ b/components/brave_wallet_ui/components/desktop/network-filter-selector/network-filter-item.tsx @@ -17,14 +17,13 @@ import { AllNetworksOption } from '../../../options/network-filter-options' import { NetworkItemButton, NetworkName, LeftSide, NetworkItemWrapper, BigCheckMark } from './style' export interface Props { - children?: React.ReactNode - selectedNetwork: BraveWallet.NetworkInfo + isSelected: boolean network: BraveWallet.NetworkInfo onSelectNetwork: (network?: BraveWallet.NetworkInfo) => void } function NetworkFilterItem (props: Props) { - const { network, onSelectNetwork, selectedNetwork } = props + const { network, onSelectNetwork, isSelected } = props const onClickSelectNetwork = () => { onSelectNetwork(network) @@ -39,8 +38,7 @@ function NetworkFilterItem (props: Props) { )} {network.chainName} - {network.chainId === selectedNetwork.chainId && - network.symbol.toLowerCase() === selectedNetwork.symbol.toLowerCase() && } + {isSelected ? : null} ) diff --git a/components/brave_wallet_ui/components/shared/create-network-icon/index.tsx b/components/brave_wallet_ui/components/shared/create-network-icon/index.tsx index 41bd84e74f7e..96931c531221 100644 --- a/components/brave_wallet_ui/components/shared/create-network-icon/index.tsx +++ b/components/brave_wallet_ui/components/shared/create-network-icon/index.tsx @@ -25,81 +25,96 @@ import { getNetworkLogo } from '../../../options/asset-options' // Hooks import { useNetworkOrb } from '../../../common/hooks/use-orb' +type SimpleNetwork = Pick< + BraveWallet.NetworkInfo, + 'iconUrls' | 'chainId' | 'symbol' | 'chainName' +> + interface Props { - network?: Pick< - BraveWallet.NetworkInfo, - 'iconUrls' | 'chainId' | 'symbol' | 'chainName' - > + network?: SimpleNetwork marginRight?: number size?: 'huge' | 'big' | 'small' | 'tiny' | 'extra-small' } const isStorybook = isComponentInStorybook() -export const CreateNetworkIcon = ({ - network, - marginRight, - size -}: Props) => { - // computed - const networkImageURL = stripERC20TokenImageURL(network?.iconUrls[0]) - const isRemoteURL = isRemoteImageURL(networkImageURL) - const isDataURL = network?.iconUrls[0]?.startsWith( - 'chrome://erc-token-images/' - ) - - const networkLogo = network - ? getNetworkLogo(network.chainId, network.symbol) - : '' - - const isValidIcon = - isStorybook || - (network && - (isRemoteURL || isDataURL - ? isValidIconExtension(new URL(network?.iconUrls[0]).pathname) - : false)) - - const needsPlaceholder = - networkLogo === '' && (networkImageURL === '' || !isValidIcon) - - const orb = useNetworkOrb(network) +export const CreateNetworkIcon = ({ network, marginRight, size }: Props) => { + // exit early if no network + if (!network) { + return ( + + ) + } - const remoteImage = isRemoteURL - ? `chrome://image?${networkImageURL}` - : '' + // computed + const networkLogo = getNetworkLogo(network.chainId, network.symbol) + const isTestnet = SupportedTestNetworks.includes(network.chainId) - // render - if (needsPlaceholder) { + // simple render + if (networkLogo) { return ( - + ) } + // complex compute + render + const networkIcon = network.iconUrls[0] + const isSandboxUrl = networkIcon?.startsWith('chrome://erc-token-images/') + const networkImageURL = isSandboxUrl + ? stripERC20TokenImageURL(networkIcon) + : networkIcon + + const isRemoteURL = isRemoteImageURL(networkImageURL) + + // needs placeholder + if ( + !networkImageURL || + !isStorybook || + (isRemoteURL || isSandboxUrl + ? !isValidIconExtension(new URL(networkIcon).pathname) + : true) + ) { + return ( + + ) + } + return ( ) } export default CreateNetworkIcon + +function NetworkPlaceholderIcon({ + marginRight, + network +}: { + marginRight: number | undefined + network?: SimpleNetwork +}) { + // custom hooks + const orb = useNetworkOrb(network) + + // render + return ( + + + + ) +}