diff options
Diffstat (limited to 'docs/prototypes/2026-07-02-desktop-settings-panel-prototype-10.html')
| -rw-r--r-- | docs/prototypes/2026-07-02-desktop-settings-panel-prototype-10.html | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/docs/prototypes/2026-07-02-desktop-settings-panel-prototype-10.html b/docs/prototypes/2026-07-02-desktop-settings-panel-prototype-10.html new file mode 100644 index 0000000..ea26651 --- /dev/null +++ b/docs/prototypes/2026-07-02-desktop-settings-panel-prototype-10.html @@ -0,0 +1,194 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1"> +<title>Desktop Settings — Prototype 10 (spacecraft DSKY, Dupre Kit)</title> +<link rel="stylesheet" href="desktop-settings-shared.css"> +<style> + :root{ + --ground:#151311; --panel:#100f0f; --well:#0a0c0d; --raise:#1a1917; + --silver:#bfc4d0; --cream:#f3e7c5; --steel:#969385; --dim:#7c838a; + --slate:#424f5e; --slate-hi:#54677d; --wash:#2c2f32; + --pass:#74932f; --fail:#cb6b4d; + --phos:#7fe0a0; --phos-dim:#1c3626; --vfd:#63e6c8; + --sevgrn:#57d357; --sevred:#e2543f; --sevoff:#1a1613; + --jewel-r:#ff5b45; --jewel-a:#ffb43a; --jewel-g:#6fce33; + --gold:#e2a038; --gold-hi:#ffbe54; + --amber-grad-top:#f2c76a; --amber-grad-mid:#d29638; --amber-grad-bot:#8f671f; + --amber-edge:#7d5c16; --amber-warn:#f0b552; + --glow-hi:255,190,84; --glow-lo:226,160,56; + --mono:"BerkeleyMono Nerd Font","Berkeley Mono",monospace; + --pulse-rate:1s; + } + .row { display: flex; justify-content: center; align-items: flex-start; gap: 10px; flex-wrap: wrap; } + .dupre-rotsel, .dupre-keylock { display: inline-block; } + .cellcap { color: var(--steel); font-size: 8.5px; letter-spacing: 0.1em; text-align: center; margin-top: 3px; text-transform: uppercase; } + .swgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; } + .swcell { display: flex; flex-direction: column; align-items: center; gap: 2px; } + .caution-well { pointer-events: none; } + .verbcard { color: var(--dim); font-size: 9px; line-height: 1.5; text-align: center; } + .verbcard b { color: var(--gold); font-weight: 400; } +</style> +</head> +<body class="ds-stage"> + <div class="ds-caption"> + <b>Direction 10 — Spacecraft DSKY (Dupre Kit).</b> The THUMB SLIDE + attenuator (drag the tabs) sets both levels. Toggles are slide switches + under a live caution board (amber cell = engaged). Scenes are commanded on + the DSKY: key VERB, two digits, ENTR. Power is the keyed mode switch. + </div> + + <div class="ds-bar"><span>19:24</span><span class="gear">⚙</span></div> + + <div class="ds-panel" id="panel"> + <div class="ds-face"> + <span class="glyph">⚙</span> + <span class="title">Settings</span> + <span class="sub" id="scene-sub"></span> + <span class="x">✕</span> + </div> + <div id="body"></div> + <div class="ds-toast" id="toast"></div> + <div class="ds-subview" id="subview"></div> + </div> + +<script src="widgets.js"></script> +<script src="desktop-settings-shared.js"></script> +<script> +const h = DS.h; +const body = document.getElementById("body"); +const subview = document.getElementById("subview"); +DS.bindToast(document.getElementById("toast")); + +const SCENES = Object.keys(DS.SCENES); +const TOGGLES = [ + ["autodim", "DIM"], ["caffeine", "CAFF"], ["touchpad", "TPAD"], ["mouse", "MOUSE"], + ["nightlight", "NIGHT"], ["dnd", "DND"], ["weathergeo", "WXGEO"], ["airplane", "AIR"], +]; +let booting = true; + +function openWallpaper() { + subview.innerHTML = ""; + subview.appendChild(DS.wallpaperSubview(() => subview.classList.remove("open"))); + subview.classList.add("open"); +} + +function sceneOff() { + DS.state.scene = null; + DS.toast("Scene: off", true); + render(); +} + +const debounce = (fn, ms) => { let t; return (...a) => { clearTimeout(t); t = setTimeout(() => fn(...a), ms); }; }; + +function render() { + booting = true; + body.innerHTML = ""; + const col = h("div", "ds-col"); + const rows = TOGGLES.filter(([k]) => k !== "airplane" || DS.state.laptop); + + // Caution board: display-only mirror of the toggle states (amber = on). + col.appendChild(DS.engrave("Caution board")); + const annWell = h("div", "caution-well"); + DUPRE.annunciator(annWell, { + cells: rows.map(([k, label]) => [label, DS.state[k] ? 1 : 0]), + }); + const bar = annWell.querySelector(".dupre-annbar"); + if (bar) bar.style.display = "none"; + col.appendChild(annWell); + + // Toggle switches: one slide switch per system. + col.appendChild(DS.engrave("Systems")); + const grid = h("div", "swgrid"); + rows.forEach(([k, label]) => { + const cell = h("div", "swcell"); + const host = h("div"); + DUPRE.slideToggle(host, { + on: DS.state[k], + preset: k === "airplane" ? "armed" : "panel", + onChange: (on) => { if (!booting && on !== DS.state[k]) DS.setToggle(k, cell); }, + }); + cell.appendChild(host); + cell.appendChild(h("div", "cellcap", label)); + grid.appendChild(cell); + }); + col.appendChild(grid); + + // Levels: the thumb-slide attenuator (Craig favorite #2). + col.appendChild(DS.engrave("Levels")); + const lvRow = h("div", "row"); + const tsHost = h("div"); + const commit = debounce((vals) => { + if (vals[0] !== DS.state.brightness) DS.setSlider("brightness", vals[0], tsHost); + if (vals[1] !== DS.state.kbd) DS.setSlider("kbd", vals[1], tsHost); + }, 350); + DUPRE.thumbSlide(tsHost, { + channels: [ + { name: "BRIGHT", v: DS.state.brightness }, + { name: "KBD", v: DS.state.kbd }, + ], + onChange: (vals) => { if (!booting) commit(vals.slice()); }, + }); + lvRow.appendChild(tsHost); + col.appendChild(lvRow); + + // Scenes: commanded through the DSKY verb grammar. + col.appendChild(DS.engrave("Command — scenes")); + const dHost = h("div"); + DUPRE.dsky(dHost, { + onChange: (vals, label) => { + if (booting) return; + const m = /^V(\d\d) ENTR$/.exec(label); + if (!m) return; + const code = +m[1]; + if (code === 0) sceneOff(); + else if (code >= 1 && code <= 4) DS.applyScene(SCENES[code - 1], dHost); + else DS.toast("V" + m[1] + ": no such program", false); + }, + }); + col.appendChild(dHost); + const card = h("div", "verbcard"); + card.innerHTML = + "<b>V01</b> FOCUS · <b>V02</b> PRESENTATION · <b>V03</b> BATTERY · <b>V04</b> NIGHT<br>" + + "<b>V00</b> scene off · <b>V35</b> lamp test"; + col.appendChild(card); + + // Power: keyed mode switch. + col.appendChild(DS.engrave("Power mode")); + const pRow = h("div", "row"); + const kHost = h("div"); + DUPRE.keySwitch(kHost, { + items: ["PERF", "BAL", "SAVER"], + index: DS.PROFILES.findIndex((p) => p.id === DS.state.powerprofile), + onChange: (i) => { if (!booting) DS.setProfile(DS.PROFILES[i].id, kHost); }, + }); + pRow.appendChild(kHost); + col.appendChild(pRow); + + // Actions: arm-to-fire. + col.appendChild(DS.engrave("Actions")); + const aRow = h("div", "row"); + [["LOCK", () => DS.momentary("Lock")], + ["SUSPEND", () => DS.momentary("Suspend")], + ["WALLPAPER", openWallpaper]].forEach(([label, fn]) => { + const host = h("div"); + DUPRE.armButton(host, { + label, + armLabel: label + "?", + onChange: (st) => { if (!booting && st === "fired") fn(); }, + }); + aRow.appendChild(host); + }); + col.appendChild(aRow); + + body.appendChild(col); + document.getElementById("scene-sub").textContent = DS.state.scene ? "▶ " + DS.state.scene : ""; + booting = false; +} + +DS.onChange(render); +render(); +</script> +</body> +</html> |
