Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions api/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion client/src/components/common/DragAndDropZone.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useDropzone, type Accept } from 'react-dropzone';
import { useDropzone } from 'react-dropzone';
import type { FileRejection, Accept } from 'react-dropzone';
import { useEffect, useRef, useState, useCallback } from 'preact/hooks';
import type { ComponentChildren, RefObject } from 'preact';

type DragAndDropZoneProps = {
onFileDrop: (file: File) => void | Promise<void>;
onFileReject?: (rejectedFiles: FileRejection[]) => void;
accept?: Accept;
multiple?: boolean;
className?: string;
Expand All @@ -13,6 +15,7 @@ type DragAndDropZoneProps = {

const DragAndDropZone = ({
onFileDrop,
onFileReject,
accept,
multiple = false,
className = '',
Expand Down Expand Up @@ -63,6 +66,14 @@ const DragAndDropZone = ({
console.error('Error handling dropped files:', error);
}
},
onDropRejected: (rejectedFiles) => {
if (!onFileReject) return;
try {
onFileReject(rejectedFiles);
} catch (error) {
console.error('Error handling rejected files:', error);
}
},
onDragEnter: () => updateOverlayRect(),
});

Expand Down
27 changes: 23 additions & 4 deletions client/src/components/images/ImageConverter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useRef, useEffect } from 'preact/hooks';
import { TargetedEvent } from 'preact/compat';
import { Accept } from 'react-dropzone';
import type { Accept, FileRejection } from 'react-dropzone';

import { useWasm } from '@/hooks/useWasm';
import ImageJSRootPreview from './ImageJSRootPreview';
Expand Down Expand Up @@ -60,6 +60,25 @@ const ImageConverter = () => {
'image/jpeg': ['.jpeg', '.jpg'],
};

const handleFileReject = (rejectedFiles: FileRejection[]) => {
if (rejectedFiles.length === 0) return;
const reasons = rejectedFiles
.map((rejection) => {
const errors = rejection.errors
.map((err) => {
if (err.code === 'file-invalid-type') {
return `${rejection.file.name}: unsupported type`;
}
return `${rejection.file.name}: ${err.message}`;
})
.join(', ');
return errors;
})
.join('; ');

setErrorMessage(`Rejected files: ${reasons}`);
};

const cleanupBlobUrls = () => {
if (prevSrcUrlRef.current) {
URL.revokeObjectURL(prevSrcUrlRef.current);
Expand Down Expand Up @@ -95,8 +114,8 @@ const ImageConverter = () => {
img.bits_per_sample === 16
? img.pixels_u16()
: img.bits_per_sample === 8
? img.pixels_u8()
: null;
? img.pixels_u8()
: null;
if (!pixels) {
setErrorMessage('Failed to extract pixel data from image');
return;
Expand Down Expand Up @@ -262,6 +281,7 @@ const ImageConverter = () => {
accept={acceptedFileTypes}
overlayTargetRef={overlayTargetRef}
onFileDrop={processFile}
onFileReject={handleFileReject}
className="w-full"
>
<ImageJSRootPreview
Expand Down Expand Up @@ -303,7 +323,6 @@ const ImageConverter = () => {
header={'Converted Image'}
aspectRatio={previewsAspectRatios}
setAspectRatio={setPreviewsAspectRatios}
error={errorMessage}
units={units}
mmPerPx={mmPerPx}
/>
Expand Down
Loading