Skip to content

Commit

Permalink
fix: handle invalid image paths (#634)
Browse files Browse the repository at this point in the history
  • Loading branch information
jinoosss authored Nov 11, 2024
1 parent a9c7f11 commit fe604cf
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo } from 'react';
import React, { useMemo, useState } from 'react';

import IconEmptyImage from '@assets/icon-empty-image.svg';
import Toggle from '@components/atoms/toggle';
Expand Down Expand Up @@ -34,6 +34,7 @@ const ManageTokenListItem: React.FC<ManageTokenListItemProps> = ({
onToggleActiveItem,
}) => {
const theme = useTheme();
const [hasLogoError, setHasLogoError] = useState(false);
const isTokenInfo = isManageTokenInfo(token);
const tokenUriResponse =
!isTokenInfo && token.isTokenUri && queryGRC721TokenUri
Expand All @@ -45,6 +46,10 @@ const ManageTokenListItem: React.FC<ManageTokenListItemProps> = ({
: null;

const grc721CollectionImage = useMemo(() => {
if (!hasLogoError) {
return null;
}

if (!tokenUriResponse) {
return null;
}
Expand Down Expand Up @@ -77,11 +82,15 @@ const ManageTokenListItem: React.FC<ManageTokenListItemProps> = ({
return `${balanceBN.toFormat()} Item`;
}, [token]);

const handleLogoError = (): void => {
setHasLogoError(true);
};

if (isTokenInfo) {
return (
<ManageTokenListItemWrapper>
<div className={'logo-wrapper'}>
<img className='logo' src={token.logo} alt='token img' />
<img className='logo' src={token.logo} alt='token img' onError={handleLogoError} />
</div>

<div className='name-wrapper'>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';

import IconEmptyImage from '@assets/icon-empty-image.svg';
import { Loading } from '@components/atoms';
Expand All @@ -11,6 +11,17 @@ export interface NFTCardImageProps {
}

const NFTCardImage: React.FC<NFTCardImageProps> = ({ isFetched, image, hasBadge = false }) => {
const [hasError, setHasError] = useState(false);
const [loaded, setLoaded] = useState(false);

const handleLoad = (): void => {
setLoaded(true);
};

const handleError = (): void => {
setHasError(true);
};

if (!isFetched) {
return (
<NFTCardImageSkeletonBox>
Expand All @@ -19,7 +30,7 @@ const NFTCardImage: React.FC<NFTCardImageProps> = ({ isFetched, image, hasBadge
);
}

if (!image) {
if (!image || !loaded || hasError) {
return (
<NFTCardImageWrapper className='empty'>
<img className='empty-image' src={IconEmptyImage} alt='empty image' />
Expand All @@ -29,7 +40,13 @@ const NFTCardImage: React.FC<NFTCardImageProps> = ({ isFetched, image, hasBadge

return (
<NFTCardImageWrapper>
<img className='nft-image' src={image} />
<img
className='nft-image'
src={image}
onLoad={handleLoad}
onError={handleError}
alt='nft image'
/>
</NFTCardImageWrapper>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import FailedIcon from '@assets/failed.svg';
import SuccessIcon from '@assets/success.svg';
import { TokenBalance } from '@components/molecules';
import { UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
import React, { useCallback, useMemo } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import { TransactionHistoryListItemWrapper } from './transaction-history-list-item.styles';

export interface TransactionHistoryListItemProps {
Expand Down Expand Up @@ -43,31 +43,53 @@ const TransactionHistoryListItem: React.FC<TransactionHistoryListItemProps> = (a
queryGRC721TokenUri,
onClickItem,
} = args;
const [hasLogoError, setHasLogoError] = useState(false);
const [isLoadedLogo, setIsLoadedLogo] = useState(false);

const tokenUriQuery =
type === 'TRANSFER_GRC721' && queryGRC721TokenUri !== undefined
? queryGRC721TokenUri(logo || '', '0')
: null;

const logoImage = useMemo(() => {
if (hasLogoError) {
return `${UnknownTokenIcon}`;
}

if (type === 'TRANSFER_GRC721' && tokenUriQuery) {
if (!isLoadedLogo) {
return `${UnknownTokenIcon}`;
}

return tokenUriQuery?.data || `${UnknownTokenIcon}`;
}

if (type === 'ADD_PACKAGE') {
return `${AddPackageIcon}`;
}

if (type === 'CONTRACT_CALL') {
return `${ContractIcon}`;
}

if (type === 'MULTI_CONTRACT_CALL') {
return `${ContractIcon}`;
}

if (!logo) {
return `${UnknownTokenIcon}`;
}

return `${logo}`;
}, [type, logo, tokenUriQuery]);
}, [isLoadedLogo, hasLogoError, type, logo, tokenUriQuery]);

const handleLogoError = (): void => {
setHasLogoError(true);
};

const handleLoadLogo = (): void => {
setIsLoadedLogo(true);
};

const getValueTypeClassName = useCallback(() => {
if (valueType === 'ACTIVE') {
Expand All @@ -82,7 +104,13 @@ const TransactionHistoryListItem: React.FC<TransactionHistoryListItemProps> = (a
return (
<TransactionHistoryListItemWrapper onClick={(): void => onClickItem(hash)}>
<div className='logo-wrapper'>
<img className='logo' src={logoImage} alt='logo image' />
<img
className='logo'
src={logoImage}
alt='logo image'
onLoad={handleLoadLogo}
onError={handleLogoError}
/>
<img
className='badge'
src={status === 'SUCCESS' ? SuccessIcon : FailedIcon}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import ManageTokenSearch from '@components/pages/manage-token/manage-token';
import useAppNavigate from '@hooks/use-app-navigate';
import { useCurrentAccount } from '@hooks/use-current-account';
import { useTokenBalance } from '@hooks/use-token-balance';
import { useTokenMetainfo } from '@hooks/use-token-metainfo';
import { ManageTokenInfo, RoutePath } from '@types';

const ManageTokenSearchContainer: React.FC = () => {
const { navigate, goBack } = useAppNavigate();
const [searchKeyword, setSearchKeyword] = useState('');
const [isClose, setIsClose] = useState(false);
const { currentAccount } = useCurrentAccount();
const { tokenLogoMap } = useTokenMetainfo();
const { currentBalances, toggleDisplayOption } = useTokenBalance();

useEffect(() => {
Expand All @@ -39,11 +41,11 @@ const ManageTokenSearchContainer: React.FC = () => {
value: BigNumber(metainfo.amount.value).toFormat(),
denom: metainfo.amount.denom,
},
logo: metainfo.image || `${UnknownTokenIcon}`,
logo: tokenLogoMap[metainfo.tokenId] || `${UnknownTokenIcon}`,
};
});
return filteredTokens;
}, [searchKeyword, currentBalances]);
}, [searchKeyword, currentBalances, tokenLogoMap]);

const moveTokenAddedPage = useCallback(() => {
navigate(RoutePath.ManageTokenAdded);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback } from 'react';
import { useMemo, useState } from 'react';
import styled from 'styled-components';

import AddPackageIcon from '@assets/addpkg.svg';
Expand All @@ -24,35 +24,55 @@ interface DLProps {
}

export const TransactionDetail = (): JSX.Element => {
const [hasLogoError, setHasLogoError] = useState(false);
const [isLoadedLogo, setIsLoadedLogo] = useState(false);

const { openLink } = useLink();
const { convertDenom } = useTokenMetainfo();
const { currentNetwork, scannerParameters } = useNetwork();
const { goBack, params } = useAppNavigate<RoutePath.TransactionDetail>();

const transactionItem = params.transactionInfo;
const tokenUriQuery =
transactionItem?.type === 'TRANSFER_GRC721'
? useGetGRC721TokenUri(transactionItem.logo, '0')
: null;

const getLogoImage = useCallback(() => {
if (transactionItem?.type === 'TRANSFER_GRC721') {
const logoImage = useMemo(() => {
if (transactionItem?.type === 'TRANSFER_GRC721' && tokenUriQuery) {
if (!isLoadedLogo || hasLogoError) {
return `${UnknownTokenIcon}`;
}

return tokenUriQuery?.data || `${UnknownTokenIcon}`;
}

if (transactionItem?.type === 'ADD_PACKAGE') {
return `${AddPackageIcon}`;
}

if (transactionItem?.type === 'CONTRACT_CALL') {
return `${ContractIcon}`;
}

if (transactionItem?.type === 'MULTI_CONTRACT_CALL') {
return `${ContractIcon}`;
}

if (!transactionItem?.logo) {
return `${UnknownTokenIcon}`;
}

return `${transactionItem?.logo}`;
}, [transactionItem]);
}, [isLoadedLogo, hasLogoError, transactionItem?.type, transactionItem?.logo, tokenUriQuery]);

const handleLoadLogo = (): void => {
setIsLoadedLogo(true);
};

const handleLogoError = (): void => {
setHasLogoError(true);
};

const handleLinkClick = (hash: string): void => {
const scannerUrl = currentNetwork.linkUrl || SCANNER_URL;
Expand All @@ -70,7 +90,13 @@ export const TransactionDetail = (): JSX.Element => {
alt='status icon'
/>
<TokenBox color={getStatusStyle(transactionItem.status).color}>
<img className='tx-symbol' src={getLogoImage()} alt='logo image' />
<img
className='tx-symbol'
src={logoImage}
onLoad={handleLoadLogo}
onError={handleLogoError}
alt='logo image'
/>
{transactionItem.type === 'TRANSFER' ? (
<TokenBalance
value={transactionItem.amount.value || '0'}
Expand Down

0 comments on commit fe604cf

Please sign in to comment.