feat: full HEIF/HEIC support, content-aware resize performance fix, UI improvements

- Add bidirectional HEIF support: decode (input) and encode (output) via system heif-convert/heif-enc
- Add server-side WebP preview generation for non-browser-previewable formats (HEIC, TIFF)
- Fix content-aware resize failing on HEIF input (decode before passing to caire)
- Fix content-aware resize timeout on large images by downscaling to max 1200px and using JPEG intermediate
- Add HEIF as target format in convert tool
- Add loading spinner for HEIF preview decode in file store
- Fix file picker not accepting HEIF files (explicit .heic,.heif,.hif extensions)
- Extend frontend timeout for medium tools to 180s with 45s progress animation
- Redesign rotate controls with preset buttons and compact flip section
- Remove misleading savings percentage from convert tool
This commit is contained in:
Siddharth Kumar Sah
2026-04-11 23:27:44 +08:00
parent e0869477d4
commit 6f5283019b
18 changed files with 425 additions and 86 deletions
+9 -1
View File
@@ -10,7 +10,15 @@ interface DropzoneProps {
currentFiles?: File[];
}
// Browsers may not map .heic/.heif to image/* in file pickers.
// Append explicit extensions so they are selectable.
function expandAccept(accept?: string): string | undefined {
if (!accept?.includes("image/*")) return accept;
return `${accept},.heic,.heif,.hif`;
}
export function Dropzone({ onFiles, accept, multiple = true, currentFiles = [] }: DropzoneProps) {
const resolvedAccept = expandAccept(accept);
const [isDragging, setIsDragging] = useState(false);
const handleDrag = useCallback((e: DragEvent) => {
@@ -35,7 +43,7 @@ export function Dropzone({ onFiles, accept, multiple = true, currentFiles = [] }
const input = document.createElement("input");
input.type = "file";
input.multiple = multiple;
if (accept) input.accept = accept;
if (resolvedAccept) input.accept = resolvedAccept;
input.onchange = (e) => {
const files = Array.from((e.target as HTMLInputElement).files || []);
if (files.length > 0) onFiles?.(files);