Add StillVideo component

media-gallery
Alex Gleason 2023-02-08 16:56:33 -06:00
rodzic fd2bb2e16f
commit 49b996a901
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
4 zmienionych plików z 74 dodań i 67 usunięć

Wyświetl plik

@ -1,5 +1,6 @@
import React from 'react';
import StillVideo from 'soapbox/components/still-video';
import { Icon } from 'soapbox/components/ui';
import { MIMETYPE_ICONS } from 'soapbox/components/upload';
@ -8,15 +9,15 @@ import type { Attachment } from 'soapbox/types/entities';
const defaultIcon = require('@tabler/icons/paperclip.svg');
interface IMediaPreview {
className?: string
attachment: Attachment
withExt?: boolean
}
/**
* Displays a generic preview for an attachment depending on its media type.
* It fills its container and is expected to be sized by its parent.
*/
const MediaPreview: React.FC<IMediaPreview> = ({ className, attachment }) => {
const MediaPreview: React.FC<IMediaPreview> = ({ attachment, withExt }) => {
const mimeType = attachment.pleroma.get('mime_type') as string | undefined;
switch (attachment.type) {
@ -31,14 +32,10 @@ const MediaPreview: React.FC<IMediaPreview> = ({ className, attachment }) => {
);
case 'video':
return (
<video
className='pointer-events-none h-full w-full object-cover'
src={attachment.preview_url}
autoPlay
playsInline
controls={false}
muted
loop
<StillVideo
className='h-full w-full object-cover'
src={attachment.url}
withExt={withExt}
/>
);
default:

Wyświetl plik

@ -0,0 +1,65 @@
import clsx from 'clsx';
import React from 'react';
import ExtensionBadge from './extension-badge';
interface IStillVideo {
src: string
className?: string
hoverToPlay?: boolean
playbackRate?: number
withExt?: boolean
}
/** Displays a frozen frame of a video unless hovered. */
const StillVideo: React.FC<IStillVideo> = ({
src,
className,
hoverToPlay = true,
playbackRate = 3,
withExt = true,
}) => {
// https://stackoverflow.com/a/4695156
const ext = src.split('.').pop()?.toUpperCase();
const handleMouseEnter: React.MouseEventHandler<HTMLVideoElement> = ({ currentTarget: video }) => {
if (hoverToPlay) {
video.playbackRate = playbackRate;
video.play();
}
};
const handleMouseLeave: React.MouseEventHandler<HTMLVideoElement> = ({ currentTarget: video }) => {
if (hoverToPlay) {
video.pause();
}
};
const handleClick: React.MouseEventHandler<HTMLVideoElement> = (e) => {
e.preventDefault();
};
return (
<div className={clsx(className, 'relative isolate overflow-hidden')}>
<video
className='h-full w-full object-cover'
src={src}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onClick={handleClick}
playsInline
controls={false}
muted
loop
/>
{(withExt && ext) && (
<div className='pointer-events-none absolute left-2 bottom-2 opacity-90'>
<ExtensionBadge ext={ext} />
</div>
)}
</div>
);
};
export default StillVideo;

Wyświetl plik

@ -1,55 +0,0 @@
import React from 'react';
import { Icon } from 'soapbox/components/ui';
import { MIMETYPE_ICONS } from 'soapbox/components/upload';
import type { Attachment } from 'soapbox/types/entities';
const defaultIcon = require('@tabler/icons/paperclip.svg');
interface IChatUploadPreview {
className?: string
attachment: Attachment
}
/**
* Displays a generic preview for an upload depending on its media type.
* It fills its container and is expected to be sized by its parent.
*/
const ChatUploadPreview: React.FC<IChatUploadPreview> = ({ className, attachment }) => {
const mimeType = attachment.pleroma.get('mime_type') as string | undefined;
switch (attachment.type) {
case 'image':
return (
<img
className='pointer-events-none h-full w-full object-cover'
src={attachment.preview_url}
alt=''
/>
);
case 'video':
return (
<video
className='pointer-events-none h-full w-full object-cover'
src={attachment.preview_url}
autoPlay
playsInline
controls={false}
muted
loop
/>
);
default:
return (
<div className='pointer-events-none flex h-full w-full items-center justify-center'>
<Icon
className='mx-auto my-12 h-16 w-16 text-gray-800 dark:text-gray-200'
src={MIMETYPE_ICONS[mimeType || ''] || defaultIcon}
/>
</div>
);
}
};
export default ChatUploadPreview;

Wyświetl plik

@ -28,7 +28,7 @@ const ChatUpload: React.FC<IChatUpload> = ({ attachment, onDelete }) => {
<div className='relative isolate inline-block h-24 w-24 overflow-hidden rounded-lg bg-gray-200 dark:bg-primary-900'>
<Blurhash hash={attachment.blurhash} className='absolute inset-0 -z-10 h-full w-full' />
<div className='absolute right-[6px] top-[6px]'>
<div className='absolute right-[6px] top-[6px] z-10'>
<RemoveButton onClick={onDelete} />
</div>
@ -36,7 +36,7 @@ const ChatUpload: React.FC<IChatUpload> = ({ attachment, onDelete }) => {
onClick={clickable ? handleOpenModal : undefined}
className={clsx('h-full w-full', { 'cursor-zoom-in': clickable, 'cursor-default': !clickable })}
>
<MediaPreview attachment={attachment} />
<MediaPreview attachment={attachment} withExt={false} />
</button>
</div>
);