From a31c5349925130d9a92dd3e11c72bcc265432b92 Mon Sep 17 00:00:00 2001 From: "[dyad]" Date: Sun, 18 Jan 2026 11:06:39 +0100 Subject: [PATCH] [dyad] Enable batch image processing - wrote 1 file(s) --- src/components/image-converter.tsx | 133 +++++++++++++---------------- 1 file changed, 60 insertions(+), 73 deletions(-) diff --git a/src/components/image-converter.tsx b/src/components/image-converter.tsx index 76daff5..8a28a62 100644 --- a/src/components/image-converter.tsx +++ b/src/components/image-converter.tsx @@ -28,9 +28,6 @@ export function ImageConverter() { const [images, setImages] = useState([]); const [previewUrls, setPreviewUrls] = useState([]); const [filenames, setFilenames] = useState([]); - const [selectedImageIndex, setSelectedImageIndex] = useState( - null - ); const [width, setWidth] = useState(""); const [height, setHeight] = useState(""); const [format, setFormat] = useState<"png" | "jpeg" | "webp">("png"); @@ -44,20 +41,6 @@ export function ImageConverter() { }; }, [previewUrls]); - useEffect(() => { - if (selectedImageIndex !== null && previewUrls[selectedImageIndex]) { - const img = new Image(); - img.onload = () => { - setWidth(img.width); - setHeight(img.height); - }; - img.src = previewUrls[selectedImageIndex]; - } else { - setWidth(""); - setHeight(""); - } - }, [selectedImageIndex, previewUrls]); - const handleFiles = (files: FileList | null) => { if (!files || files.length === 0) return; @@ -86,9 +69,6 @@ export function ImageConverter() { setPreviewUrls(newPreviewUrls); setFilenames(newFilenames); - if (selectedImageIndex === null) { - setSelectedImageIndex(images.length); - } toast.success(`${imageFiles.length} image(s) added.`); }; @@ -122,14 +102,6 @@ export function ImageConverter() { setImages(newImages); setPreviewUrls(newPreviewUrls); setFilenames(newFilenames); - - if (selectedImageIndex === indexToRemove) { - setSelectedImageIndex( - newImages.length > 0 ? Math.max(0, indexToRemove - 1) : null - ); - } else if (selectedImageIndex !== null && selectedImageIndex > indexToRemove) { - setSelectedImageIndex(selectedImageIndex - 1); - } }; const handleClearAll = () => { @@ -137,7 +109,6 @@ export function ImageConverter() { setImages([]); setPreviewUrls([]); setFilenames([]); - setSelectedImageIndex(null); toast.info("All images cleared."); }; @@ -150,56 +121,69 @@ export function ImageConverter() { setFilenames(newFilenames); }; - const handleConvertAndDownload = () => { - if (selectedImageIndex === null || !width || !height) { - toast.error("Please select an image and set dimensions."); + const handleConvertAndDownload = async () => { + if (images.length === 0 || !width || !height) { + toast.error("Please upload images and set dimensions."); return; } - if ( - !filenames[selectedImageIndex] || - filenames[selectedImageIndex].trim() === "" - ) { - toast.error("Please enter a filename for the selected image."); + + if (filenames.some((name) => name.trim() === "")) { + toast.error("Please ensure all images have a filename."); return; } setIsConverting(true); - const image = images[selectedImageIndex]; - const previewUrl = previewUrls[selectedImageIndex]; - const img = new Image(); - img.crossOrigin = "anonymous"; - img.src = previewUrl; + toast.info(`Starting conversion for ${images.length} images...`); - img.onload = () => { - const canvas = document.createElement("canvas"); - canvas.width = Number(width); - canvas.height = Number(height); - const ctx = canvas.getContext("2d"); + const conversionPromises = images.map((image, index) => { + return new Promise((resolve, reject) => { + const previewUrl = previewUrls[index]; + const img = new Image(); + img.crossOrigin = "anonymous"; + img.src = previewUrl; - if (ctx) { - ctx.drawImage(img, 0, 0, Number(width), Number(height)); - const dataUrl = canvas.toDataURL(`image/${format}`); - const link = document.createElement("a"); - link.href = dataUrl; - const customName = filenames[selectedImageIndex]; - link.download = `${customName}_${width}x${height}.${format}`; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - toast.success(`Exported ${image.name} successfully!`); + img.onload = () => { + const canvas = document.createElement("canvas"); + canvas.width = Number(width); + canvas.height = Number(height); + const ctx = canvas.getContext("2d"); + + if (ctx) { + ctx.drawImage(img, 0, 0, Number(width), Number(height)); + const dataUrl = canvas.toDataURL(`image/${format}`); + const link = document.createElement("a"); + link.href = dataUrl; + const customName = filenames[index]; + link.download = `${customName}_${width}x${height}.${format}`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + resolve(); + } else { + reject(new Error(`Could not process ${image.name}.`)); + } + }; + img.onerror = () => { + reject(new Error(`Failed to load ${image.name} for conversion.`)); + }; + }); + }); + + try { + await Promise.all(conversionPromises); + toast.success(`Successfully exported all ${images.length} images!`); + } catch (error) { + if (error instanceof Error) { + toast.error(error.message); } else { - toast.error("Could not process the image."); + toast.error("An unknown error occurred during conversion."); } + } finally { setIsConverting(false); - }; - img.onerror = () => { - toast.error("Failed to load image for conversion."); - setIsConverting(false); - }; + } }; const hasImages = images.length > 0; - const isImageSelected = selectedImageIndex !== null; return (
@@ -208,23 +192,23 @@ export function ImageConverter() { Image Settings - Adjust resolution and format for the selected image. + Adjust resolution and format for all uploaded images.
- setWidth(e.target.value)} disabled={!isImageSelected} /> + setWidth(e.target.value)} disabled={!hasImages} />
- setHeight(e.target.value)} disabled={!isImageSelected} /> + setHeight(e.target.value)} disabled={!hasImages} />
- setFormat(value)} disabled={!hasImages}> PNG @@ -236,7 +220,10 @@ export function ImageConverter() { - +
@@ -272,7 +259,7 @@ export function ImageConverter() {
{previewUrls.map((url, index) => ( -
setSelectedImageIndex(index)}> +
{`Preview

@@ -280,10 +267,10 @@ export function ImageConverter() {

- handleFilenameChange(e, index)} onClick={(e) => e.stopPropagation()} /> + handleFilenameChange(e, index)} />
-