mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: wire up batch processing across tool settings components
This commit is contained in:
@@ -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>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user