Skip to content

Commit

Permalink
fix: [lw-12125] align assets search in assets picker
Browse files Browse the repository at this point in the history
  • Loading branch information
vetalcore committed Jan 17, 2025
1 parent 37ffbe2 commit 76866e3
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 42 deletions.
13 changes: 6 additions & 7 deletions apps/browser-extension-wallet/src/hooks/useNftSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,16 @@ interface NftSearchResultProps {
handleSearch: (items: NftItemProps[], searchValue: string) => void;
}

export const searchNft = (item: NftItemProps, searchValue: string, assetsInfo: AssetOrHandleInfoMap): boolean =>
item.name.toLowerCase().includes(searchValue.toLowerCase()) ||
item.assetId === searchValue ||
assetsInfo.get(Cardano.AssetId(item.assetId)).policyId === searchValue;

export const searchNfts = (
data: NftItemProps[],
searchValue: string,
assetsInfo: AssetOrHandleInfoMap
): NftItemProps[] =>
data.filter(
(item) =>
item.name.toLowerCase().includes(searchValue.toLowerCase()) ||
item.assetId === searchValue ||
assetsInfo.get(Cardano.AssetId(item.assetId)).policyId === searchValue
);
): NftItemProps[] => data.filter((nft) => searchNft(nft, searchValue, assetsInfo));

