feat: wire up batch processing across tool settings components

This commit is contained in:
Siddharth Kumar Sah
2026-03-23 14:11:08 +08:00
parent 846a51a9fd
commit 9e2c28f191
10 changed files with 80 additions and 33 deletions
@@ -6,7 +6,7 @@ import { ProgressCard } from "@/components/common/progress-card";
export function BorderSettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
useToolProcessor("border");
const [borderWidth, setBorderWidth] = useState(10);
@@ -16,7 +16,12 @@ export function BorderSettings() {
const [shadowBlur, setShadowBlur] = useState(0);
const handleProcess = () => {
processFiles(files, { borderWidth, borderColor, cornerRadius, padding, shadowBlur });
const settings = { borderWidth, borderColor, cornerRadius, padding, shadowBlur };
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -84,7 +89,7 @@ export function BorderSettings() {
disabled={!hasFile || processing}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Add Border
{files.length > 1 ? `Apply Border (${files.length} files)` : "Apply Border"}
</button>
)}
@@ -14,7 +14,7 @@ interface ColorSettingsProps {
export function ColorSettings({ toolId }: ColorSettingsProps) {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
useToolProcessor(toolId);
const [tab, setTab] = useState<Tab>(() => {
@@ -37,7 +37,7 @@ export function ColorSettings({ toolId }: ColorSettingsProps) {
const [effect, setEffect] = useState<Effect>("none");
const handleProcess = () => {
processFiles(files, {
const settings = {
brightness,
contrast,
saturation,
@@ -45,7 +45,12 @@ export function ColorSettings({ toolId }: ColorSettingsProps) {
green,
blue,
effect,
});
};
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -215,7 +220,7 @@ export function ColorSettings({ toolId }: ColorSettingsProps) {
disabled={!hasFile || !hasChanges || processing}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Apply
{files.length > 1 ? `Apply (${files.length} files)` : "Apply"}
</button>
)}
@@ -8,7 +8,7 @@ type CompressMode = "quality" | "targetSize";
export function CompressSettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
useToolProcessor("compress");
const [mode, setMode] = useState<CompressMode>("quality");
@@ -22,7 +22,11 @@ export function CompressSettings() {
} else {
settings.targetSizeKb = Number(targetSizeKb);
}
processFiles(files, settings);
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -124,7 +128,7 @@ export function CompressSettings() {
disabled={!hasFile || !canProcess || processing}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Compress
{files.length > 1 ? `Compress (${files.length} files)` : "Compress"}
</button>
)}
@@ -9,7 +9,7 @@ const LOSSY_FORMATS = new Set(["jpg", "webp", "avif"]);
export function ConvertSettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
useToolProcessor("convert");
const [format, setFormat] = useState<string>("png");
@@ -28,7 +28,11 @@ export function ConvertSettings() {
if (isLossy) {
settings.quality = quality;
}
processFiles(files, settings);
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -118,7 +122,7 @@ export function ConvertSettings() {
disabled={!hasFile || processing}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Convert
{files.length > 1 ? `Convert (${files.length} files)` : "Convert"}
</button>
)}
@@ -14,7 +14,7 @@ const ASPECT_PRESETS = [
export function CropSettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
useToolProcessor("crop");
const [left, setLeft] = useState("0");
@@ -31,12 +31,17 @@ export function CropSettings() {
};
const handleProcess = () => {
processFiles(files, {
const settings = {
left: Number(left),
top: Number(top),
width: Number(width),
height: Number(height),
});
};
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -141,7 +146,7 @@ export function CropSettings() {
disabled={!hasFile || !hasSize || processing}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Crop
{files.length > 1 ? `Crop (${files.length} files)` : "Crop"}
</button>
)}
@@ -6,7 +6,7 @@ import { ProgressCard } from "@/components/common/progress-card";
export function ReplaceColorSettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
useToolProcessor("replace-color");
const [sourceColor, setSourceColor] = useState("#FF0000");
@@ -15,7 +15,12 @@ export function ReplaceColorSettings() {
const [tolerance, setTolerance] = useState(30);
const handleProcess = () => {
processFiles(files, { sourceColor, targetColor, makeTransparent, tolerance });
const settings = { sourceColor, targetColor, makeTransparent, tolerance };
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -81,7 +86,7 @@ export function ReplaceColorSettings() {
disabled={!hasFile || processing}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Replace Color
{files.length > 1 ? `Replace Color (${files.length} files)` : "Replace Color"}
</button>
)}
@@ -19,7 +19,7 @@ const platforms = [...new Set(SOCIAL_MEDIA_PRESETS.map((p) => p.platform))];
export function ResizeSettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, progress } =
useToolProcessor("resize");
const [tab, setTab] = useState<ResizeTab>("presets");
@@ -56,7 +56,11 @@ export function ResizeSettings() {
settings.withoutEnlargement = withoutEnlargement;
}
processFiles(files, settings);
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -252,7 +256,7 @@ export function ResizeSettings() {
disabled={!canProcess}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Resize
{files.length > 1 ? `Resize (${files.length} files)` : "Resize"}
</button>
)}
@@ -22,7 +22,7 @@ interface RotateSettingsProps {
export function RotateSettings({ onPreviewTransform }: RotateSettingsProps) {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, progress } =
useToolProcessor("rotate");
const [angle, setAngle] = useState(0);
@@ -38,11 +38,16 @@ export function RotateSettings({ onPreviewTransform }: RotateSettingsProps) {
const rotateRight = () => setAngle((a) => (a + 90) % 360);
const handleProcess = () => {
processFiles(files, {
const settings = {
angle,
horizontal: flipH,
vertical: flipV,
});
};
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -144,7 +149,7 @@ export function RotateSettings({ onPreviewTransform }: RotateSettingsProps) {
disabled={!hasFile || !hasChanges || processing}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Apply
{files.length > 1 ? `Apply (${files.length} files)` : "Apply"}
</button>
)}
@@ -6,7 +6,7 @@ import { ProgressCard } from "@/components/common/progress-card";
export function TextOverlaySettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
useToolProcessor("text-overlay");
const [text, setText] = useState("Your Text Here");
@@ -18,7 +18,12 @@ export function TextOverlaySettings() {
const [shadow, setShadow] = useState(true);
const handleProcess = () => {
processFiles(files, { text, fontSize, color, position, backgroundBox, backgroundColor, shadow });
const settings = { text, fontSize, color, position, backgroundBox, backgroundColor, shadow };
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -102,7 +107,7 @@ export function TextOverlaySettings() {
disabled={!hasFile || processing || !text}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Add Text
{files.length > 1 ? `Apply Overlay (${files.length} files)` : "Apply Overlay"}
</button>
)}
@@ -8,7 +8,7 @@ type Position = "center" | "top-left" | "top-right" | "bottom-left" | "bottom-ri
export function WatermarkTextSettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress } =
useToolProcessor("watermark-text");
const [text, setText] = useState("Sample Watermark");
@@ -19,7 +19,12 @@ export function WatermarkTextSettings() {
const [rotation, setRotation] = useState(0);
const handleProcess = () => {
processFiles(files, { text, fontSize, color, opacity, position, rotation });
const settings = { text, fontSize, color, opacity, position, rotation };
if (files.length > 1) {
processAllFiles(files, settings);
} else {
processFiles(files, settings);
}
};
const hasFile = files.length > 0;
@@ -106,7 +111,7 @@ export function WatermarkTextSettings() {
disabled={!hasFile || processing || !text}
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
Add Watermark
{files.length > 1 ? `Apply Watermark (${files.length} files)` : "Apply Watermark"}
</button>
)}