2023-10-07 15:14:45 -07:00
|
|
|
import React, { Suspense } from 'react';
|
2022-05-31 10:31:08 -07:00
|
|
|
|
|
|
|
import { openModal } from 'soapbox/actions/modals';
|
|
|
|
import AttachmentThumbs from 'soapbox/components/attachment-thumbs';
|
2023-10-10 17:03:03 -07:00
|
|
|
import PreviewCard from 'soapbox/components/preview-card';
|
2022-11-15 11:00:40 -08:00
|
|
|
import PlaceholderCard from 'soapbox/features/placeholder/components/placeholder-card';
|
2022-05-31 10:31:08 -07:00
|
|
|
import { MediaGallery, Video, Audio } from 'soapbox/features/ui/util/async-components';
|
2024-04-21 10:07:14 -07:00
|
|
|
import { useAppDispatch, useSettings } from 'soapbox/hooks';
|
|
|
|
import { defaultMediaVisibility } from 'soapbox/utils/status';
|
2022-05-31 10:31:08 -07:00
|
|
|
|
|
|
|
import type { List as ImmutableList } from 'immutable';
|
|
|
|
import type { Status, Attachment } from 'soapbox/types/entities';
|
|
|
|
|
|
|
|
interface IStatusMedia {
|
|
|
|
/** Status entity to render media for. */
|
2023-10-02 11:54:02 -07:00
|
|
|
status: Status;
|
2022-05-31 10:31:08 -07:00
|
|
|
/** Whether to display compact media. */
|
2023-10-02 11:54:02 -07:00
|
|
|
muted?: boolean;
|
2022-05-31 10:31:08 -07:00
|
|
|
/** Callback when compact media is clicked. */
|
2023-10-02 11:54:02 -07:00
|
|
|
onClick?: () => void;
|
2022-05-31 10:31:08 -07:00
|
|
|
/** Whether or not the media is concealed behind a NSFW banner. */
|
2023-10-02 11:54:02 -07:00
|
|
|
showMedia?: boolean;
|
2022-05-31 10:31:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Render media attachments for a status. */
|
|
|
|
const StatusMedia: React.FC<IStatusMedia> = ({
|
|
|
|
status,
|
|
|
|
muted = false,
|
|
|
|
onClick,
|
2024-04-21 10:07:14 -07:00
|
|
|
showMedia,
|
2022-05-31 10:31:08 -07:00
|
|
|
}) => {
|
|
|
|
const dispatch = useAppDispatch();
|
2024-04-21 10:07:14 -07:00
|
|
|
const { displayMedia } = useSettings();
|
|
|
|
|
|
|
|
const visible = showMedia || (status.hidden === null ? defaultMediaVisibility(status, displayMedia) : status.hidden);
|
2022-05-31 10:31:08 -07:00
|
|
|
|
2022-11-27 14:29:45 -08:00
|
|
|
const size = status.media_attachments.size;
|
|
|
|
const firstAttachment = status.media_attachments.first();
|
2022-09-08 14:25:02 -07:00
|
|
|
|
|
|
|
let media: JSX.Element | null = null;
|
2022-05-31 10:31:08 -07:00
|
|
|
|
|
|
|
const renderLoadingMediaGallery = (): JSX.Element => {
|
|
|
|
return <div className='media_gallery' style={{ height: '285px' }} />;
|
|
|
|
};
|
|
|
|
|
|
|
|
const renderLoadingVideoPlayer = (): JSX.Element => {
|
2024-04-29 06:49:09 -07:00
|
|
|
return <div className='relative mt-2 block cursor-pointer border-0 bg-cover bg-center bg-no-repeat' style={{ height: '285px' }} />;
|
2022-05-31 10:31:08 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
const renderLoadingAudioPlayer = (): JSX.Element => {
|
2024-04-29 06:49:09 -07:00
|
|
|
return <div className='relative mt-2 block cursor-pointer border-0 bg-cover bg-center bg-no-repeat' style={{ height: '285px' }} />;
|
2022-05-31 10:31:08 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
const openMedia = (media: ImmutableList<Attachment>, index: number) => {
|
2022-10-18 17:10:16 -07:00
|
|
|
dispatch(openModal('MEDIA', { media, status, index }));
|
2022-05-31 10:31:08 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
if (size > 0 && firstAttachment) {
|
|
|
|
if (muted) {
|
|
|
|
media = (
|
|
|
|
<AttachmentThumbs
|
2022-11-27 14:29:45 -08:00
|
|
|
media={status.media_attachments}
|
2022-05-31 10:31:08 -07:00
|
|
|
onClick={onClick}
|
|
|
|
sensitive={status.sensitive}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
} else if (size === 1 && firstAttachment.type === 'video') {
|
|
|
|
const video = firstAttachment;
|
|
|
|
|
2023-09-19 11:10:57 -07:00
|
|
|
media = (
|
2023-10-07 15:14:45 -07:00
|
|
|
<Suspense fallback={renderLoadingVideoPlayer()}>
|
|
|
|
<Video
|
|
|
|
preview={video.preview_url}
|
|
|
|
blurhash={video.blurhash}
|
|
|
|
src={video.url}
|
|
|
|
alt={video.description}
|
|
|
|
aspectRatio={Number(video.meta.getIn(['original', 'aspect']))}
|
|
|
|
height={285}
|
2024-04-21 10:07:14 -07:00
|
|
|
visible={visible}
|
2023-10-07 15:14:45 -07:00
|
|
|
inline
|
|
|
|
/>
|
|
|
|
</Suspense>
|
2023-09-19 11:10:57 -07:00
|
|
|
);
|
2022-05-31 10:31:08 -07:00
|
|
|
} else if (size === 1 && firstAttachment.type === 'audio') {
|
|
|
|
const attachment = firstAttachment;
|
|
|
|
|
|
|
|
media = (
|
2023-10-07 15:14:45 -07:00
|
|
|
<Suspense fallback={renderLoadingAudioPlayer()}>
|
|
|
|
<Audio
|
|
|
|
src={attachment.url}
|
|
|
|
alt={attachment.description}
|
|
|
|
poster={attachment.preview_url !== attachment.url ? attachment.preview_url : status.getIn(['account', 'avatar_static']) as string | undefined}
|
|
|
|
backgroundColor={attachment.meta.getIn(['colors', 'background']) as string | undefined}
|
|
|
|
foregroundColor={attachment.meta.getIn(['colors', 'foreground']) as string | undefined}
|
|
|
|
accentColor={attachment.meta.getIn(['colors', 'accent']) as string | undefined}
|
2024-04-29 06:49:09 -07:00
|
|
|
duration={attachment.meta.getIn(['original', 'duration'], 0) as number | undefined}
|
2023-10-07 15:14:45 -07:00
|
|
|
height={263}
|
|
|
|
/>
|
|
|
|
</Suspense>
|
2022-05-31 10:31:08 -07:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
media = (
|
2023-10-07 15:14:45 -07:00
|
|
|
<Suspense fallback={renderLoadingMediaGallery()}>
|
|
|
|
<MediaGallery
|
|
|
|
media={status.media_attachments}
|
|
|
|
sensitive={status.sensitive}
|
|
|
|
height={285}
|
|
|
|
onOpenMedia={openMedia}
|
2024-04-21 10:07:14 -07:00
|
|
|
visible={visible}
|
2023-10-07 15:14:45 -07:00
|
|
|
/>
|
|
|
|
</Suspense>
|
2022-05-31 10:31:08 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
} else if (status.spoiler_text.length === 0 && !status.quote && status.card) {
|
|
|
|
media = (
|
2023-10-10 17:03:03 -07:00
|
|
|
<PreviewCard
|
2022-05-31 10:31:08 -07:00
|
|
|
onOpenMedia={openMedia}
|
|
|
|
card={status.card}
|
|
|
|
compact
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
} else if (status.expectsCard) {
|
|
|
|
media = (
|
|
|
|
<PlaceholderCard />
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-11-20 10:56:13 -08:00
|
|
|
if (media) {
|
|
|
|
return (
|
|
|
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
|
|
<div onClick={e => e.stopPropagation()}>
|
|
|
|
{media}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
2022-05-31 10:31:08 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
export default StatusMedia;
|