Fix discovery phase appearing frozen

Scanner now updates message every 250 files during os.walk so the UI
shows a live count. Progress bar switches to an indeterminate animated
pulse during discovery and takeout phases (no known total yet), then
reverts to a normal percentage bar once indexing begins.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
tocmo
2026-04-05 01:25:41 -04:00
parent 6e7bb241ad
commit b519e065cb
2 changed files with 21 additions and 2 deletions

View File

@@ -492,6 +492,12 @@ def run_scan(folder_path: str, scan_id: int, mode: str = "incremental"):
ext = Path(fname).suffix.lower() ext = Path(fname).suffix.lower()
if ext in SUPPORTED_EXT: if ext in SUPPORTED_EXT:
all_files.append(os.path.join(root, fname)) all_files.append(os.path.join(root, fname))
# Live count update every 250 files so UI doesn't look frozen
if len(all_files) % 250 == 0:
scan_state["message"] = f"Discovering... {len(all_files):,} files found"
if scan_state["cancel_requested"]:
break
scan_state["total"] = len(all_files) scan_state["total"] = len(all_files)
scan_state["message"] = f"Found {len(all_files):,} files" scan_state["message"] = f"Found {len(all_files):,} files"

View File

@@ -212,6 +212,14 @@
background: var(--accent); background: var(--accent);
transition: width .3s; transition: width .3s;
} }
.progress-bar-fill.indeterminate {
width: 40% !important;
animation: indeterminate 1.4s ease-in-out infinite;
}
@keyframes indeterminate {
0% { transform: translateX(-100%); }
100% { transform: translateX(300%); }
}
.progress-msg { font-size: 12px; color: var(--text-dim); } .progress-msg { font-size: 12px; color: var(--text-dim); }
.phase-pills { .phase-pills {
display: flex; display: flex;
@@ -1057,8 +1065,13 @@ function updateScanUI(s) {
if (isRunning) { if (isRunning) {
el('progress-msg').textContent = s.message || ''; el('progress-msg').textContent = s.message || '';
const pct = s.total > 0 ? Math.round((s.progress / s.total) * 100) : 0; const indeterminate = s.phase === 'discovery' || s.phase === 'takeout' || s.total === 0;
el('progress-fill').style.width = pct + '%'; const fill = el('progress-fill');
fill.classList.toggle('indeterminate', indeterminate);
if (!indeterminate) {
const pct = Math.round((s.progress / s.total) * 100);
fill.style.width = pct + '%';
}
el('progress-count').textContent = s.total > 0 ? `${fmt(s.progress)} / ${fmt(s.total)}` : ''; el('progress-count').textContent = s.total > 0 ? `${fmt(s.progress)} / ${fmt(s.total)}` : '';
const phaseIdx = PHASES.indexOf(s.phase); const phaseIdx = PHASES.indexOf(s.phase);