import React, { useState } from 'react'; import { openModal } from 'soapbox/actions/modals'; import AttachmentThumbs from 'soapbox/components/attachment-thumbs'; import PlaceholderCard from 'soapbox/features/placeholder/components/placeholder_card'; import Card from 'soapbox/features/status/components/card'; import Bundle from 'soapbox/features/ui/components/bundle'; import { MediaGallery, Video, Audio } from 'soapbox/features/ui/util/async-components'; import { useAppDispatch } from 'soapbox/hooks'; import type { List as ImmutableList } from 'immutable'; import type { Status, Attachment } from 'soapbox/types/entities'; interface IStatusMedia { /** Status entity to render media for. */ status: Status, /** Whether to display compact media. */ muted?: boolean, /** Callback when compact media is clicked. */ onClick?: () => void, /** Whether or not the media is concealed behind a NSFW banner. */ showMedia?: boolean, /** Callback when visibility is toggled (eg clicked through NSFW). */ onToggleVisibility?: () => void, /** Whether or not to hide image describer as 'Banner' */ excludeBanner?: boolean, } /** Render media attachments for a status. */ const StatusMedia: React.FC = ({ status, muted = false, onClick, showMedia = true, onToggleVisibility = () => {}, excludeBanner = false, }) => { const dispatch = useAppDispatch(); const [mediaWrapperWidth, setMediaWrapperWidth] = useState(undefined); const mediaAttachments = excludeBanner ? status.media_attachments.filter(({ description, pleroma }) => description !== 'Banner' && pleroma.get('mime_type') !== 'text/html') : status.media_attachments; const size = mediaAttachments.size; const firstAttachment = mediaAttachments.first(); let media: JSX.Element | null = null; const setRef = (c: HTMLDivElement): void => { if (c) { setMediaWrapperWidth(c.offsetWidth); } }; const renderLoadingMediaGallery = (): JSX.Element => { return
; }; const renderLoadingVideoPlayer = (): JSX.Element => { return
; }; const renderLoadingAudioPlayer = (): JSX.Element => { return
; }; const openMedia = (media: ImmutableList, index: number) => { dispatch(openModal('MEDIA', { media, index })); }; const openVideo = (media: Attachment, time: number): void => { dispatch(openModal('VIDEO', { media, time })); }; if (size > 0 && firstAttachment) { if (muted) { media = ( ); } else if (size === 1 && firstAttachment.type === 'video') { const video = firstAttachment; if (video.external_video_id && status.card) { const getHeight = (): number => { const width = Number(video.meta.getIn(['original', 'width'])); const height = Number(video.meta.getIn(['original', 'height'])); return Number(mediaWrapperWidth) / (width / height); }; const height = getHeight(); media = (
); } else { media = ( {(Component: any) => ( )} ); } } else if (size === 1 && firstAttachment.type === 'audio') { const attachment = firstAttachment; media = ( {(Component: any) => ( )} ); } else { media = ( {(Component: any) => ( )} ); } } else if (status.spoiler_text.length === 0 && !status.quote && status.card) { media = ( ); } else if (status.expectsCard) { media = ( ); } return media; }; export default StatusMedia;