import { AudiotrackRounded, ImageNotSupported } from '@mui/icons-material' import clsx from 'clsx' import NextImage from 'next/image' import { forwardRef, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import ReactPlayer from 'react-player' import { NftCardInfo } from '@dao-dao/types' import { NFT_VIDEO_EXTENSIONS, getImageUrlForChainId, getNftName, objectMatchesStructure, toAccessibleImageUrl, } from '@dao-dao/utils' import { AudioPlayer } from './AudioPlayer' import { CopyToClipboard } from './CopyToClipboard' import { LinkWrapper } from './LinkWrapper' export interface HorizontalNftCardProps extends NftCardInfo { className?: string } export const HorizontalNftCard = forwardRef< HTMLDivElement, HorizontalNftCardProps >(function HorizontalNftCard( { collectionAddress, collectionName, externalLink, imageUrl, metadata, name, tokenId, chainId, className, }, ref ) { const { t } = useTranslation() const chainImage = getImageUrlForChainId(chainId) const chainImageNode = chainImage && ( ) const video = // If image contains a video, treat it as a video. imageUrl && NFT_VIDEO_EXTENSIONS.includes(imageUrl.split('.').pop() || '') ? imageUrl : metadata && objectMatchesStructure(metadata, { properties: { video: {}, }, }) ? metadata.properties.video : null const [imageLoading, setImageLoading] = useState(!!imageUrl) const [imageLoadErrored, setImageLoadErrored] = useState(false) // Load image in background so we can listen for loading complete. const [loadedImageSrc, setLoadedImgSrc] = useState() useEffect(() => { if ( // If showing a video, don't load image. video || !imageUrl || loadedImageSrc === toAccessibleImageUrl(imageUrl) ) { return } setImageLoading(true) const img = new Image() img.onload = () => { setLoadedImgSrc(img.src) setImageLoading(false) setImageLoadErrored(false) } img.onerror = () => { setLoadedImgSrc(undefined) setImageLoading(false) setImageLoadErrored(true) } img.src = toAccessibleImageUrl(imageUrl) }, [imageUrl, loadedImageSrc, video]) const audio = metadata && objectMatchesStructure(metadata, { properties: { audio: {}, }, }) ? metadata.properties.audio : null const showingImageUrl = imageUrl && !imageLoadErrored return ( {video ? ( setImageLoading(false)} url={video} width="100%" /> ) : showingImageUrl ? ( ) : ( {audio ? ( ) : ( )} )} {audio && !video && ( )} {/* Don't include collection name since we show it below. */} {getNftName('', tokenId, name)} {/* Collection */} {collectionName} {/* Source chain */} {chainImageNode ? ( externalLink ? ( {chainImageNode} ) : ( chainImageNode ) ) : null} ) }) export const HorizontalNftCardLoader = () => ( LOADING LOADING LOADING )
{/* Don't include collection name since we show it below. */} {getNftName('', tokenId, name)}
{collectionName}
LOADING