Timers: add enable checkbox; collapse settings + hide display readouts when off
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a011a89100
commit
333477afdb
1 changed files with 12 additions and 5 deletions
17
index.html
17
index.html
|
|
@ -56,6 +56,7 @@
|
|||
.display { background:#0a0d11; border:1px solid #000; border-radius:8px; padding:8px 14px; text-align:center; box-shadow:inset 0 2px 10px rgba(0,0,0,.7); }
|
||||
.display .big { font-family:"Courier New",monospace; font-weight:700; font-size:40px; color:#ffd166; letter-spacing:3px; text-shadow:0 0 12px rgba(255,209,102,.5); }
|
||||
.display .dtimers { font-family:"Courier New",monospace; font-size:13px; color:#4dd0e1; margin:3px 0; display:flex; gap:14px; justify-content:center; flex-wrap:wrap; }
|
||||
.display .dtimers[hidden] { display:none; }
|
||||
.display .ctx { font-family:"Courier New",monospace; font-size:12px; color:#4dd0e1; min-height:15px; line-height:1.3; }
|
||||
.display .ctx.muted-cue { color:#ffb454; }
|
||||
.knob { margin-bottom:10px; }
|
||||
|
|
@ -192,7 +193,7 @@
|
|||
<div style="flex:0 0 190px; min-width:170px">
|
||||
<div class="display">
|
||||
<div class="big" id="bpmDisplay">120</div>
|
||||
<div class="dtimers">
|
||||
<div class="dtimers" id="dtimers">
|
||||
<span title="elapsed (stopwatch)">⏱ <span id="elapsedVal">0:00</span></span>
|
||||
<span id="countWrap" title="countdown" hidden>⏳ <span id="countVal" class="tval">0:00</span></span>
|
||||
</div>
|
||||
|
|
@ -228,8 +229,8 @@
|
|||
<label style="font-size:12px">every <input type="number" class="num" id="rampEvery" min="1" max="16" value="4"> bars</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fbox" id="timerBox">
|
||||
<div class="fhead"><span class="ftitle">Timers</span><span class="hint" style="margin:0">run while playing</span></div>
|
||||
<div class="fbox toggleable" id="timerBox">
|
||||
<label class="fhead"><input type="checkbox" id="timersOn"><span class="ftitle">Timers</span><span class="hint" style="margin:0">run while playing</span></label>
|
||||
<div class="fbody">
|
||||
<div class="row" style="gap:10px; align-items:center">
|
||||
<label style="font-size:12px">Elapsed (stopwatch)</label>
|
||||
|
|
@ -649,7 +650,7 @@ function renderLaneStrip(m) {
|
|||
/* =========================================================================
|
||||
PRESETS (localStorage)
|
||||
========================================================================= */
|
||||
const LS = { presets: "metronome.presets", setlists: "metronome.setlists", logs: "metronome.logs", seeded: "metronome.seeded", continue: "metronome.continue" };
|
||||
const LS = { presets: "metronome.presets", setlists: "metronome.setlists", logs: "metronome.logs", seeded: "metronome.seeded", continue: "metronome.continue", timers: "metronome.timers" };
|
||||
function lsGet(k, fb) { try { const v = localStorage.getItem(k); return v ? JSON.parse(v) : fb; } catch (e) { return fb; } }
|
||||
function lsSet(k, v) { try { localStorage.setItem(k, JSON.stringify(v)); return true; } catch (e) { console.warn("localStorage unavailable", e); return false; } }
|
||||
|
||||
|
|
@ -676,6 +677,7 @@ let activeItem = -1; // selected / loaded item in the active set list
|
|||
let nowPlaying = null; // { at, name } for duration logging
|
||||
let historyName = null; // item whose past-session history is shown
|
||||
let continueMode = lsGet(LS.continue, false); // auto-advance to next item when countdown ends
|
||||
let timersOn = lsGet(LS.timers, true); // master switch for the elapsed/countdown timers
|
||||
|
||||
function currentSetup() { return { bpm: state.bpm, lanes: snapshotLanes(), trainer: { ...trainer }, ramp: { ...ramp }, countMs: timers.totalMs }; }
|
||||
function applySetup(s) {
|
||||
|
|
@ -694,6 +696,7 @@ function syncPracticeUI() {
|
|||
function refreshFeatureBoxes() {
|
||||
$("trainerBox").classList.toggle("on", trainer.on);
|
||||
$("rampBox").classList.toggle("on", ramp.on);
|
||||
$("timerBox").classList.toggle("on", timersOn);
|
||||
}
|
||||
function fmtDur(sec) { sec = Math.round(sec); const m = Math.floor(sec / 60); return m + ":" + String(sec % 60).padStart(2, "0"); }
|
||||
function getSL() { return setlists[activeSL]; }
|
||||
|
|
@ -996,7 +999,7 @@ function tickTimers() {
|
|||
const now = Date.now();
|
||||
const dt = timers.last ? Math.min(now - timers.last, 1000) : 0; // clamp so backgrounded gaps don't jump
|
||||
timers.last = now;
|
||||
if (state.running) {
|
||||
if (timersOn && state.running) {
|
||||
timers.elapsedMs += dt;
|
||||
if (timers.totalMs > 0) {
|
||||
const before = timers.remainingMs;
|
||||
|
|
@ -1011,6 +1014,8 @@ function tickTimers() {
|
|||
renderTimers();
|
||||
}
|
||||
function renderTimers() {
|
||||
$("dtimers").hidden = !timersOn;
|
||||
if (!timersOn) return;
|
||||
$("elapsedVal").textContent = fmtClock(timers.elapsedMs);
|
||||
const off = timers.totalMs <= 0;
|
||||
$("countWrap").hidden = off; // hide countdown when off
|
||||
|
|
@ -1090,6 +1095,7 @@ $("countTime").addEventListener("input", (e) => { timers.totalMs = parseTime(e.t
|
|||
$("elapsedReset").addEventListener("click", () => { timers.elapsedMs = 0; renderTimers(); });
|
||||
$("countReset").addEventListener("click", () => { timers.remainingMs = timers.totalMs; renderTimers(); });
|
||||
$("continueMode").addEventListener("change", (e) => { continueMode = e.target.checked; lsSet(LS.continue, continueMode); });
|
||||
$("timersOn").addEventListener("change", (e) => { timersOn = e.target.checked; lsSet(LS.timers, timersOn); refreshFeatureBoxes(); renderTimers(); });
|
||||
$("trayMenuBtn").addEventListener("click", (e) => { e.stopPropagation(); $("trayMenu").hidden = !$("trayMenu").hidden; });
|
||||
document.addEventListener("click", (e) => { const m = $("trayMenu"); if (m && !m.hidden && !m.contains(e.target) && e.target.id !== "trayMenuBtn") m.hidden = true; });
|
||||
$("newSetlistBtn").addEventListener("click", newSetlist);
|
||||
|
|
@ -1155,6 +1161,7 @@ renderLog();
|
|||
updateCtx();
|
||||
refreshFeatureBoxes();
|
||||
$("continueMode").checked = continueMode;
|
||||
$("timersOn").checked = timersOn;
|
||||
$("appVersion").textContent = "v" + APP_VERSION;
|
||||
requestAnimationFrame(drawLoop);
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue