Skip to content

Commit

Permalink
Show NFTs with missing metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljscript committed Mar 17, 2023
1 parent a98e503 commit a8cde7d
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 24 deletions.
19 changes: 14 additions & 5 deletions src/NftDetails/NftDetails.tsx
Expand Up @@ -14,7 +14,7 @@ import {useSelectedWallet} from '../SelectedWallet'
import {COLORS} from '../theme'
import {useNft} from '../yoroi-wallets'
import {YoroiNft} from '../yoroi-wallets/types'
import placeholder from './../assets/img/nft-placeholder.png'
import placeholderImage from './../assets/img/nft-placeholder.png'

export const NftDetails = () => {
const {id} = useRoute<RouteProp<NftRoutes, 'nft-details'>>().params
Expand Down Expand Up @@ -61,7 +61,12 @@ export const NftDetails = () => {

const UnModeratedNftImage = ({nft}: {nft: YoroiNft}) => {
const navigateTo = useNavigateTo()
return <NftImage source={{uri: nft.image}} onPress={() => navigateTo.nftZoom(nft.id)} />
return (
<NftImage
source={typeof nft.image === 'string' ? {uri: nft.image} : placeholderImage}
onPress={() => navigateTo.nftZoom(nft.id)}
/>
)
}

const NftImage = ({
Expand All @@ -88,7 +93,7 @@ const ModeratedNftImage = ({nft}: {nft: YoroiNft}) => {

return (
<NftImage
source={canShowNft ? {uri: nft.image} : placeholder}
source={canShowNft ? {uri: nft.image} : placeholderImage}
onPress={() => navigateTo.nftZoom(nft.id)}
disabled={!canShowNft}
/>
Expand Down Expand Up @@ -123,13 +128,13 @@ const NftOverview = ({nft}: {nft: YoroiNft}) => {
<HR />

<MetadataRow title={strings.description}>
<Text secondary>{nft.description}</Text>
<Text secondary>{normalizeMetadataString(nft.description)}</Text>
</MetadataRow>

<HR />

<MetadataRow title={strings.author}>
<Text secondary>{nft.metadata.originalMetadata.author ?? '-'}</Text>
<Text secondary>{normalizeMetadataString(nft.metadata.originalMetadata?.author)}</Text>
</MetadataRow>

<HR />
Expand Down Expand Up @@ -175,6 +180,10 @@ const NftOverview = ({nft}: {nft: YoroiNft}) => {
)
}

const normalizeMetadataString = (content?: string): string => {
return typeof content === 'undefined' || content.length === 0 ? '-' : content
}

const HR = () => (
<View
style={{
Expand Down
7 changes: 6 additions & 1 deletion src/NftDetails/NftDetailsImage.tsx
Expand Up @@ -3,6 +3,7 @@ import React from 'react'
import {Dimensions, Image, StyleSheet, View} from 'react-native'
import ViewTransformer from 'react-native-easy-view-transformer'

import placeholderImage from '../assets/img/nft-placeholder.png'
import {FadeIn} from '../components'
import {NftRoutes} from '../navigation'
import {useSelectedWallet} from '../SelectedWallet'
Expand All @@ -20,7 +21,11 @@ export const NftDetailsImage = () => {
<FadeIn style={styles.container}>
<ViewTransformer maxScale={3} minScale={1}>
<View style={styles.contentContainer}>
<Image source={{uri: nft.image}} style={{height: imageSize, width: imageSize}} resizeMode="contain" />
<Image
source={typeof nft.image === 'string' ? {uri: nft.image} : placeholderImage}
style={{height: imageSize, width: imageSize}}
resizeMode="contain"
/>
</View>
</ViewTransformer>
</FadeIn>
Expand Down
21 changes: 9 additions & 12 deletions src/Nfts/ImageGallery/ImageGallery.tsx
Expand Up @@ -50,7 +50,7 @@ interface ModeratedImageProps {
const UnModeratedImage = ({onPress, nft: {image, name}}: ModeratedImageProps) => {
return (
<TouchableOpacity onPress={onPress}>
<ApprovedNft text={name} uri={image} />
{typeof image === 'string' ? <ApprovedNft text={name} uri={image} /> : <PlaceholderNft text={name} />}
</TouchableOpacity>
)
}
Expand Down Expand Up @@ -87,7 +87,9 @@ const ModeratedImage = ({onPress, nft}: ModeratedImageProps) => {

return (
<TouchableOpacity onPress={onPress}>
{isImageApproved ? (
{typeof thumbnail === 'undefined' ? (
<PlaceholderNft text={text} />
) : isImageApproved ? (
<ApprovedNft text={text} uri={thumbnail} />
) : isImageWithConsent ? (
<RequiresConsentNft text={text} uri={thumbnail} />
Expand All @@ -101,18 +103,14 @@ const ModeratedImage = ({onPress, nft}: ModeratedImageProps) => {
}

function BlockedNft({text}: {text: string}) {
return (
<View>
<Image source={placeholderImage} style={[styles.image, {width: IMAGE_SIZE, height: IMAGE_SIZE}]} />

<Spacer height={IMAGE_PADDING} />

<Text style={[styles.text, {width: IMAGE_SIZE}]}>{text}</Text>
</View>
)
return <PlaceholderNft text={text} />
}

function ManualReviewNft({text}: {text: string}) {
return <PlaceholderNft text={text} />
}

function PlaceholderNft({text}: {text: string}) {
return (
<View>
<Image source={placeholderImage} style={[styles.image, {width: IMAGE_SIZE, height: IMAGE_SIZE}]} />
Expand All @@ -123,7 +121,6 @@ function ManualReviewNft({text}: {text: string}) {
</View>
)
}

function RequiresConsentNft({uri, text}: {text: string; uri: string}) {
return (
<View>
Expand Down
6 changes: 6 additions & 0 deletions src/components/TokenIcon/ModeratedNftIcon.tsx
Expand Up @@ -39,10 +39,16 @@ function BlockedNftIcon() {
}

function ApprovedNftIcon({image}: {image?: string}) {
if (typeof image === 'undefined') {
return <Icon source={NftPlaceholder} />
}
return <Icon source={{uri: image}} />
}

function ConsentNftIcon({image}: {image?: string}) {
if (typeof image === 'undefined') {
return <Icon source={NftPlaceholder} />
}
return <Image source={{uri: image}} style={styles.assetIcon} blurRadius={20} borderRadius={32} />
}

Expand Down
5 changes: 3 additions & 2 deletions src/yoroi-wallets/cardano/api/api.ts
Expand Up @@ -22,7 +22,7 @@ import {NFTAsset, RemoteAsset, YoroiNft, YoroiNftModerationStatus} from '../../t
import {hasProperties, isArray, isNonNullable, isObject, isRecord} from '../../utils/parsing'
import {ServerStatus} from '..'
import {ApiError} from '../errors'
import {convertNft} from '../nfts'
import {convertNft, createPlaceholderNft} from '../nfts'
import fetchDefault, {checkedFetch} from './fetch'
import {fallbackTokenInfo, tokenInfo, toTokenSubject} from './utils'

Expand Down Expand Up @@ -233,8 +233,9 @@ function parseNFTs(value: unknown, storageUrl: string): YoroiNft[] {
const nftMetadata = nftAsset.metadata?.[policyId]?.[assetName]

if (!nftMetadata || !nftMetadata.image) {
return null
return createPlaceholderNft({policyId, shortName: assetName})
}

return convertNft(nftMetadata, storageUrl, policyId, assetName)
})

Expand Down
16 changes: 16 additions & 0 deletions src/yoroi-wallets/cardano/nfts.ts
Expand Up @@ -31,3 +31,19 @@ export const convertNft = (
},
}
}

export const createPlaceholderNft = ({shortName, policyId}: {shortName: string; policyId: string}): YoroiNft => {
const assetNameHex = asciiToHex(shortName)
const fingerprint = getAssetFingerprint(policyId, assetNameHex)
const id = `${policyId}.${assetNameHex}`
return {
id,
fingerprint,
name: shortName,
description: '',
metadata: {
policyId,
assetNameHex,
},
}
}
2 changes: 1 addition & 1 deletion src/yoroi-wallets/hooks/index.ts
Expand Up @@ -238,7 +238,7 @@ export const useNftImageModerated = ({
}: {
wallet: YoroiWallet
nftId: string
}): {image: string; status: YoroiNftModerationStatus} | null => {
}): {image?: string; status: YoroiNftModerationStatus} | null => {
const nft = useNft(wallet, {id: nftId})
const fingerprint = nft.fingerprint
const {data} = useNftModerationStatus({wallet, fingerprint})
Expand Down
6 changes: 3 additions & 3 deletions src/yoroi-wallets/types/types.ts
Expand Up @@ -63,13 +63,13 @@ export type YoroiNft = {
id: string
name: string
description: string
image: string
thumbnail: string
image?: string
thumbnail?: string
fingerprint: string
metadata: {
policyId: string
assetNameHex: string
originalMetadata: NftMetadata
originalMetadata?: NftMetadata
}
}

Expand Down

0 comments on commit a8cde7d

Please sign in to comment.