fix: batch SSE progress and non-AI processing UX (#24)

Batch progress was broken because JobProgress events lacked a `type`
field. The frontend checks `data.type === "batch"` to distinguish batch
from single-file SSE events, so batch progress was silently discarded
and multi-file processing appeared stuck at 15%.

Also improves the processing UX for non-AI (Sharp-based) tools: the
progress bar now pulses during the server processing phase and shows
a "This may take a moment" hint after 10 seconds.

Co-authored-by: Siddharth Kumar Sah <siddharth123sk@gmail.com>
This commit is contained in:
stirling-image
2026-04-06 21:25:00 +08:00
committed by GitHub
co-authored by Siddharth Kumar Sah
parent 3018137548
commit dc70cdbdd5
2 changed files with 12 additions and 5 deletions
@@ -12,6 +12,9 @@ interface ProgressCardProps {
export function ProgressCard({ active, phase, label, stage, percent, elapsed }: ProgressCardProps) {
if (!active) return null;
// No real-time server progress: non-AI tools sit at 100% while the server works
const isIndeterminate = phase === "processing" && percent >= 100;
const icon =
phase === "uploading" ? (
<Upload className="h-4 w-4 text-primary" />
@@ -19,7 +22,8 @@ export function ProgressCard({ active, phase, label, stage, percent, elapsed }:
<Loader2 className="h-4 w-4 text-primary animate-spin" />
);
const sublabel = [stage, `${elapsed}s`].filter(Boolean).join(" \u00b7 ");
const slowHint = phase === "processing" && elapsed >= 10 ? "This may take a moment" : undefined;
const sublabel = [stage, slowHint, `${elapsed}s`].filter(Boolean).join(" \u00b7 ");
return (
<div className="bg-muted/80 border border-border rounded-xl p-3 space-y-2.5">
@@ -37,7 +41,7 @@ export function ProgressCard({ active, phase, label, stage, percent, elapsed }:
</div>
<div className="w-full h-1 bg-muted rounded-full overflow-hidden">
<div
className="h-full bg-primary rounded-full transition-all duration-500 ease-out"
className={`h-full bg-primary rounded-full transition-all duration-500 ease-out ${isIndeterminate ? "animate-pulse" : ""}`}
style={{ width: `${Math.min(100, percent)}%` }}
/>
</div>