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; };