Files
relay/client/src/components/chat/chatArea/AttachmentPreview.tsx

75 lines
2.2 KiB
TypeScript

import { useEffect, useState } from 'react';
import LoadingWheel from '../LoadingWheel.tsx';
import FileBox from './FileBox.tsx';
const loadedMedia = new Set();
const AttachmentPreview = ({ url }: { url: string }) => {
const isImage = url.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/i);
const isVideo = url.match(/\.(mp4|webm|ogg|mov)$/i);
const [isLoading, setIsLoading] = useState(!loadedMedia.has(url));
useEffect(() => {
if (isImage && !loadedMedia.has(url)) {
const img = new Image();
img.onload = () => {
loadedMedia.add(url);
setIsLoading(false);
};
img.src = url;
} else if (isVideo && !loadedMedia.has(url)) {
const video = document.createElement('video');
video.onloadedmetadata = () => {
loadedMedia.add(url);
setIsLoading(false);
};
video.src = url;
}
// setIsLoading(true);
}, [url, isImage, isVideo]);
if (!isImage && !isVideo) {
return <FileBox url={url} />;
}
if (isVideo) {
return (
<div className="relative w-full">
{isLoading && (
<div className="absolute max-h-64 inset-0 flex items-center justify-center bg-gray-800 bg-opacity-50 rounded h-40">
<LoadingWheel />
</div>
)}
<video
controls
className={`w-full max-h-64 rounded transition-opacity duration-200 ${
isLoading ? 'opacity-0' : 'opacity-100'
}`}
onLoadedMetadata={() => setIsLoading(false)}
>
<source src={url} type={`video/${url.split('.').pop()}`} />
Your browser does not support the video tag.
</video>
</div>
);
}
return (
<div className="relative inline-block max-w-full">
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-gray-800 bg-opacity-50 rounded "></div>
)}
<a href={url} target="_blank" rel="noopener noreferrer">
<img
src={url}
alt="attachment"
className={`min-h-14 max-h-64 max-w-full rounded
transition-opacity duration-300 ease-in
${isLoading ? 'opacity-0' : 'opacity-100'}`}
/>
</a>
</div>
);
};
export default AttachmentPreview;