Skip to content

Commit

Permalink
feat: get and display collection name
Browse files Browse the repository at this point in the history
  • Loading branch information
AMIRKHANEF committed Oct 28, 2024
1 parent 0013459 commit 95d3ca5
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,98 +6,83 @@
import type { ThumbnailProps } from '../utils/types';

import CollectionsIcon from '@mui/icons-material/Collections';
import { Box, Divider, Grid, Typography } from '@mui/material';
import React, { useCallback, useMemo, useState } from 'react';
import { Divider, Grid, Typography } from '@mui/material';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router';

import { useTranslation } from '../../../components/translate';
import { THUMBNAIL_HEIGHT, THUMBNAIL_WIDTH } from '../utils/constants';
import Details, { InfoRow } from './Details';
import { fetchCollectionName } from '../utils/util';
import Details from './Details';
import InfoRow from './InfoRow';
import ItemAvatar from './ItemAvatar';
import ItemSkeleton from './ItemSkeleton';

export default function Thumbnail ({ api, itemInformation }: ThumbnailProps): React.ReactElement {
const { t } = useTranslation();
const { address } = useParams<{ address: string }>();

const [showDetail, setShowDetail] = useState<boolean>(false);

const displayNft = useMemo(() => Boolean(!itemInformation?.noData && itemInformation?.data), [itemInformation?.data, itemInformation?.noData]);
const loading = useMemo(() => Boolean(itemInformation?.data && !itemInformation.description && !itemInformation.name), [itemInformation?.data, itemInformation?.description, itemInformation?.name]);

useEffect(() => {
itemInformation && !itemInformation?.isCollection && !itemInformation?.collectionName && fetchCollectionName(address, api, itemInformation).catch(console.error);
}, [address, api, itemInformation]);

const openNftDetail = useCallback(() => setShowDetail(true), []);

return (
<>
{loading
? <ItemSkeleton />
: <Grid container item onClick={openNftDetail} sx={{ bgcolor: 'divider', border: '1px solid', borderColor: 'divider', borderRadius: '10px', boxShadow: '2px 3px 4px rgba(0, 0, 0, 0.2)', cursor: displayNft ? 'pointer' : 'default', height: THUMBNAIL_HEIGHT, width: THUMBNAIL_WIDTH }}>
{itemInformation?.data === null &&
<Grid alignItems='center' container item justifyContent='center'>
<Typography fontSize='16px' fontWeight={400}>
{t('Without data')}!
: <Grid container item onClick={openNftDetail} sx={{ '&:hover': { boxShadow: 3, transform: 'translateY(-2px)' }, bgcolor: 'divider', border: '1px solid', borderColor: 'divider', borderRadius: '10px', boxShadow: '2px 3px 4px rgba(0, 0, 0, 0.2)', cursor: 'pointer', height: THUMBNAIL_HEIGHT, position: 'relative', transition: '0.3s', width: THUMBNAIL_WIDTH }}>
<ItemAvatar
image={itemInformation?.image ?? null}
/>
<Grid container item px='8px'>
{itemInformation?.name &&
<Typography fontSize='14px' fontWeight={400} sx={{ maxWidth: '174px', overflow: 'hidden', py: '15px', textAlign: 'center', textOverflow: 'ellipsis', whiteSpace: 'nowrap', width: '100%' }}>
{itemInformation.name}
</Typography>
</Grid>
}
{displayNft &&
<Box
}
{itemInformation?.items !== undefined &&
<InfoRow
isThumbnail
text={itemInformation.items.toString()}
title={t('Items')}
/>
}
{!itemInformation?.isCollection &&
<InfoRow
api={api}
divider={false}
price={itemInformation?.price}
title={t('Price')}
/>
}
{itemInformation?.chainName &&
<>
<Divider sx={{ bgcolor: 'divider', height: '1px', m: '8px auto 0', width: '100%' }} />
<Typography fontSize='14px' fontWeight={400} sx={{ maxWidth: '174px', overflow: 'hidden', py: '5px', textAlign: 'center', textOverflow: 'ellipsis', whiteSpace: 'nowrap', width: '100%' }}>
{itemInformation.chainName}
</Typography>
</>
}
</Grid>
{itemInformation?.isCollection &&
<CollectionsIcon
sx={{
'&:hover': {
boxShadow: 3,
transform: 'translateY(-2px)'
},
bgcolor: 'support.main',
borderRadius: '5px',
position: 'relative',
transition: '0.3s',
width: 'max-content'
boxShadow: '0 0 1px rgb(0, 0, 0)',
color: 'secondary.light',
p: '2px',
position: 'absolute',
right: '10px',
top: '10px'
}}
>
<ItemAvatar
image={itemInformation?.image ?? null}
/>
<Grid container item px='8px'>
{itemInformation?.name &&
<Typography fontSize='14px' fontWeight={400} sx={{ maxWidth: '174px', overflow: 'hidden', py: '15px', textAlign: 'center', textOverflow: 'ellipsis', whiteSpace: 'nowrap', width: '100%' }}>
{itemInformation.name}
</Typography>
}
{itemInformation?.items !== undefined &&
<InfoRow
isThumbnail
text={itemInformation.items.toString()}
title={t('Items')}
/>
}
{!itemInformation?.isCollection &&
<InfoRow
api={api}
divider={false}
price={itemInformation?.price}
title={t('Price')}
/>
}
{itemInformation?.chainName &&
<>
<Divider sx={{ bgcolor: 'divider', height: '1px', m: '8px auto 0', width: '100%' }} />
<Typography fontSize='14px' fontWeight={400} sx={{ maxWidth: '174px', overflow: 'hidden', pt: '10px', textAlign: 'center', textOverflow: 'ellipsis', whiteSpace: 'nowrap', width: '100%' }}>
{itemInformation.chainName}
</Typography>
</>
}
</Grid>
{itemInformation?.isCollection &&
<CollectionsIcon
sx={{
bgcolor: 'support.main',
borderRadius: '5px',
boxShadow: '0 0 1px rgb(0, 0, 0)',
color: 'secondary.light',
p: '2px',
position: 'absolute',
right: '10px',
top: '10px'
}}
/>
}
</Box>
/>
}
</Grid>
}
Expand Down
2 changes: 1 addition & 1 deletion packages/extension-polkagate/src/fullscreen/nft/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function NFT (): React.ReactElement {
setStep(STEPS.INDEX);

nfts.forEach((nft) => {
(nft.data && (nft.image === undefined && nft.animation_url === undefined)) &&
(nft.data && ((nft.image === undefined && nft.animation_url === undefined) || !nft.collectionName)) &&
fetchItemMetadata(address, nft).catch(console.error);
});

Expand Down
50 changes: 50 additions & 0 deletions packages/extension-polkagate/src/fullscreen/nft/utils/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
// SPDX-License-Identifier: Apache-2.0

import type { ApiPromise } from '@polkadot/api';
import type { DataType, ItemInformation, ItemMetadata } from './types';

import NftManager from '../../../class/nftManager';
Expand Down Expand Up @@ -99,6 +100,50 @@ export const fetchData = async <T>(contentUrl: string | undefined, isMetadata =

const nftManager = new NftManager();

const getCollectionName = (collectionId: string | undefined, isNftCollection: boolean) => {
const allNftItems = nftManager.getAll();

if (allNftItems && collectionId) {
const collection = Object.values(allNftItems).flat().find(({ collectionId: id, isCollection, isNft }) => isCollection && isNftCollection === isNft && id === String(collectionId));

if (collection) {
return collection.name;
}
}

return undefined;
};

export const fetchCollectionName = async (address: string, api: ApiPromise | undefined, nftItemInfo: ItemInformation): Promise<void> => {
if (!api) {
return;
}

try {
const queryPath = nftItemInfo.isNft ? 'nfts' : 'uniques';
const metadataMethod = nftItemInfo.isNft ? 'collectionMetadataOf' : 'classMetadataOf';

const response = await api.query[queryPath][metadataMethod](nftItemInfo.collectionId);
const res = response.toPrimitive() as { data: string | undefined };

if (!res?.data) {
return;
}

const metadata = await fetchData<{ name?: string }>(res.data, true);

if (metadata?.name) {
nftManager.setItemDetail(
address,
nftItemInfo,
{ collectionName: metadata.name } as ItemMetadata
);
}
} catch (error) {
console.error(`Error fetching ${nftItemInfo.isNft ? 'NFT' : 'Unique'} collection name:`, error);
}
};

export const fetchItemMetadata = async (address: string, item: ItemInformation) => {
try {
// if data in empty or null or undefined so the item detail gonna be null, means nothing to display
Expand Down Expand Up @@ -135,10 +180,15 @@ export const fetchItemMetadata = async (address: string, item: ItemInformation)
? await fetchData<DataType>(itemMetadata.animation_url)
: null;

const collectionName = item.isCollection
? undefined
: getCollectionName(item.collectionId, item.isNft);

const detail = {
...itemMetadata,
animationContentType: nftAnimationContent?.contentType,
animation_url: nftAnimationContent?.url ?? null,
collectionName,
image: nftImageContent?.url ?? null,
imageContentType: nftImageContent?.contentType
};
Expand Down

0 comments on commit 95d3ca5

Please sign in to comment.