feat: show analysis progress with per-file counter and cached tally
Day highlights: replaces the static "Analysing N files…" spinner with a
live progress bar, current filename ("3 / 8 — recording.wav"), and a
running tally of cached vs freshly-analysed files. Completes with a
summary line ("Done — 8 files (6 cached, 2 analysed)").
Single-file analyse: adds a small "cached" badge in the waveform box
when the result was served from cache.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -704,6 +704,11 @@ button.chip:hover{background:#6c1f08;border-color:#9a3412}
|
|||||||
button.chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
|
button.chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
|
||||||
.quiet{color:var(--muted);font-size:12px;margin-top:6px}
|
.quiet{color:var(--muted);font-size:12px;margin-top:6px}
|
||||||
.spin{color:var(--muted);font-style:italic;font-size:12px;padding:6px 0}
|
.spin{color:var(--muted);font-style:italic;font-size:12px;padding:6px 0}
|
||||||
|
.prog-bar{height:3px;background:var(--brd);border-radius:2px;margin:6px 0 4px;overflow:hidden}
|
||||||
|
.prog-fill{height:100%;background:var(--accent);border-radius:2px;transition:width 0.15s ease}
|
||||||
|
.prog-file{font-size:12px;color:var(--muted);font-style:italic;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
|
||||||
|
.prog-tally{font-size:11px;color:var(--muted);margin-top:3px}
|
||||||
|
.cached-badge{font-size:10px;color:var(--muted);background:var(--surf);border:1px solid var(--brd);border-radius:3px;padding:1px 5px;margin-left:6px;vertical-align:middle;font-style:normal}
|
||||||
.empty{text-align:center;padding:60px;color:var(--muted)}
|
.empty{text-align:center;padding:60px;color:var(--muted)}
|
||||||
/* player row */
|
/* player row */
|
||||||
.player-row td{padding:0 10px 10px;background:var(--bg);border-bottom:1px solid var(--brd)}
|
.player-row td{padding:0 10px 10px;background:var(--bg);border-bottom:1px solid var(--brd)}
|
||||||
@@ -955,6 +960,12 @@ async function analyse(idx, filename, cell, btn) {
|
|||||||
}
|
}
|
||||||
const box = document.createElement('div'); box.className='wbox';
|
const box = document.createElement('div'); box.className='wbox';
|
||||||
box.appendChild(drawWave(d.rms_display||[], d.sections||[], d.duration||0, filename));
|
box.appendChild(drawWave(d.rms_display||[], d.sections||[], d.duration||0, filename));
|
||||||
|
if (d.cached) {
|
||||||
|
const badge = document.createElement('span');
|
||||||
|
badge.className = 'cached-badge'; badge.textContent = 'cached';
|
||||||
|
badge.title = 'Result loaded from cache — change threshold/gap and re-analyse to recompute';
|
||||||
|
box.firstChild.after(badge);
|
||||||
|
}
|
||||||
|
|
||||||
const chips = document.createElement('div');
|
const chips = document.createElement('div');
|
||||||
chips.className='chips';
|
chips.className='chips';
|
||||||
@@ -1323,22 +1334,43 @@ async function dayHighlights(dayId, analyzableFiles) {
|
|||||||
|
|
||||||
hlRow.hidden = false;
|
hlRow.hidden = false;
|
||||||
const n = analyzableFiles.length;
|
const n = analyzableFiles.length;
|
||||||
contentEl.innerHTML = `<div class="spin" aria-live="polite" aria-busy="true">Analysing ${n} file${n!==1?'s':''}…</div>`;
|
|
||||||
if (btn) btn.disabled = true;
|
if (btn) btn.disabled = true;
|
||||||
|
|
||||||
|
// Build progress UI
|
||||||
|
const progWrap = document.createElement('div');
|
||||||
|
progWrap.setAttribute('aria-live', 'polite'); progWrap.setAttribute('aria-busy', 'true');
|
||||||
|
const progBar = document.createElement('div'); progBar.className = 'prog-bar';
|
||||||
|
const progFill = document.createElement('div'); progFill.className = 'prog-fill'; progFill.style.width = '0%';
|
||||||
|
progBar.appendChild(progFill);
|
||||||
|
const progFile = document.createElement('div'); progFile.className = 'prog-file';
|
||||||
|
const progTally = document.createElement('div'); progTally.className = 'prog-tally';
|
||||||
|
progWrap.appendChild(progBar); progWrap.appendChild(progFile); progWrap.appendChild(progTally);
|
||||||
|
contentEl.innerHTML = ''; contentEl.appendChild(progWrap);
|
||||||
|
|
||||||
const threshold = document.getElementById('threshold-input').value || '0.05';
|
const threshold = document.getElementById('threshold-input').value || '0.05';
|
||||||
const minGap = document.getElementById('min-gap-input').value || '2';
|
const minGap = document.getElementById('min-gap-input').value || '2';
|
||||||
|
|
||||||
const results = [];
|
const results = [];
|
||||||
for (const f of analyzableFiles) {
|
let nCached = 0, nLive = 0;
|
||||||
|
for (let i = 0; i < analyzableFiles.length; i++) {
|
||||||
|
const f = analyzableFiles[i];
|
||||||
|
progFile.textContent = `${i + 1} / ${n} — ${f.name}`;
|
||||||
|
progFill.style.width = `${(i / n) * 100}%`;
|
||||||
|
const tallyParts = [];
|
||||||
|
if (nCached) tallyParts.push(`${nCached} cached`);
|
||||||
|
if (nLive) tallyParts.push(`${nLive} analysed`);
|
||||||
|
progTally.textContent = tallyParts.join(' · ');
|
||||||
try {
|
try {
|
||||||
const r = await fetch('/api/analyze?file=' + encodeURIComponent(f.name)
|
const r = await fetch('/api/analyze?file=' + encodeURIComponent(f.name)
|
||||||
+ '&threshold=' + encodeURIComponent(threshold)
|
+ '&threshold=' + encodeURIComponent(threshold)
|
||||||
+ '&min_gap=' + encodeURIComponent(minGap));
|
+ '&min_gap=' + encodeURIComponent(minGap));
|
||||||
const d = await r.json();
|
const d = await r.json();
|
||||||
if (!d.error) results.push({ f, data: d });
|
if (!d.error) { results.push({ f, data: d }); d.cached ? nCached++ : nLive++; }
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
}
|
}
|
||||||
|
progFill.style.width = '100%';
|
||||||
|
progFile.textContent = `Done — ${n} file${n!==1?'s':''} (${nCached} cached, ${nLive} analysed)`;
|
||||||
|
progTally.textContent = '';
|
||||||
|
|
||||||
if (!results.length) {
|
if (!results.length) {
|
||||||
contentEl.innerHTML = '<div class="quiet">No analysable results.</div>';
|
contentEl.innerHTML = '<div class="quiet">No analysable results.</div>';
|
||||||
|
|||||||
Reference in New Issue
Block a user