← Commit history

1.0.115: demo pill follows the desktop remote (stop closes it with a toast, mute face mirrored), mute is session-only and announced on Play, toasts stack above the pill

John Lauer ·eef7a0097e ·1mo ago ·parent 1aba618
2 files changed +11−5
dashboard/ui/index.html+10−4
@@ -634,7 +634,7 @@ function doMount(phrases){ } // Guided demo with a REAL progress bar + the stepShot stream (one screenshot per finished beat). async function startDemo(){-  toast('starting the guided demo (background)');+  toast(demoMuted()?'starting the guided demo MUTED (narration off): click the speaker on the pill or the remote to unmute':'starting the guided demo');   $('#demoShots').innerHTML='';   const s=await act('demo',{muted:demoMuted()});const d=s.data||s;   if(d.success===false){toast('demo failed to start: '+(d.error||'unknown'),'err');return;}@@ -653,7 +653,11 @@ async function startDemo(){       c.innerHTML='<img src="data:image/png;base64,'+q.stepShot.image+'" alt="'+(q.stepShot.title||'')+'"><div class="cap">'+(q.stepShot.title||q.stepShot.step||'')+'</div>';       $('#demoShots').appendChild(c);     }-    if(q.done){clearInterval(poll);$('#demoToolbar').style.display='none';document.body.classList.remove('demo-running');toast(q.error?('demo failed: '+q.error):(q.result&&q.result.exited?'demo stopped':'demo complete'),'' + (q.error?'err':'ok'));refresh(true);}+    // Mirror the desktop remote: mute face, and a STOP (the remote's X) hides+    // this pill at once with a toast, before the bridge finishes the beat in flight.+    if(typeof q.muted==='boolean'){$('#dtMute').dataset.muted=q.muted?'1':'0';$('#dtMute').innerHTML=q.muted?'&#128263;':'&#128266;';}+    if(q.stopping&&!$('#demoToolbar').dataset.closing){$('#demoToolbar').dataset.closing='1';$('#demoToolbar').style.display='none';document.body.classList.remove('demo-running');toast('closing the demo tour','ok');}+    if(q.done){clearInterval(poll);$('#demoToolbar').style.display='none';document.body.classList.remove('demo-running');delete $('#demoToolbar').dataset.closing;toast(q.error?('demo failed: '+q.error):(q.result&&q.result.exited?'demo stopped':'demo complete'),'' + (q.error?'err':'ok'));refresh(true);}   },3000); } // Demo transport: mirrors the ab toast buttons; the bridge applies commands@@ -982,10 +986,12 @@ function maybeCountLaunch(st){  // ── dash-demo player: toolbar wiring ─────────────────────────────────────── const MUTE_KEY='kdDemoMuted';-function demoMuted(){try{return localStorage.getItem(MUTE_KEY)==='1'}catch(e){return false}}+// John, 2026-09-03: a mute remembered across sessions silently started every later tour without+// audio. Mute now lives for THIS page session only, and Play says so when it starts muted.+function demoMuted(){try{return sessionStorage.getItem(MUTE_KEY)==='1'}catch(e){return false}} function setMuteUI(){$('#dtMute').classList.toggle('muted',demoMuted());} $('#dtMute').onclick=async()=>{-  const m=!demoMuted();try{localStorage.setItem(MUTE_KEY,m?'1':'0')}catch(e){}+  const m=!demoMuted();try{sessionStorage.setItem(MUTE_KEY,m?'1':'0')}catch(e){}   setMuteUI();await act('demo_control',{cmd:m?'mute':'unmute'});   toast(m?'narration muted':'narration on','ok'); };
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "kicad-bridge",-  "version": "1.0.114",+  "version": "1.0.115",   "type": "app",   "description": "Skills for your container so your AI knows how to drive the KiCad bridge. The bridge runtime itself is the release zip; Adom Bridge loads that.",   "tags": [