Files
explore/ui/shared/nft/NftMediaFullscreenModal.tsx

91 lines
2.7 KiB
TypeScript

import React from 'react';
import type { TokenInstance } from 'types/api/token';
import { DialogContent, DialogRoot, DialogCloseTrigger } from '@luxfi/ui/dialog';
import NftHtml from './NftHtml';
import NftImage from './NftImage';
import NftVideo from './NftVideo';
import useNftMediaInfo from './useNftMediaInfo';
import type { MediaType } from './utils';
interface Props {
open: boolean;
onOpenChange: ({ open }: { open: boolean }) => void;
data: TokenInstance;
allowedTypes?: Array<MediaType>;
field: 'animation_url' | 'image_url';
}
const NftMediaFullscreenModal = ({ open, onOpenChange, data, allowedTypes, field }: Props) => {
const [ mediaInfoIndex, setMediaInfoIndex ] = React.useState(0);
const mediaInfoQuery = useNftMediaInfo({ data, size: 'original', allowedTypes, field, isEnabled: true });
const handleMediaLoadError = React.useCallback(() => {
if (mediaInfoQuery.data) {
if (mediaInfoIndex < mediaInfoQuery.data.length - 1) {
setMediaInfoIndex(mediaInfoIndex + 1);
return;
}
}
// FIXME: maybe we should display something if the media is not loaded
}, [ mediaInfoIndex, mediaInfoQuery.data ]);
const content = (() => {
const mediaInfo = mediaInfoQuery.data?.[mediaInfoIndex];
switch (mediaInfo?.mediaType) {
case 'video':
return (
<NftVideo
src={ mediaInfo.src }
transport={ mediaInfo.transport }
onError={ handleMediaLoadError }
className="max-w-[90vw] max-h-[90vh] object-contain"
autoPlay
instance={ data }
/>
);
case 'html':
return (
<NftHtml
src={ mediaInfo.src }
transport={ mediaInfo.transport }
onError={ handleMediaLoadError }
className="w-[90vw] h-[90vh]"
/>
);
case 'image':
return (
<NftImage
src={ mediaInfo.src }
srcSet={ mediaInfo.srcSet }
transport={ mediaInfo.transport }
onError={ handleMediaLoadError }
className="max-w-[90vw] max-h-[90vh] object-contain"
/>
);
default:
return null;
}
})();
return (
<DialogRoot open={ open } onOpenChange={ onOpenChange } motionPreset="none">
<DialogContent className="w-[unset] max-w-[100vw] p-0 bg-transparent shadow-none">
{ /* FIXME (maybe): if close trigger is outside of the dialog header, it will not hide backdrop after closing the dialog */ }
<div>
<DialogCloseTrigger
className="fixed top-6 right-6"
/>
</div>
{ content }
</DialogContent>
</DialogRoot>
);
};
export default NftMediaFullscreenModal;