From 432753e1887dd5e4300f6486848a77c840cbafa9 Mon Sep 17 00:00:00 2001 From: arsen Date: Sun, 17 May 2026 16:34:14 +0700 Subject: [PATCH] feat(adr-107): progress bar in raw.html calibrate button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the text-pill status with a 140×14 px progress bar that fills from 0 → 99% over CALIB_DURATION_SEC (90s default). On complete it flashes to 100% with "done" label, then hides itself after 3s; on error it surfaces a text pill so failure modes stay visible. Closes the last Open Item in ADR-107. Co-Authored-By: claude-flow --- .../static/raw.html | 66 ++++++++++++++++--- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/v2/crates/wifi-densepose-sensing-server/static/raw.html b/v2/crates/wifi-densepose-sensing-server/static/raw.html index 20cf8249..ceb9b414 100644 --- a/v2/crates/wifi-densepose-sensing-server/static/raw.html +++ b/v2/crates/wifi-densepose-sensing-server/static/raw.html @@ -54,6 +54,18 @@ + + @@ -401,24 +413,49 @@ function renderTick() { } requestAnimationFrame(renderTick); -// ── ADR-107: baseline calibrate button + polling ────────────────── +// ── ADR-107: baseline calibrate button + progress bar ───────────── let calibPollTimer = null; +const CALIB_DURATION_SEC = 90; + +function setCalibProgress(pct, label) { + const bar = document.getElementById('calibProgress'); + const fill = document.getElementById('calibProgressFill'); + const txt = document.getElementById('calibProgressLabel'); + if (!bar || !fill || !txt) return; + bar.style.display = pct < 0 ? 'none' : 'inline-block'; + fill.style.width = Math.max(0, Math.min(100, pct)) + '%'; + txt.textContent = label || ''; +} + async function startCalibrate() { - if (!confirm('Step OUT of the room now. Calibration will record for 90 s.\nClick OK when you are out.')) return; + if (!confirm(`Step OUT of the room now. Calibration will record for ${CALIB_DURATION_SEC} s.\nClick OK when you are out.`)) return; const btn = document.getElementById('calibrateBtn'); const stat = document.getElementById('calibStatus'); btn.disabled = true; btn.textContent = 'recording…'; - stat.style.display = 'inline-block'; stat.textContent = 'starting…'; + // Hide the text-pill while the progress bar is the primary indicator; + // it reappears only on terminal status messages (error / complete). + stat.style.display = 'none'; + setCalibProgress(0, 'starting…'); try { const res = await fetch('/api/v1/baseline/calibrate', { method: 'POST', headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ duration_sec: 90, trim_sec: 15, clean_window_sec: 30 }), + body: JSON.stringify({ duration_sec: CALIB_DURATION_SEC, trim_sec: 15, clean_window_sec: 30 }), }); const j = await res.json(); - if (!j.started) { stat.textContent = j.reason || 'failed to start'; btn.disabled = false; btn.textContent = 'calibrate empty'; return; } + if (!j.started) { + setCalibProgress(-1, ''); + stat.style.display = 'inline-block'; + stat.textContent = j.reason || 'failed to start'; + btn.disabled = false; btn.textContent = 'calibrate empty'; + return; + } } catch (e) { - stat.textContent = 'network error'; btn.disabled = false; btn.textContent = 'calibrate empty'; return; + setCalibProgress(-1, ''); + stat.style.display = 'inline-block'; + stat.textContent = 'network error'; + btn.disabled = false; btn.textContent = 'calibrate empty'; + return; } if (calibPollTimer) clearInterval(calibPollTimer); let elapsed = 0; @@ -427,11 +464,22 @@ async function startCalibrate() { try { const r = await fetch('/api/v1/baseline'); const j = await r.json(); const s = j.calibration_status || 'idle'; - stat.textContent = s.startsWith('running') ? `recording… ${elapsed}/90 s` : s; - if (!s.startsWith('running')) { + if (s.startsWith('running')) { + const pct = Math.min(99, (elapsed / CALIB_DURATION_SEC) * 100); + setCalibProgress(pct, `${elapsed}/${CALIB_DURATION_SEC} s`); + } else { clearInterval(calibPollTimer); calibPollTimer = null; btn.disabled = false; btn.textContent = 'calibrate empty'; - if (s === 'complete') stat.textContent = 'baseline updated ✓'; + if (s === 'complete') { + setCalibProgress(100, 'done'); + stat.style.display = 'inline-block'; + stat.textContent = 'baseline updated ✓'; + setTimeout(() => setCalibProgress(-1, ''), 3000); + } else { + setCalibProgress(-1, ''); + stat.style.display = 'inline-block'; + stat.textContent = s; + } } } catch (e) {} }, 2000);