Skip to content

Commit

Permalink
chore: remove token manage from token picker (#11943)
Browse files Browse the repository at this point in the history
  • Loading branch information
swkatmask authored Nov 22, 2024
1 parent ffaa10a commit 05f0a3a
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 253 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import { memo, useMemo } from 'react'
import { Box, Link, ListItem, ListItemIcon, ListItemText, Typography } from '@mui/material'
import { formatBalance, type FungibleToken } from '@masknet/web3-shared-base'
import { NetworkPluginID } from '@masknet/shared-base'
import { TokenIcon } from '../TokenIcon/index.js'
import { Icons } from '@masknet/icons'
import { useFungibleTokenBalance, useNetwork, useNetworkContext, useWeb3Utils } from '@masknet/web3-hooks-base'
import { NetworkPluginID } from '@masknet/shared-base'
import { LoadingBase, makeStyles } from '@masknet/theme'
import type { Web3Helper } from '@masknet/web3-helpers'
import { makeStyles, LoadingBase, ActionButton } from '@masknet/theme'
import { useFungibleTokenBalance, useNetwork, useNetworkContext, useWeb3Utils } from '@masknet/web3-hooks-base'
import { formatBalance } from '@masknet/web3-shared-base'
import { Box, Link, ListItem, ListItemIcon, ListItemText, Typography } from '@mui/material'
import { memo, useMemo } from 'react'
import { useSharedTrans } from '../../../locales/index.js'
import { TokenListMode } from './type.js'
import { SettingSwitch } from '../SettingSwitch/index.js'
import { useTokenBlocked, useTokenTrusted } from './useTokenBlocked.js'
import { FormattedBalance } from '../../wallet/index.js'
import { DotLoading, NetworkIcon } from '../index.js'
import { useAsyncFn } from 'react-use'
import { TokenIcon } from '../TokenIcon/index.js'

const useStyles = makeStyles()((theme) => ({
icon: {
Expand Down Expand Up @@ -94,17 +90,7 @@ const useStyles = makeStyles()((theme) => ({
}))

export const getFungibleTokenItem = <T extends NetworkPluginID>(
getSource: (address: string) => 'personal' | 'official' | 'external' | 'official-native',
isSelected: (address: string, chainId: Web3Helper.ChainIdAll) => boolean,
mode: TokenListMode,
addOrRemoveTokenToLocal: (
token: FungibleToken<Web3Helper.Definition[T]['ChainId'], Web3Helper.Definition[T]['SchemaType']>,
strategy: 'add' | 'remove',
) => Promise<void>,
trustOrBlockTokenToLocal: (
token: FungibleToken<Web3Helper.Definition[T]['ChainId'], Web3Helper.Definition[T]['SchemaType']>,
strategy: 'trust' | 'block',
) => Promise<void>,
isHiddenChainIcon?: boolean,
isCustomToken?: boolean,
) => {
Expand All @@ -118,68 +104,12 @@ export const getFungibleTokenItem = <T extends NetworkPluginID>(

const { chainId, address, name, symbol, decimals, logoURL, balance } = token

const isBlocked = useTokenBlocked(address)
const isTrust = useTokenTrusted(address, token.chainId)

const { pluginID } = useNetworkContext<T>()
const network = useNetwork(pluginID, chainId)

const source = useMemo(() => getSource(address), [getSource, address])
const selected = useMemo(() => isSelected(address, chainId), [isSelected, address, chainId])

const [{ loading: onAddOrRemoveTokenToLocalLoading }, onAddOrRemoveTokenToLocal] = useAsyncFn(
async (event: React.MouseEvent<HTMLButtonElement | HTMLElement>, strategy: 'add' | 'remove') => {
event.stopPropagation()
if (token) await addOrRemoveTokenToLocal(token, strategy)
},
[token, addOrRemoveTokenToLocal],
)

const [{ loading: onTrustOrBlockTokenToLocalLoading }, onTrustOrBlockTokenToLocal] = useAsyncFn(
async (event: React.ChangeEvent<HTMLInputElement>) => {
event.stopPropagation()
if (token) await trustOrBlockTokenToLocal(token, event.target.checked ? 'trust' : 'block')
},
[token, trustOrBlockTokenToLocal],
)

const explorerLink = useMemo(() => {
return Utils.explorerResolver.fungibleTokenLink(token.chainId, token.address)
}, [token.address, token.chainId, Utils.explorerResolver.fungibleTokenLink])
const selected = isSelected(address, chainId)
const explorerLink = Utils.explorerResolver.fungibleTokenLink(token.chainId, token.address)

const action = useMemo(() => {
if (mode === TokenListMode.Manage) {
if (source === 'personal')
return <Icons.TrashLine onClick={(e) => onAddOrRemoveTokenToLocal(e, 'remove')} size={24} />
return (
<>
{isCustomToken ?
<ActionButton
color="primary"
disabled={onAddOrRemoveTokenToLocalLoading}
loading={onAddOrRemoveTokenToLocalLoading}
className={classes.importButton}
onClick={(e) => onAddOrRemoveTokenToLocal(e, 'add')}>
{t.import()}
</ActionButton>
: <SettingSwitch
disabled={
(source === 'official-native' && mode === TokenListMode.Manage) ||
onTrustOrBlockTokenToLocalLoading
}
classes={{ root: classes.switch }}
onChange={async (event) => {
event.stopPropagation()
event.preventDefault()
await onTrustOrBlockTokenToLocal(event)
}}
size="small"
checked={!isBlocked}
/>
}
</>
)
}
return (
<Typography className={classes.balance}>
{balance === undefined ?
Expand All @@ -195,7 +125,7 @@ export const getFungibleTokenItem = <T extends NetworkPluginID>(
}
</Typography>
)
}, [balance, decimals, isBlocked, source, mode, isTrust])
}, [balance, decimals])

const { data: tokenBalance, isPending: isLoadingTokenBalance } = useFungibleTokenBalance(
NetworkPluginID.PLUGIN_EVM,
Expand All @@ -212,8 +142,8 @@ export const getFungibleTokenItem = <T extends NetworkPluginID>(
key={address}
button
className={`${classes.list} dashboard token-list`}
onClick={mode === TokenListMode.List ? () => onSelect(token) : undefined}
disabled={!!(selected && mode === TokenListMode.List)}>
onClick={() => onSelect(token)}
disabled={selected}>
<ListItemIcon>
<Box position="relative">
<TokenIcon
Expand Down

This file was deleted.

116 changes: 9 additions & 107 deletions packages/shared/src/UI/components/FungibleTokenList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { useCallback, useEffect, useMemo, useState, useTransition } from 'react'
import { uniqBy } from 'lodash-es'
import { EMPTY_LIST, EMPTY_OBJECT, type NetworkPluginID } from '@masknet/shared-base'
import { SearchableList, makeStyles, type MaskFixedSizeListProps, type MaskTextFieldProps } from '@masknet/theme'
import type { Web3Helper } from '@masknet/web3-helpers'
import { AddressType } from '@masknet/web3-shared-evm'
import {
useAccount,
useAddressType,
Expand All @@ -17,7 +14,6 @@ import {
useNetworkContext,
useTrustedFungibleTokens,
useWeb3Utils,
useWeb3State,
} from '@masknet/web3-hooks-base'
import {
CurrencyType,
Expand All @@ -28,13 +24,12 @@ import {
toZero,
type FungibleToken,
} from '@masknet/web3-shared-base'
import { Box, Stack } from '@mui/material'
import { AddressType } from '@masknet/web3-shared-evm'
import { Stack } from '@mui/material'
import { uniqBy } from 'lodash-es'
import { useCallback, useEffect, useMemo, useState, useTransition } from 'react'
import { useSharedTrans } from '../../../locales/index.js'
import { getFungibleTokenItem } from './FungibleTokenItem.js'
import { ManageTokenListBar } from './ManageTokenListBar.js'
import { TokenListMode } from './type.js'

export * from './type.js'

const SEARCH_KEYS = ['address', 'symbol', 'name']

Expand All @@ -55,12 +50,7 @@ export interface FungibleTokenListProps<T extends NetworkPluginID>

FixedSizeListProps?: Partial<MaskFixedSizeListProps>
SearchTextFieldProps?: MaskTextFieldProps
enableManage?: boolean
isHiddenChainIcon?: boolean

setMode?(mode: TokenListMode): void

mode?: TokenListMode
}

const useStyles = makeStyles<{}>()(() => ({
Expand All @@ -85,10 +75,7 @@ export function FungibleTokenList<T extends NetworkPluginID>(props: FungibleToke
FixedSizeListProps,
selectedChainId,
selectedTokens = EMPTY_LIST,
enableManage = false,
isHiddenChainIcon = true,
setMode,
mode = TokenListMode.List,
} = props

const t = useSharedTrans()
Expand All @@ -97,7 +84,6 @@ export function FungibleTokenList<T extends NetworkPluginID>(props: FungibleToke
const { pluginID } = useNetworkContext<T>(props.pluginID)
const account = useAccount(pluginID)
const chainId = useChainId(pluginID, props.chainId)
const { Token } = useWeb3State<'all'>(pluginID)
const Utils = useWeb3Utils(pluginID)

const { data: fungibleTokens = EMPTY_LIST } = useFungibleTokensFromTokenList(pluginID, {
Expand Down Expand Up @@ -143,41 +129,7 @@ export function FungibleTokenList<T extends NetworkPluginID>(props: FungibleToke
{ account, chainId },
)

// To avoid SearchableList re-render, reduce the dep
const sortedFungibleTokensForManage = useMemo(() => {
if (mode === TokenListMode.List) return EMPTY_LIST
const isTrustedToken = currySameAddress(trustedFungibleTokens.map((x) => x.address))

return uniqBy([...(nativeToken ? [nativeToken] : []), ...fungibleTokens, ...trustedFungibleTokens], (x) =>
x.address.toLowerCase(),
).sort((a, z) => {
// trusted token
if (isTrustedToken(a.address)) return -1
if (isTrustedToken(z.address)) return 1

const isNativeTokenA = isSameAddress(a.address, Utils.getNativeTokenAddress(a.chainId))
if (isNativeTokenA) return -1
const isNativeTokenZ = isSameAddress(z.address, Utils.getNativeTokenAddress(z.chainId))
if (isNativeTokenZ) return 1

// mask token with position value
const isMaskTokenA = isSameAddress(a.address, Utils.getMaskTokenAddress(a.chainId))
if (isMaskTokenA) return -1
const isMaskTokenZ = isSameAddress(z.address, Utils.getMaskTokenAddress(z.chainId))
if (isMaskTokenZ) return 1

if (z.rank && (!a.rank || a.rank - z.rank > 0)) return 1
if (a.rank && (!z.rank || z.rank - a.rank > 0)) return -1

// alphabet
if (a.name !== z.name) return a.name < z.name ? -1 : 1

return 0
})
}, [chainId, trustedFungibleTokens, fungibleTokens, nativeToken, mode])

const sortedFungibleTokensForList = useMemo(() => {
if (mode === TokenListMode.Manage) return EMPTY_LIST
const fungibleAssetsTable = Object.fromEntries(
fungibleAssets.filter((x) => x.chainId === chainId).map((x) => [x.address, x]),
)
Expand Down Expand Up @@ -239,7 +191,7 @@ export function FungibleTokenList<T extends NetworkPluginID>(props: FungibleToke

return 0
})
}, [mode, chainId, fungibleAssets, trustedFungibleTokens, filteredFungibleTokens, fungibleTokensBalance])
}, [chainId, fungibleAssets, trustedFungibleTokens, filteredFungibleTokens, fungibleTokensBalance])

// #region add token by address
const [keyword, setKeyword] = useState('')
Expand Down Expand Up @@ -269,14 +221,6 @@ export function FungibleTokenList<T extends NetworkPluginID>(props: FungibleToke
chainId,
})

const isCustomToken = useMemo(
() =>
!sortedFungibleTokensForManage.find(
(x) => isSameAddress(x.address, searchedToken?.address) && searchedToken?.chainId === x.chainId,
) && Boolean(searchedToken),
[sortedFungibleTokensForManage, searchedToken],
)

const { data: tokenBalance = '' } = useFungibleTokenBalance(pluginID, searchedToken?.address, {
chainId,
account,
Expand All @@ -285,49 +229,14 @@ export function FungibleTokenList<T extends NetworkPluginID>(props: FungibleToke

const itemRender = useMemo(() => {
return getFungibleTokenItem<T>(
(address) => {
if (isSameAddress(nativeToken?.address, address)) return 'official-native'

const inOfficialList = fungibleTokens.some((x) => isSameAddress(x.address, address))
if (inOfficialList) return 'official'

const inPersonaList = trustedFungibleTokens.some((x) => isSameAddress(x.address, address))
if (inPersonaList) return 'personal'

return 'external'
},
(address, tokenChainId) => {
if (tokenChainId !== selectedChainId) return false
return selectedTokens.some((x) => isSameAddress(x, address))
},
mode,
async (
token: FungibleToken<Web3Helper.ChainIdAll, Web3Helper.SchemaTypeAll>,
strategy: 'add' | 'remove',
) => {
if (strategy === 'add') await Token?.addToken?.(account, token)
if (strategy === 'remove') await Token?.removeToken?.(account, token)
},
async (
token: FungibleToken<Web3Helper.ChainIdAll, Web3Helper.SchemaTypeAll>,
strategy: 'trust' | 'block',
) => {
if (strategy === 'trust') await Token?.trustToken?.(account, token)
if (strategy === 'block') await Token?.blockToken?.(account, token)
},
isHiddenChainIcon,
isCustomToken,
false,
)
}, [
chainId,
nativeToken?.address,
selectedTokens,
mode,
trustedFungibleTokens,
fungibleTokens,
isCustomToken,
isHiddenChainIcon,
])
}, [selectedTokens, isHiddenChainIcon])
const SearchFieldProps = useMemo(
() => ({
placeholder: t.erc20_token_list_placeholder(),
Expand Down Expand Up @@ -360,10 +269,8 @@ export function FungibleTokenList<T extends NetworkPluginID>(props: FungibleToke
isAddressNotContract ? EMPTY_LIST
: searchedToken && isSameAddress(searchedToken.address, searchedTokenAddress) ?
// balance field work for case: user search someone token by contract and whitelist is empty.
[{ ...searchedToken, balance: tokenBalance, isCustomToken }]
: mode === TokenListMode.List ?
sortedFungibleTokensForList
: sortedFungibleTokensForManage
[{ ...searchedToken, balance: tokenBalance, isCustomToken: false }]
: sortedFungibleTokensForList
}
searchKey={SEARCH_KEYS}
disableSearch={!!props.disableSearch}
Expand All @@ -373,11 +280,6 @@ export function FungibleTokenList<T extends NetworkPluginID>(props: FungibleToke
FixedSizeListProps={FixedSizeListProps}
SearchFieldProps={SearchFieldProps}
/>
{mode === TokenListMode.List && enableManage ?
<Box className={classes.bar}>
<ManageTokenListBar onClick={() => setMode?.(TokenListMode.Manage)} />
</Box>
: null}
</Stack>
)
}
Expand Down
4 changes: 0 additions & 4 deletions packages/shared/src/UI/components/FungibleTokenList/type.ts

This file was deleted.

Loading

0 comments on commit 05f0a3a

Please sign in to comment.