100 lines
2.5 KiB
TypeScript
100 lines
2.5 KiB
TypeScript
import { useState, useEffect } from "react"
|
|
import axios from "axios"
|
|
import prettyBytes from "pretty-bytes"
|
|
import { DownloadIcon } from "@heroicons/react/solid"
|
|
|
|
import type { MessageWithMember } from "../../../../../models/Message"
|
|
import { Loader } from "../../../../design/Loader"
|
|
import { FileIcon } from "./FileIcon"
|
|
import { api } from "../../../../../tools/api"
|
|
|
|
const supportedImageMimetype = [
|
|
"image/png",
|
|
"image/jpg",
|
|
"image/jpeg",
|
|
"image/gif",
|
|
]
|
|
|
|
export interface FileData {
|
|
blob: Blob
|
|
url: string
|
|
}
|
|
|
|
export interface MessageContentProps {
|
|
message: MessageWithMember
|
|
}
|
|
|
|
export const MessageFile: React.FC<MessageContentProps> = (props) => {
|
|
const { message } = props
|
|
|
|
const [file, setFile] = useState<FileData | null>(null)
|
|
|
|
useEffect(() => {
|
|
const ourRequest = axios.CancelToken.source()
|
|
|
|
const fetchData = async (): Promise<void> => {
|
|
const { data } = await api.get(message.value, {
|
|
responseType: "blob",
|
|
cancelToken: ourRequest.token,
|
|
})
|
|
const fileURL = URL.createObjectURL(data)
|
|
setFile({ blob: data, url: fileURL })
|
|
}
|
|
fetchData().catch(() => {})
|
|
|
|
return () => {
|
|
ourRequest.cancel()
|
|
}
|
|
}, [message.value])
|
|
|
|
if (file == null) {
|
|
return <Loader />
|
|
}
|
|
if (supportedImageMimetype.includes(message.mimetype)) {
|
|
return (
|
|
<a href={file.url} target="_blank" rel="noreferrer">
|
|
<img
|
|
data-cy={`message-file-image-${message.id}`}
|
|
className="max-h-80 sm:max-w-xs"
|
|
src={file.url}
|
|
alt={message.value}
|
|
/>
|
|
</a>
|
|
)
|
|
}
|
|
if (message.mimetype.startsWith("audio/")) {
|
|
return (
|
|
<audio controls data-cy={`message-file-audio-${message.id}`}>
|
|
<source src={file.url} type={message.mimetype} />
|
|
</audio>
|
|
)
|
|
}
|
|
if (message.mimetype.startsWith("video/")) {
|
|
return (
|
|
<video
|
|
className="max-h-80 max-w-xs"
|
|
controls
|
|
data-cy={`message-file-video-${message.id}`}
|
|
>
|
|
<source src={file.url} type={message.mimetype} />
|
|
</video>
|
|
)
|
|
}
|
|
return (
|
|
<a href={file.url} download data-cy={`message-file-download-${message.id}`}>
|
|
<div className="flex items-center">
|
|
<div className="flex items-center">
|
|
<div>
|
|
<FileIcon />
|
|
</div>
|
|
<div className="ml-4">
|
|
<p>{file.blob.type}</p>
|
|
<p className="mt-1">{prettyBytes(file.blob.size)}</p>
|
|
</div>
|
|
</div>
|
|
<DownloadIcon className="ml-4 h-8 w-8" />
|
|
</div>
|
|
</a>
|
|
)
|
|
}
|