From d31416f85d82336728d395267adfe5f8bcabc627 Mon Sep 17 00:00:00 2001 From: dswbx Date: Mon, 29 Sep 2025 15:55:25 +0200 Subject: [PATCH] feat: enhance mime type handling and improve file metadata management Updated mime types to include additional formats for text and application categories. Improved file metadata handling in the Storage class to accurately reflect file properties during uploads. Enhanced the DropzoneInner component with new icons for various file types and refined the MediaInfoModal to support a broader range of text formats for previews. --- app/src/media/storage/Storage.ts | 23 ++++--- app/src/media/storage/mime-types-tiny.ts | 4 +- app/src/ui/elements/media/DropzoneInner.tsx | 72 ++++++++++++++++++++- app/src/ui/modals/media/MediaInfoModal.tsx | 14 ++-- 4 files changed, 90 insertions(+), 23 deletions(-) diff --git a/app/src/media/storage/Storage.ts b/app/src/media/storage/Storage.ts index 6615f8e..1d11b1d 100644 --- a/app/src/media/storage/Storage.ts +++ b/app/src/media/storage/Storage.ts @@ -71,22 +71,29 @@ export class Storage implements EmitsEvents { let info: FileUploadPayload = { name, - meta: { - size: 0, - type: "application/octet-stream", - }, + meta: isFile(file) + ? { + size: file.size, + type: file.type, + } + : { + size: 0, + type: "application/octet-stream", + }, etag: typeof result === "string" ? result : "", }; + // normally only etag is returned if (typeof result === "object") { info = result; - } else if (isFile(file)) { - info.meta.size = file.size; - info.meta.type = file.type; } // try to get better meta info - if (!isMimeType(info.meta.type, ["application/octet-stream", "application/json"])) { + if ( + !info.meta.type || + ["application/octet-stream", "application/json"].includes(info.meta.type) || + !info.meta.size + ) { const meta = await this.#adapter.getObjectMeta(name); if (!meta) { throw new Error("Failed to get object meta"); diff --git a/app/src/media/storage/mime-types-tiny.ts b/app/src/media/storage/mime-types-tiny.ts index 16598b6..fcadd55 100644 --- a/app/src/media/storage/mime-types-tiny.ts +++ b/app/src/media/storage/mime-types-tiny.ts @@ -2,8 +2,8 @@ export const Q = { video: ["mp4", "webm"], audio: ["ogg"], image: ["jpeg", "png", "gif", "webp", "bmp", "tiff", "avif", "heic", "heif"], - text: ["html", "css", "mdx", "yaml", "vcard", "csv", "vtt"], - application: ["zip", "xml", "toml", "json", "json5", "pdf"], + text: ["html", "css", "mdx", "yaml", "vcard", "csv", "vtt", "xml"], + application: ["zip", "toml", "json", "json5", "pdf", "sql"], font: ["woff", "woff2", "ttf", "otf"], } as const; diff --git a/app/src/ui/elements/media/DropzoneInner.tsx b/app/src/ui/elements/media/DropzoneInner.tsx index db3402e..742ca3b 100644 --- a/app/src/ui/elements/media/DropzoneInner.tsx +++ b/app/src/ui/elements/media/DropzoneInner.tsx @@ -1,7 +1,22 @@ import { type ComponentPropsWithoutRef, memo, type ReactNode, useCallback, useMemo } from "react"; import { twMerge } from "tailwind-merge"; import { useRenderCount } from "ui/hooks/use-render-count"; -import { TbDots, TbExternalLink, TbTrash, TbUpload } from "react-icons/tb"; +import { + TbDots, + TbExternalLink, + TbFileTypeCsv, + TbFileText, + TbJson, + TbFileTypePdf, + TbMarkdown, + TbMusic, + TbTrash, + TbUpload, + TbFileTypeTxt, + TbFileTypeXml, + TbZip, + TbFileTypeSql, +} from "react-icons/tb"; import { Dropdown, type DropdownItem } from "ui/components/overlay/Dropdown"; import { IconButton } from "ui/components/buttons/IconButton"; import { formatNumber } from "core/utils"; @@ -85,7 +100,7 @@ const UploadPlaceholder = ({ onClick, text = "Upload files" }) => { ); }; -type ReducedFile = Pick; +type ReducedFile = Omit; export type PreviewComponentProps = { file: ReducedFile; fallback?: (props: { file: ReducedFile }) => ReactNode; @@ -271,8 +286,59 @@ const VideoPreview = ({ return