diff --git a/packages/app/package.json b/packages/app/package.json index 59a8817d..f44fc609 100755 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -66,6 +66,7 @@ "localforage": "^1.10.0", "luxon": "^3.0.4", "match-sorter": "^6.3.1", + "mime": "^3.0.0", "moment": "2.29.4", "moment-timezone": "^0.5.37", "mpegts.js": "^1.6.10", diff --git a/packages/app/src/components/PostCard/components/attachments/index.jsx b/packages/app/src/components/PostCard/components/attachments/index.jsx index 3faa708e..e119ac0f 100755 --- a/packages/app/src/components/PostCard/components/attachments/index.jsx +++ b/packages/app/src/components/PostCard/components/attachments/index.jsx @@ -3,121 +3,112 @@ import { Skeleton } from "antd" import { Carousel } from "react-responsive-carousel" import { ImageViewer } from "components" import Plyr from "plyr-react" +import mimetypes from "mime" import ContentFailed from "../contentFailed" -const mediaTypes = { - "jpg": "image", - "jpeg": "image", - "png": "image", - "gif": "image", - "mp4": "video", - "webm": "video", - "ogv": "video", - "mov": "video", - "avi": "video", - "mkv": "video", - "ogg": "audio", - "mp3": "audio", - "wav": "audio", - "flac": "audio", - "aac": "audio", - "m4a": "audio", -} - import "react-responsive-carousel/lib/styles/carousel.min.css" import "plyr-react/dist/plyr.css" import "./index.less" const Attachment = React.memo((props) => { - const { url, id } = props.attachment - const [loaded, setLoaded] = React.useState(false) - const [mediaType, setMediaType] = React.useState(null) const [mimeType, setMimeType] = React.useState(null) - const onDoubleClickAttachment = (e) => { - if (mediaType.split("/")[0] === "image") { - e.preventDefault() - e.stopPropagation() - - app.controls.openFullImageViewer(url) - } - } - - const getMediaType = async () => { - let extension = null - - // get media type by parsing the url - const mediaTypeExt = /\.([a-zA-Z0-9]+)$/.exec(url) - - if (mediaTypeExt) { - extension = mediaTypeExt[1] - } else { - // try to get media by creating requesting the url - const response = await fetch(url, { - method: "HEAD", - }) - - extension = response.headers.get("content-type").split("/")[1] - } - - extension = extension.toLowerCase() - - const mediaType = mediaTypes[extension] - const mimeType = `${mediaType}/${extension}` - - setMediaType(mediaType) - setMimeType(mimeType) - - setLoaded(true) - } - - const renderMedia = () => { - switch (mediaType.split("/")[0]) { - case "image": { - return - } - case "video": { - return - } - case "audio": { - return - } - default: { - return

- Unsupported media type [{mediaType}/{mediaTypeExt}] -

- } - } - } - - React.useEffect(() => { - getMediaType() - }, []) - - if (!loaded) { - return - } - - if (loaded && !mediaType && !mimeType) { - return - } - try { + const { url, id } = props.attachment + + const onDoubleClickAttachment = (e) => { + if (mimeType.split("/")[0] === "image") { + e.preventDefault() + e.stopPropagation() + + app.controls.openFullImageViewer(url) + } + } + + const getMediaType = async () => { + let extension = null + + // get media type by parsing the url + const mediaExtname = /\.([a-zA-Z0-9]+)$/.exec(url) + + if (mediaExtname) { + extension = mediaExtname[1] + } else { + // try to get media by creating requesting the url + const response = await fetch(url, { + method: "HEAD", + }) + + extension = response.headers.get("content-type").split("/")[1] + } + + extension = extension.toLowerCase() + + if (!extension) { + setLoaded(true) + + console.error("Failed to get media type", url, extension) + + return + } + + const mimeType = mimetypes.getType(extension) + + setMimeType(mimeType) + + setLoaded(true) + } + + const renderMedia = () => { + if (!mimeType) { + return null + } + + switch (mimeType.split("/")[0]) { + case "image": { + return + } + case "video": { + return + } + case "audio": { + return + } + default: { + return

+ Unsupported media type [{mimeType}] +

+ } + } + } + + React.useEffect(() => { + getMediaType() + }, []) + + if (!loaded) { + return + } + + if (loaded && !mimeType) { + return + } + return
{ {renderMedia()}
} catch (error) { - console.error(`Failed to render attachment ${props.attachment.name} (${props.attachment.id})`, error) + console.error(error) return } @@ -179,6 +170,10 @@ export default (props) => { > { props.attachments?.length > 0 && props.attachments.map((attachment, index) => { + if (typeof attachment !== "object") { + return null + } + return }) }