diff --git a/settings/ui/app.js b/settings/ui/app.js
index 25c77d4..9ba7ac4 100644
--- a/settings/ui/app.js
+++ b/settings/ui/app.js
@@ -746,9 +746,9 @@
name${hint("As the keys say it")}
` + fieldsHtml("Spotify");
}
function autofixHtml(c) {
- const fixes = Object.entries(c.fixes).map(([id, f]) => { const cl = closes(f); const on = (c.auto_fix.fixes || []).includes(id); return ` ${esc(f.short || id)} `; }).join(" ");
+ const fixes = Object.entries(c.fixes).map(([id, f]) => { const cl = closes(f); const on = (c.auto_fix.fixes || []).includes(id); return ` ${esc(f.short || id)}${cl || f.restart_ok ? " ⚠" : ""} `; }).join(" ");
return `${calendarHtml("auto_fix.windows", c.auto_fix.windows)}
- Fixes it may run${hint("Gentle ones only: a fix that closes a program is never run by itself")} ${fixes}
` + fieldsHtml("Schedules");
+ Fixes it may run${hint("Ticked fixes run by themselves inside the painted hours. ⚠ = it closes a running program to do its job; ticking it allows that without a hold.")} ${fixes}
` + fieldsHtml("Schedules");
}
// --- the weekly calendar: half-hour cells; click or drag to paint ---
const DAYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
@@ -776,10 +776,11 @@
}
function calendarHtml(path, windows) {
const on = cellsOf(windows);
- let grid = `
` + DAYS.map((d) => `${d[0].toUpperCase() + d.slice(1)}
`).join("");
+ const SHOW = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
+ let grid = `
` + SHOW.map((d) => `${d[0].toUpperCase() + d.slice(1)}
`).join("");
for (let m = 0; m < 1440; m += 30) {
grid += `${m % 120 === 0 ? toHHMM(m) : ""}
`;
- for (let d = 0; d < 7; d++) grid += `
`;
+ for (const name of SHOW) { const d = DAYS.indexOf(name); grid += `
`; }
}
const words = (windows || []).length ? (windows || []).map((w) => `${(w.days || []).map((d) => d[0].toUpperCase() + d.slice(1)).join(", ")} ${esc(w.start)}–${esc(w.end)}`).join(" · ") : "never";
return `${grid}
${words} ${editing() ? " Click or drag to paint; drag over painted cells to clear." : ""}
`;
@@ -889,7 +890,7 @@
for (const b of main.querySelectorAll("[data-job]")) b.onclick = () => job(b.dataset.job);
for (const m of main.querySelectorAll("[data-map]")) m.onchange = () => { if (!m.value || !ensureDraft()) return; const [kind, name] = m.dataset.map.split("|"); (kind === "conn" ? renameConn : renameDante)(name, m.value); saveDraft(); route(); };
for (const b of main.querySelectorAll("[data-addconn]")) b.onclick = () => { const conn = b.dataset.addconn; if (!ensureDraft()) return; const d = state.draft.config; let id = slug(conn) || "key", n = 2; while (d.tiles.some((t) => t.id === id)) id = slug(conn) + "_" + n++; const t = { id, label: conn.toUpperCase().replace(/[_-]+/g, " ").slice(0, 10).trim(), checks: [{ type: "conn", conn, fix: "restart-connection" }] }; const pos = firstEmpty(d, "status"); if (pos) t.pos = pos; d.tiles.push(t); saveDraft(); location.hash = "#keys/" + id; };
- for (const cb of main.querySelectorAll("[data-autofix]")) cb.onchange = () => { if (!ensureDraft()) return; const set = new Set(state.draft.config.auto_fix.fixes || []); cb.checked ? set.add(cb.dataset.autofix) : set.delete(cb.dataset.autofix); setPath("auto_fix.fixes", [...set]); };
+ for (const cb of main.querySelectorAll("[data-autofix]")) cb.onchange = () => { if (!ensureDraft()) return; const d = state.draft.config, id = cb.dataset.autofix, f = d.fixes[id]; const set = new Set(d.auto_fix.fixes || []); if (cb.checked) { set.add(id); if (closes(f)) f.restart_ok = true; if (f.never_auto) delete f.never_auto; } else set.delete(id); setPath("auto_fix.fixes", [...set]); };
for (const b of main.querySelectorAll("[data-rmcheck]")) b.onclick = () => confirmBox("Remove this MIDI link from its key?", "Remove", () => { if (!ensureDraft()) return; const [tid, j] = b.dataset.rmcheck.split("|"); const t = state.draft.config.tiles.find((x) => x.id === tid); t.checks.splice(+j, 1); saveDraft(); route(); });
const ds = q("#decksave"); if (ds) ds.onclick = () => applyDecks(main);
const dc = () => danteCheck(state.draft.config);