export const useNftSearch = (assetsInfo: AssetOrHandleInfoMap): NftSearchResultProps => {
const [isSearching, setIsSearching] = useState(false);
Expand Down
13 changes: 9 additions & 4 deletions apps/browser-extension-wallet/src/utils/get-token-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { CurrencyInfo } from '@src/types';
import { isNFT } from './is-nft';
import { getAssetImage } from './get-asset-image';
import { Asset } from '@cardano-sdk/core';
import { TokenInformation } from '@src/views/browser-view/features/assets/types';

const DISPLAY_FALLBACK = '-';
const NAME_TRUNCATE_LENGTH = 10;
Expand Down Expand Up @@ -132,7 +133,7 @@ const getDecimalsFromNftMetadata = (metadata?: Asset.NftMetadata): number | unde
*/
export const getTokenDisplayMetadata = (
info?: AssetOrHandleInfo
): Pick<NonNFTAsset, 'name' | 'description' | 'logo' | 'decimals'> => {
): Pick<NonNFTAsset, 'name' | 'description' | 'logo' | 'decimals'> & Partial<TokenInformation> => {
const name =
info?.tokenMetadata?.name ||
info?.nftMetadata?.name ||
Expand All @@ -145,7 +146,9 @@ export const getTokenDisplayMetadata = (
name,
description: ticker,
decimals,
logo: getTokenLogoUrl(info)
logo: getTokenLogoUrl(info),
policyId: info?.policyId,
fingerprint: info?.fingerprint
};
};

Expand All @@ -167,7 +170,7 @@ export const getNftDisplayMetadata = (info?: AssetOrHandleInfo): Pick<NFT, 'name
export const getTokenList = (params: GetTokenListParams): { tokenList: NonNFTAsset[]; nftList: NFT[] } => {
const { assetsInfo = new Map() as AssetOrHandleInfoMap, balance, prices, tokensSpent, fiatCurrency } = params;
const nfts: NFT[] = [];
const tokens: NonNFTAsset[] = [];
const tokens: (NonNFTAsset & Partial<TokenInformation>)[] = [];
if (isNil(balance) || balance.size === 0) {
return { tokenList: [], nftList: [] };
}
Expand Down Expand Up @@ -209,7 +212,9 @@ export const getTokenList = (params: GetTokenListParams): { tokenList: NonNFTAss
description: ftDisplayMetadata.description,
logo: ftDisplayMetadata.logo,
defaultLogo: getRandomIcon({ id: assetId.toString(), size: 30 }),
decimals: ftDisplayMetadata.decimals
decimals: ftDisplayMetadata.decimals,
policyId: ftDisplayMetadata.policyId,
fingerprint: ftDisplayMetadata.fingerprint
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@ import { Skeleton } from 'antd';
import { AssetTable, IRow } from '@lace/core';
import { CONTENT_LAYOUT_ID } from '@components/Layout';
import { LACE_APP_ID } from '@utils/constants';
import { IAssetDetails } from '@views/browser/features/assets/types';
import { IAssetDetails, TokenInformation } from '@views/browser/features/assets/types';
import { useTranslation } from 'react-i18next';
import { useWalletStore } from '@stores';
import styles from './AssetsPortfolio.module.scss';

const MIN_ASSETS_COUNT_FOR_SEARCH = 10;

const searchTokens = (data: IAssetDetails[], searchValue: string) => {
const fields = ['name', 'policyId', 'fingerprint', 'ticker'] as const;
const fields = ['name', 'policyId', 'fingerprint', 'ticker'] as const;
export const searchToken = (item: Partial<IRow> & Partial<TokenInformation>, searchValue: string): boolean =>
fields.some((field) => field in item && item[field]?.toLowerCase().includes(searchValue));

export const searchTokens = (data: IAssetDetails[], searchValue: string): IAssetDetails[] => {
const lowerSearchValue = searchValue.toLowerCase();

return data.filter((item) =>
fields.some((field) => field in item && item[field]?.toLowerCase().includes(lowerSearchValue))
);
return data.filter((item) => searchToken(item, lowerSearchValue));
};

interface AssetPortfolioContentProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Wallet } from '@lace/cardano';
import { AssetTableProps } from '@lace/core';

type Unpacked<T> = T extends (infer U)[] ? U : T;
interface TokenInformation {
export interface TokenInformation {
policyId: string;
fingerprint: string;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/* eslint-disable max-params */
import React, { useEffect, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ASSET_COMPONENTS, AssetSelectorOverlay } from '@lace/core';
import { ASSET_COMPONENTS, AssetSelectorOverlay, NftItemProps } from '@lace/core';
import { useWalletStore } from '@stores';
import { useObservable } from '@lace/common';
import styles from './CreateFolderDrawer.module.scss';
import { formatNftsList } from '../utils';
import { useCurrencyStore } from '@providers';
import { useAssetInfo } from '@hooks';
import { searchNft } from '@hooks/useNftSearch';

const nftsPerRow = {
popupView: 2,
Expand Down Expand Up @@ -71,10 +72,16 @@ export const AssetPicker = ({
onSetIsFormValid(selectedNFTs.length > 0);
}, [selectedNFTs, onSetIsFormValid]);

const handleSearch = useCallback(
(item: NftItemProps, searchValue: string) => searchNft(item, searchValue, assets),
[assets]
);

return (
<div className={styles.assetsSelectorWrapper} data-testid="asset-selector-wrapper">
<AssetSelectorOverlay
nfts={nftList}
searchNfts={handleSearch}
nftListConfig={{ rows: isPopupView ? nftsPerRow.popupView : nftsPerRow.browserView }}
onClick={setSelectedTokens}
addToMultipleSelectionList={setSelectedTokens}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,5 @@ export const formatNftsList = (

const { nftList } = getTokenList({ assetsInfo, balance: balance.assets, environmentName, fiatCurrency });

return nftList.map((nft) => {
const { assetId, ...rest } = nft;
return { ...rest, id: assetId.toString() };
});
return nftList.map((nft) => ({ ...nft, id: nft.assetId.toString() }));
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable max-params */
import React, { useEffect, useState } from 'react';
import { AssetSelectorOverlay, AssetSelectorOverlayProps } from '@lace/core';
import React, { useCallback, useEffect, useState } from 'react';
import { AssetSelectorOverlay, AssetSelectorOverlayProps, NftItemProps } from '@lace/core';
import { Wallet } from '@lace/cardano';
import CardanoLogo from '../../../../../assets/icons/browser-view/cardano-logo.svg';
import { useFetchCoinPrice, PriceResult, AssetOrHandleInfoMap, useAssetInfo } from '@hooks';
Expand Down Expand Up @@ -28,6 +28,8 @@ import styles from './AssetPicker.module.scss';
import { useCurrencyStore } from '@providers';
import { isNFT } from '@src/utils/is-nft';
import { useObservable } from '@lace/common';
import { searchToken } from '../../assets/components/AssetsPortfolio/AssetPortfolioContent';
import { searchNft } from '@hooks/useNftSearch';

const formatAssetPickerLists = (
assetsInfo: AssetOrHandleInfoMap = new Map(),
Expand Down Expand Up @@ -62,10 +64,7 @@ const formatAssetPickerLists = (
return { ...rest, id: assetId.toString() };
});

const nfts = nftList.map((nft) => {
const { assetId, ...rest } = nft;
return { ...rest, id: assetId.toString() };
});
const nfts = nftList.map((nft) => ({ ...nft, id: nft.assetId.toString() }));

if (addCardanoAsAnAsset) {
tokens.push({
Expand Down Expand Up @@ -210,9 +209,16 @@ export const AssetPicker = ({ isPopupView }: AssetPickerProps): React.ReactEleme
setSelectedTokenList(id, isNFT(assetInfo));
};

const handleSearchNfts = useCallback(
(item: NftItemProps, searchValue: string) => searchNft(item, searchValue, assets),
[assets]
);

return (
<>
<AssetSelectorOverlay
searchNfts={handleSearchNfts}
searchTokens={searchToken}
className={styles.selectorOverlay}
nfts={nftList}
tokens={tokenList}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ export interface AssetSelectorOverlayProps {
removeTokenFromList: (id: string) => void;
className?: string;
groups?: Array<ASSET_COMPONENTS.TOKENS | ASSET_COMPONENTS.NFTS>;
searchNfts: (item: NftItemProps, searchValue: string) => boolean;
searchTokens?: (item: DropdownList, searchValue: string) => boolean;
}

export const AssetSelectorOverlay = ({
Expand All @@ -139,7 +141,9 @@ export const AssetSelectorOverlay = ({
removeTokenFromList,
doesWalletHaveTokens,
className,
groups = [ASSET_COMPONENTS.TOKENS, ASSET_COMPONENTS.NFTS]
groups = [ASSET_COMPONENTS.TOKENS, ASSET_COMPONENTS.NFTS],
searchNfts,
searchTokens
}: AssetSelectorOverlayProps): React.ReactElement => {
const { t } = useTranslation();
const [value, setValue] = useState<string>();
Expand All @@ -158,21 +162,15 @@ export const AssetSelectorOverlay = ({

const filterAssets = useCallback(async () => {
const filter = () => {
const filteredNfts = nfts?.filter((item) => !value || stringIncludesValue(item.name, value));
const filteredTokens = tokens?.filter(
(item) =>
!value ||
item.id === value ||
stringIncludesValue(item.name, value) ||
stringIncludesValue(item.description, value)
);
const filteredNfts = nfts?.filter((item) => !value || searchNfts(item, value));
const filteredTokens = tokens?.filter((item) => !value || searchTokens?.(item, value));
return Promise.resolve({ filteredNfts, filteredTokens });
};
setIsSearching(true);
const result = await filter();
setSearchResult({ nfts: result.filteredNfts ?? [], tokens: result.filteredTokens ?? [] });
setIsSearching(false);
}, [nfts, tokens, value]);
}, [nfts, searchNfts, searchTokens, tokens, value]);

useEffect(() => {
filterAssets();
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/ui/components/Nft/NftItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ const ContextMenu = ({ setClicked, children, onRender, points }: ContextMenuProp
);
};

export interface NftItemProps {
export type NftItemProps = {
id?: string;
assetId?: string;
image?: string;
name: string;
Expand All @@ -53,7 +54,7 @@ export interface NftItemProps {
selected?: boolean;
type?: NftsItemsTypes.NFT;
contextMenu?: React.ReactElement;
}
};

export const NftItem = ({ image, name, onClick, amount, selected, contextMenu }: NftItemProps): React.ReactElement => {
const bodyRef = useRef<{ clientWidth?: number }>({ clientWidth: 0 });
Expand Down

0 comments on commit 76866e3

Please sign in to comment.