import { FC, ReactElement, useEffect, useState } from "react"; import clsx from "clsx"; import { useAppSelector } from "@/app/store"; import useExpiredResMap from "@/hooks/useExpiredResMap"; import { formatBytes, fromNowTime, getFileIcon } from "@/utils"; import IconDownload from "@/assets/icons/download.svg"; import { AudioPreview, CodePreview, DocPreview, ImagePreview, PdfPreview, VideoPreview } from "./preview"; import { shallowEqual } from "react-redux"; interface Data { file_type: string; name: string; content: string; } const renderPreview = (data: Data) => { const { file_type, name, content } = data; let preview: null | ReactElement = null; const checks = { image: /^image/gi, audio: /^audio/gi, video: /^video/gi, code: /(json|javascript|java|rb|c|php|xml|css|html)$/gi, doc: /^text/gi, pdf: /\/pdf$/gi }; const _arr = name.split("."); const _type = file_type || _arr[_arr.length - 1]; switch (true) { case checks.image.test(_type): { preview = ; } break; case checks.pdf.test(_type): preview = ; break; case checks.code.test(_type): preview = ; break; case checks.doc.test(_type): preview = ; break; case checks.audio.test(_type): preview = ; break; case checks.video.test(_type): preview = ; break; } return preview; }; interface Props { preview?: boolean; flex: boolean; file_type: string; name: string; size: number; created_at: number; from_uid: number; content: string; } const FileBox: FC = ({ preview, flex, file_type, name, size, created_at, from_uid, content }) => { const [fetchError, setFetchError] = useState(false); const { isExpired, setExpired } = useExpiredResMap(); const fromUser = useAppSelector((store) => store.users.byId[from_uid], shallowEqual); const icon = getFileIcon(file_type, name, "icon w-9 h-12"); const expired = isExpired(content); useEffect(() => { const tryFetch = async (url: string) => { try { let statusNum = (await fetch(url)).status; if (statusNum >= 400) { setFetchError(true); } } catch (e) { setFetchError(true); } }; if (!expired && content) { tryFetch(content); } }, [content, expired]); useEffect(() => { if (fetchError) { setExpired(content); } }, [fetchError, content]); if (!content || expired || fetchError) return null; const previewContent = renderPreview({ file_type, content, name }); const withPreview = preview && previewContent && !fetchError && !expired; return (
{icon}
{name} {formatBytes(size)} {fromNowTime(created_at)} by {fromUser?.name || "Deleted User"}
{withPreview &&
{previewContent}
}
); }; export default FileBox;