From 41151a4703a395c0afe715bde601b3dfedb84f2e Mon Sep 17 00:00:00 2001 From: Sergey Zhuravlev Date: Thu, 28 Nov 2024 14:54:35 +0300 Subject: [PATCH] fix: small ux fixes on assets page (#2751) --- .../asset/ui/AssetDetails/AssetDetails.tsx | 5 ++- .../asset/ui/AssetLinks/AssetLinks.tsx | 5 ++- .../entities/balance/lib/constants.ts | 2 +- .../entities/chain/ui/ChainIcon/ChainIcon.tsx | 6 ++- .../entities/price/ui/AssetFiatBalance.tsx | 5 ++- src/renderer/entities/price/ui/TokenPrice.tsx | 5 ++- .../ui/AssetCard/AssetCard.tsx | 13 ++++--- .../AssetsChainView/ui/AssetsChainView.tsx | 7 +++- .../ui/NetworkAssets/NetworkAssets.tsx | 15 +++++--- .../ui/AssetsPortfolioView.tsx | 9 +++-- .../AssetsPortfolioView/ui/NetworkCard.tsx | 5 ++- .../AssetsPortfolioView/ui/TokenBalance.tsx | 5 ++- .../ui/TokenBalanceList.tsx | 5 ++- .../assets/AssetsSearch/ui/AssetsSearch.tsx | 2 +- .../AssetsSettings/ui/AssetsSettings.tsx | 38 +++++++++---------- .../ContactFilter/ui/ContactFilter.tsx | 2 +- .../features/navigation/ui/Navigation.tsx | 5 ++- .../ui-entities/AssetIcon/AssetIcon.tsx | 6 ++- src/renderer/shared/ui/Inputs/Input/Input.tsx | 2 +- .../ui/Inputs/SearchInput/SearchInput.tsx | 6 ++- 20 files changed, 87 insertions(+), 61 deletions(-) diff --git a/src/renderer/entities/asset/ui/AssetDetails/AssetDetails.tsx b/src/renderer/entities/asset/ui/AssetDetails/AssetDetails.tsx index e4456e4876..4e1d12b5c7 100644 --- a/src/renderer/entities/asset/ui/AssetDetails/AssetDetails.tsx +++ b/src/renderer/entities/asset/ui/AssetDetails/AssetDetails.tsx @@ -1,5 +1,6 @@ import { type BN } from '@polkadot/util'; import { BigNumber } from 'bignumber.js'; +import { memo } from 'react'; import { type Asset } from '@/shared/core'; import { HelpText, Shimmering } from '@/shared/ui'; @@ -12,7 +13,7 @@ type Props = { value?: BN; }; -export const AssetDetails = ({ asset, value, label }: Props) => { +export const AssetDetails = memo(({ asset, value, label }: Props) => { return (
@@ -28,4 +29,4 @@ export const AssetDetails = ({ asset, value, label }: Props) => {
); -}; +}); diff --git a/src/renderer/entities/asset/ui/AssetLinks/AssetLinks.tsx b/src/renderer/entities/asset/ui/AssetLinks/AssetLinks.tsx index 4b24e75b41..0d70c910e7 100644 --- a/src/renderer/entities/asset/ui/AssetLinks/AssetLinks.tsx +++ b/src/renderer/entities/asset/ui/AssetLinks/AssetLinks.tsx @@ -1,4 +1,5 @@ import { useUnit } from 'effector-react'; +import { memo } from 'react'; import { Link } from 'react-router-dom'; import { type ChainId } from '@/shared/core'; @@ -11,7 +12,7 @@ type Props = { chainId: ChainId; }; -export const AssetLinks = ({ assetId, chainId }: Props) => { +export const AssetLinks = memo(({ assetId, chainId }: Props) => { const activeWallet = useUnit(walletModel.$activeWallet); return ( @@ -34,4 +35,4 @@ export const AssetLinks = ({ assetId, chainId }: Props) => { ); -}; +}); diff --git a/src/renderer/entities/balance/lib/constants.ts b/src/renderer/entities/balance/lib/constants.ts index c8047affe7..b94369fdfb 100644 --- a/src/renderer/entities/balance/lib/constants.ts +++ b/src/renderer/entities/balance/lib/constants.ts @@ -1,2 +1,2 @@ export const SAVE_TIMEOUT = 5000; -export const BUFFER_DELAY = 500; +export const BUFFER_DELAY = 1000; diff --git a/src/renderer/entities/chain/ui/ChainIcon/ChainIcon.tsx b/src/renderer/entities/chain/ui/ChainIcon/ChainIcon.tsx index d7b9db4aa7..b664fc8873 100644 --- a/src/renderer/entities/chain/ui/ChainIcon/ChainIcon.tsx +++ b/src/renderer/entities/chain/ui/ChainIcon/ChainIcon.tsx @@ -1,3 +1,5 @@ +import { memo } from 'react'; + import { useToggle } from '@/shared/lib/hooks'; import { cnTw } from '@/shared/lib/utils'; import { Shimmering } from '@/shared/ui'; @@ -9,7 +11,7 @@ type Props = { className?: string; }; -export const ChainIcon = ({ src, name, size = 16, className }: Props) => { +export const ChainIcon = memo(({ src, name, size = 16, className }: Props) => { const [isImgLoaded, toggleImgLoaded] = useToggle(); return ( @@ -25,4 +27,4 @@ export const ChainIcon = ({ src, name, size = 16, className }: Props) => { /> ); -}; +}); diff --git a/src/renderer/entities/price/ui/AssetFiatBalance.tsx b/src/renderer/entities/price/ui/AssetFiatBalance.tsx index b57deb19a6..dbbf466ecf 100644 --- a/src/renderer/entities/price/ui/AssetFiatBalance.tsx +++ b/src/renderer/entities/price/ui/AssetFiatBalance.tsx @@ -1,5 +1,6 @@ import { default as BigNumber } from 'bignumber.js'; import { useUnit } from 'effector-react'; +import { memo } from 'react'; import { type Asset, type AssetByChains } from '@/shared/core'; import { useI18n } from '@/shared/i18n'; @@ -16,7 +17,7 @@ type Props = { className?: string; }; -export const AssetFiatBalance = ({ asset, amount, className }: Props) => { +export const AssetFiatBalance = memo(({ asset, amount, className }: Props) => { const { t } = useI18n(); const currency = useUnit(currencyModel.$activeCurrency); @@ -50,4 +51,4 @@ export const AssetFiatBalance = ({ asset, amount, className }: Props) => { }); return ; -}; +}); diff --git a/src/renderer/entities/price/ui/TokenPrice.tsx b/src/renderer/entities/price/ui/TokenPrice.tsx index d81e5908d1..4e63adc698 100644 --- a/src/renderer/entities/price/ui/TokenPrice.tsx +++ b/src/renderer/entities/price/ui/TokenPrice.tsx @@ -1,4 +1,5 @@ import { useStoreMap, useUnit } from 'effector-react'; +import { memo } from 'react'; import { useI18n } from '@/shared/i18n'; import { ZERO_BALANCE, cnTw, formatFiatBalance } from '@/shared/lib/utils'; @@ -14,7 +15,7 @@ type Props = { wrapperClassName?: string; }; -export const TokenPrice = ({ assetId, className, wrapperClassName }: Props) => { +export const TokenPrice = memo(({ assetId, className, wrapperClassName }: Props) => { const { t } = useI18n(); const currency = useUnit(currencyModel.$activeCurrency); const price = useStoreMap(priceProviderModel.$assetsPrices, (prices) => { @@ -58,4 +59,4 @@ export const TokenPrice = ({ assetId, className, wrapperClassName }: Props) => { {Boolean(price.change) && {changeToShow}%} ); -}; +}); diff --git a/src/renderer/features/assets/AssetsChainView/ui/AssetCard/AssetCard.tsx b/src/renderer/features/assets/AssetsChainView/ui/AssetCard/AssetCard.tsx index 58fe294f02..13f7c7276b 100644 --- a/src/renderer/features/assets/AssetsChainView/ui/AssetCard/AssetCard.tsx +++ b/src/renderer/features/assets/AssetsChainView/ui/AssetCard/AssetCard.tsx @@ -1,5 +1,5 @@ import { useUnit } from 'effector-react'; -import { type KeyboardEvent } from 'react'; +import { type KeyboardEvent, memo, useMemo } from 'react'; import { type Asset, type Balance, type ChainId } from '@/shared/core'; import { useI18n } from '@/shared/i18n'; @@ -15,7 +15,7 @@ type Props = { balance?: Balance; }; -export const AssetCard = ({ chainId, asset, balance }: Props) => { +export const AssetCard = memo(({ chainId, asset, balance }: Props) => { const { t } = useI18n(); const fiatFlag = useUnit(priceProviderModel.$fiatFlag); @@ -30,7 +30,8 @@ export const AssetCard = ({ chainId, asset, balance }: Props) => { } }; - const transferableBalance = balance ? transferableAmountBN(balance) : undefined; + const transferableBalance = useMemo(() => (balance ? transferableAmountBN(balance) : undefined), [balance]); + const totalBalance = useMemo(() => totalAmount(balance), [balance]); // TODO: move
  • in parent beneath
      return ( @@ -56,8 +57,8 @@ export const AssetCard = ({ chainId, asset, balance }: Props) => {
      {balance?.free ? ( <> - - + + ) : (
      @@ -78,4 +79,4 @@ export const AssetCard = ({ chainId, asset, balance }: Props) => { )} ); -}; +}); diff --git a/src/renderer/features/assets/AssetsChainView/ui/AssetsChainView.tsx b/src/renderer/features/assets/AssetsChainView/ui/AssetsChainView.tsx index 78ab726368..e39a6c534b 100644 --- a/src/renderer/features/assets/AssetsChainView/ui/AssetsChainView.tsx +++ b/src/renderer/features/assets/AssetsChainView/ui/AssetsChainView.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'; import { chainsService } from '@/shared/api/network'; import { type Account, type Chain } from '@/shared/core'; +import { useDeferredList } from '@/shared/lib/hooks'; import { isStringsMatchQuery, nullable } from '@/shared/lib/utils'; import { AssetsListView, EmptyAssetsState } from '@/entities/asset'; import { balanceModel } from '@/entities/balance'; @@ -30,6 +31,8 @@ export const AssetsChainView = ({ query, activeShards, hideZeroBalances, assetsV const [sortedChains, setSortedChains] = useState([]); + const { list } = useDeferredList({ list: sortedChains }); + useEffect(() => { if (!activeWallet || assetsView !== AssetsListView.CHAIN_CENTRIC || !activeShards.length) return; @@ -75,8 +78,8 @@ export const AssetsChainView = ({ query, activeShards, hideZeroBalances, assetsV return (
      -
        - {sortedChains.map((chain) => ( +
          + {list.map((chain) => ( { +export const NetworkAssets = memo(({ chain, accounts, query, hideZeroBalances, searchSymbolOnly }: Props) => { const { t } = useI18n(); const assetsPrices = useUnit(priceProviderModel.$assetsPrices); @@ -47,9 +47,12 @@ export const NetworkAssets = ({ chain, accounts, query, hideZeroBalances, search }, []); }, [chain.chainId, selectedAccountIds]); - useEffect(() => { - const chainBalances = balances.filter((b) => b.chainId === chain.chainId && accountIds.includes(b.accountId)); + const chainBalances = useMemo( + () => balances.filter((b) => b.chainId === chain.chainId && accountIds.includes(b.accountId)), + [balances, chain, accountIds], + ); + useEffect(() => { const newBalancesObject: Record = {}; const groupedBalances = Object.values(groupBy(chainBalances, 'assetId')); @@ -64,7 +67,7 @@ export const NetworkAssets = ({ chain, accounts, query, hideZeroBalances, search } setBalancesObject(newBalancesObject); - }, [balances, accountIds.join('')]); + }, [chainBalances, accountIds.join('')]); useEffect(() => { const filteredAssets = chain.assets.filter((asset) => { @@ -135,4 +138,4 @@ export const NetworkAssets = ({ chain, accounts, query, hideZeroBalances, search ); -}; +}); diff --git a/src/renderer/features/assets/AssetsPortfolioView/ui/AssetsPortfolioView.tsx b/src/renderer/features/assets/AssetsPortfolioView/ui/AssetsPortfolioView.tsx index c806e59b58..9c1c4ccefe 100644 --- a/src/renderer/features/assets/AssetsPortfolioView/ui/AssetsPortfolioView.tsx +++ b/src/renderer/features/assets/AssetsPortfolioView/ui/AssetsPortfolioView.tsx @@ -2,6 +2,7 @@ import { useUnit } from 'effector-react'; import { type Wallet, WalletType } from '@/shared/core'; import { useI18n } from '@/shared/i18n'; +import { useDeferredList } from '@/shared/lib/hooks'; import { FootnoteText } from '@/shared/ui'; import { AssetsListView, EmptyAssetsState } from '@/entities/asset'; import { priceProviderModel } from '@/entities/price'; @@ -32,6 +33,8 @@ export const AssetsPortfolioView = () => { const fiatFlag = useUnit(priceProviderModel.$fiatFlag); const wallet = useUnit(walletModel.$activeWallet); + const { list } = useDeferredList({ list: sortedTokens }); + if (activeView !== AssetsListView.TOKEN_CENTRIC || accounts.length === 0) { return null; } @@ -39,7 +42,7 @@ export const AssetsPortfolioView = () => { const colStyle = getColStyle(wallet); return ( -
          +
          {t('balances.token')} @@ -50,8 +53,8 @@ export const AssetsPortfolioView = () => {
          -
            - {sortedTokens.map((asset) => ( +
              + {list.map((asset) => (
            • {asset.chains.length === 1 ? : }
            • diff --git a/src/renderer/features/assets/AssetsPortfolioView/ui/NetworkCard.tsx b/src/renderer/features/assets/AssetsPortfolioView/ui/NetworkCard.tsx index 78bfdb06b6..8fb557342a 100644 --- a/src/renderer/features/assets/AssetsPortfolioView/ui/NetworkCard.tsx +++ b/src/renderer/features/assets/AssetsPortfolioView/ui/NetworkCard.tsx @@ -1,4 +1,5 @@ import { useUnit } from 'effector-react'; +import { memo } from 'react'; import { type AssetByChains } from '@/shared/core'; import { BodyText, FootnoteText } from '@/shared/ui'; @@ -14,7 +15,7 @@ type Props = { asset: AssetByChains; }; -export const NetworkCard = ({ chain, asset }: Props) => { +export const NetworkCard = memo(({ chain, asset }: Props) => { const chains = useUnit(networkModel.$chains); return ( @@ -34,4 +35,4 @@ export const NetworkCard = ({ chain, asset }: Props) => {
          ); -}; +}); diff --git a/src/renderer/features/assets/AssetsPortfolioView/ui/TokenBalance.tsx b/src/renderer/features/assets/AssetsPortfolioView/ui/TokenBalance.tsx index ba12cb0e5b..3083cef0c3 100644 --- a/src/renderer/features/assets/AssetsPortfolioView/ui/TokenBalance.tsx +++ b/src/renderer/features/assets/AssetsPortfolioView/ui/TokenBalance.tsx @@ -1,4 +1,5 @@ import { useUnit } from 'effector-react'; +import { memo } from 'react'; import { type AssetByChains } from '@/shared/core'; import { useI18n } from '@/shared/i18n'; @@ -14,7 +15,7 @@ type Props = { asset: AssetByChains; }; -export const TokenBalance = ({ asset }: Props) => { +export const TokenBalance = memo(({ asset }: Props) => { const { t } = useI18n(); const chain = asset.chains[0]; @@ -53,4 +54,4 @@ export const TokenBalance = ({ asset }: Props) => { ); -}; +}); diff --git a/src/renderer/features/assets/AssetsPortfolioView/ui/TokenBalanceList.tsx b/src/renderer/features/assets/AssetsPortfolioView/ui/TokenBalanceList.tsx index 7599bae2c4..b722a9fb79 100644 --- a/src/renderer/features/assets/AssetsPortfolioView/ui/TokenBalanceList.tsx +++ b/src/renderer/features/assets/AssetsPortfolioView/ui/TokenBalanceList.tsx @@ -1,4 +1,5 @@ import { useUnit } from 'effector-react'; +import { memo } from 'react'; import { type AssetByChains } from '@/shared/core'; import { useI18n } from '@/shared/i18n'; @@ -20,7 +21,7 @@ type Props = { asset: AssetByChains; }; -export const TokenBalanceList = ({ asset }: Props) => { +export const TokenBalanceList = memo(({ asset }: Props) => { const { t } = useI18n(); const activeWallet = useUnit(walletModel.$activeWallet); @@ -112,4 +113,4 @@ export const TokenBalanceList = ({ asset }: Props) => { ); -}; +}); diff --git a/src/renderer/features/assets/AssetsSearch/ui/AssetsSearch.tsx b/src/renderer/features/assets/AssetsSearch/ui/AssetsSearch.tsx index c7883742ac..d4fda811ca 100644 --- a/src/renderer/features/assets/AssetsSearch/ui/AssetsSearch.tsx +++ b/src/renderer/features/assets/AssetsSearch/ui/AssetsSearch.tsx @@ -13,7 +13,7 @@ export const AssetsSearch = () => { ); diff --git a/src/renderer/features/assets/AssetsSettings/ui/AssetsSettings.tsx b/src/renderer/features/assets/AssetsSettings/ui/AssetsSettings.tsx index 7bde47ecd1..47b490858f 100644 --- a/src/renderer/features/assets/AssetsSettings/ui/AssetsSettings.tsx +++ b/src/renderer/features/assets/AssetsSettings/ui/AssetsSettings.tsx @@ -1,12 +1,14 @@ import { useUnit } from 'effector-react'; +import { memo } from 'react'; import { TEST_IDS } from '@/shared/constants'; import { useI18n } from '@/shared/i18n'; -import { FootnoteText, IconButton, MenuPopover, Select, Switch } from '@/shared/ui'; +import { FootnoteText, IconButton, Select, Switch } from '@/shared/ui'; +import { Box, Popover } from '@/shared/ui-kit'; import { AssetsListView } from '@/entities/asset'; import { assetsSettingsModel } from '../model/assets-settings-modal'; -export const AssetsSettings = () => { +export const AssetsSettings = memo(() => { const { t } = useI18n(); const assetsView = useUnit(assetsSettingsModel.$assetsView); @@ -26,14 +28,17 @@ export const AssetsSettings = () => { ]; return ( - + + +
          + + {hideZeroBalances && ( + + )} +
          +
          + + { options={options} onChange={({ value }) => assetsSettingsModel.events.assetsViewChanged(value)} /> - - } - > -
          - - {hideZeroBalances && } -
          -
          + + + ); -}; +}); diff --git a/src/renderer/features/contacts/ContactFilter/ui/ContactFilter.tsx b/src/renderer/features/contacts/ContactFilter/ui/ContactFilter.tsx index a82ae8f556..a3a413850e 100644 --- a/src/renderer/features/contacts/ContactFilter/ui/ContactFilter.tsx +++ b/src/renderer/features/contacts/ContactFilter/ui/ContactFilter.tsx @@ -13,7 +13,7 @@ export const ContactFilter = () => { return ( diff --git a/src/renderer/features/navigation/ui/Navigation.tsx b/src/renderer/features/navigation/ui/Navigation.tsx index f4445b7d4c..6a58d45007 100644 --- a/src/renderer/features/navigation/ui/Navigation.tsx +++ b/src/renderer/features/navigation/ui/Navigation.tsx @@ -1,4 +1,5 @@ import { useUnit } from 'effector-react'; +import { memo } from 'react'; import { MultisigTxInitStatus } from '@/shared/core'; import { useI18n } from '@/shared/i18n'; @@ -12,7 +13,7 @@ import { basketUtils } from '@/features/operations/OperationsConfirm'; import { NavItem, type Props as NavItemProps } from './NavItem'; -export const Navigation = () => { +export const Navigation = memo(() => { const { t } = useI18n(); const chains = useUnit(networkModel.$chains); @@ -73,4 +74,4 @@ export const Navigation = () => {
        ); -}; +}); diff --git a/src/renderer/shared/ui-entities/AssetIcon/AssetIcon.tsx b/src/renderer/shared/ui-entities/AssetIcon/AssetIcon.tsx index 1370c2e1f5..099f199ae4 100644 --- a/src/renderer/shared/ui-entities/AssetIcon/AssetIcon.tsx +++ b/src/renderer/shared/ui-entities/AssetIcon/AssetIcon.tsx @@ -1,3 +1,5 @@ +import { memo } from 'react'; + import { type Asset } from '@/shared/core'; import { useToggle } from '@/shared/lib/hooks'; import { cnTw } from '@/shared/lib/utils'; @@ -9,7 +11,7 @@ type Props = { style?: 'monochrome' | 'colored'; }; -export const AssetIcon = ({ asset, style, size = 36 }: Props) => { +export const AssetIcon = memo(({ asset, style, size = 36 }: Props) => { const { iconStyle } = useTheme(); const [isImgLoaded, toggleImgLoaded] = useToggle(); const computedStyle = style || iconStyle; @@ -33,4 +35,4 @@ export const AssetIcon = ({ asset, style, size = 36 }: Props) => { />
      ); -}; +}); diff --git a/src/renderer/shared/ui/Inputs/Input/Input.tsx b/src/renderer/shared/ui/Inputs/Input/Input.tsx index f5bb92e40b..40b47d2866 100644 --- a/src/renderer/shared/ui/Inputs/Input/Input.tsx +++ b/src/renderer/shared/ui/Inputs/Input/Input.tsx @@ -46,7 +46,7 @@ export const Input = forwardRef( const inputElement = (
      (({ className, wra ref={ref} className={className} wrapperClass={cnTw('hover:shadow-none', wrapperClass)} - prefixElement={} + prefixElement={ + + + + } suffixElement={