From a7ef0397e1fbe2b009881ffcc6de8ff249a32c69 Mon Sep 17 00:00:00 2001 From: zgaetano Date: Fri, 29 May 2026 19:53:19 -0400 Subject: [PATCH] fix(web-ui): show live download % on YouTube import bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The import queue row's progress bar read only `r.progress`, which pollRow never updated numerically — it tracked asset.status (ingesting/processing/ ready) but not a percentage, so the bar sat at 0 until the asset flipped to ready, then snapped to 100 ("blank until it finishes"). pollRow now also fetches GET /jobs/ and feeds the BullMQ job's numeric progress (worker emits 2..100 across the yt-dlp download + S3 upload) into the bar, so it fills during the download. Falls back to status when the job is evicted post-completion. Also reaffirm 'downloading' label while ingesting and poll a bit faster (2s) since short clips finish quickly. Co-Authored-By: Claude Opus 4.8 --- services/web-ui/public/screens-ingest.jsx | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/services/web-ui/public/screens-ingest.jsx b/services/web-ui/public/screens-ingest.jsx index ef2d7f0..9da9262 100644 --- a/services/web-ui/public/screens-ingest.jsx +++ b/services/web-ui/public/screens-ingest.jsx @@ -230,11 +230,29 @@ function YouTubeImport({ navigate }) { patch.error = patch.error || 'Import failed: check the Jobs screen for details.'; } else if (asset.status === 'processing') { patch.status = 'processing'; + } else if (asset.status === 'ingesting') { + patch.status = 'downloading'; } + + // While the import is still running, pull the live percentage from its + // BullMQ job so the bar reflects the actual yt-dlp download instead of + // sitting at 0 until the asset flips to ready. The worker emits 2..100 + // across the download + S3 upload (job.updateProgress). If the job has + // already completed and been evicted, the fetch throws and we just fall + // back to the status-driven values above. + if (row.jobId && asset.status !== 'ready' && asset.status !== 'error') { + try { + const job = await window.ZAMPP_API.fetch('/jobs/' + row.jobId); + if (typeof job.progress === 'number') patch.progress = job.progress; + } catch { /* job evicted after completion — fall back to status */ } + } + if (Object.keys(patch).length) updateRow(row.id, patch); if (asset.status === 'ready' || asset.status === 'error') return; } catch { /* ignore */ } - setTimeout(tick, 3000); + // Poll fairly briskly: the download phase is where the user wants to see + // the bar move, and a short clip can finish in a handful of seconds. + setTimeout(tick, 2000); }; tick(); return () => { stopped = true; };