← Commit history

Dashboard 1.0.119: the recording is an inline thumbnail with a play button under Play the demo; native controls, fullscreen via Hydrogen

John Lauer ·c992619f78 ·1mo ago ·parent fa68bf4
2 files changed +25−49
dashboard/ui/index.html+24−48
@@ -321,15 +321,13 @@ main a:hover{border-bottom-color:var(--accent)} .note{font-size:12.5px;color:var(--text-2);margin:-6px 0 12px} .wins{font:12.5px 'JetBrains Mono',monospace;color:var(--text-2)} -/* ── recorded tour lightbox (John, 2026-09-05) ─────────────────────────── */-.anp-video{margin-left:8px;}-#vidBox{display:none;position:fixed;inset:0;z-index:9000;background:rgba(6,9,14,.94);flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:16px;}-#vidBox .vb-bar{display:flex;align-items:center;gap:10px;width:min(96vw,1400px);color:#c9d3df;font-size:14px;}-#vidBox .vb-sp{flex:1;}-#vidBox .vb-bar button{background:#161b22;color:#e6edf3;border:1px solid #2a3341;border-radius:8px;padding:6px 10px;cursor:pointer;font-size:13px;}-#vidBox .vb-bar button:hover{border-color:#2dd4bf;}-#vidBox video{width:min(96vw,1400px);max-height:calc(100vh - 80px);background:#000;border-radius:10px;outline:none;}-#vidBox:fullscreen{padding:24px;} #vidBox:fullscreen video{width:min(96vw,1800px);max-height:calc(100vh - 90px);}+/* ── inline demo recording (John, 2026-09-05) ─────────────────────────── */+.demo-clip{position:relative;margin-top:10px;width:min(100%,360px);border-radius:10px;overflow:hidden;background:#000;border:1px solid #2a3341;}+.demo-clip video{display:block;width:100%;aspect-ratio:16/9;background:#000;}+.demo-clip .clip-play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:56px;height:56px;border-radius:50%;border:0;background:rgba(45,212,191,.92);color:#04121a;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 18px rgba(0,0,0,.45);}+.demo-clip .clip-play:hover{background:#2dd4bf;transform:translate(-50%,-50%) scale(1.06);}+.demo-clip .clip-cap{position:absolute;left:0;right:0;bottom:0;padding:22px 10px 8px;font-size:12px;color:#e6edf3;background:linear-gradient(transparent,rgba(0,0,0,.75));pointer-events:none;}+.demo-clip.playing .clip-play,.demo-clip.playing .clip-cap{display:none;} </style> </head> <body>@@ -643,48 +641,26 @@ function doMount(phrases){   });   mountVideo(); }-// ── the recorded tour, right in the newbie panel (John, 2026-09-05) ─────────-// The recording starts at the Play click (the viewer is already in this-// dashboard, so no dock-bar or dashboard explanation). Plays in a lightbox that-// fills this webview; the fullscreen button asks the host for real fullscreen,-// which works when the hosting iframe allows it and otherwise keeps the lightbox.+// ── the recorded tour, inline in the newbie panel (John, 2026-09-05) ───────+// A small thumbnail with a play button under the demo button; it plays right+// there, and the player's own fullscreen control hands off to Hydrogen, whose+// WebView2 grows the webview to 90% of the window on the standard Fullscreen API. const DEMO_VIDEO_URL='https://wiki.adom.inc/api/pages/adom/kicad-bridge/files/docs/videos/kicad-demo-tour.mp4';+const DEMO_VIDEO_POSTER='https://wiki.adom.inc/api/pages/adom/kicad-bridge/files/docs/videos/kicad-demo-tour-poster.jpg'; function mountVideo(){-  const demoBtn=document.querySelector('#newbie .anp-demo'); if(!demoBtn||document.getElementById('btnVideo'))return;-  const b=document.createElement('button'); b.type='button'; b.id='btnVideo'; b.className='anp-demo anp-video';-  b.innerHTML='<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M10 9l5 3-5 3z"/></svg><span>Watch the recording</span>';-  b.title='The same six views, recorded on a real desktop (2 min 50 s)';-  b.addEventListener('click',openVideo);-  demoBtn.insertAdjacentElement('afterend',b);+  const demoBtn=document.querySelector('#newbie .anp-demo'); if(!demoBtn||document.getElementById('demoClip'))return;+  const col=demoBtn.parentElement;+  const wrap=document.createElement('div'); wrap.id='demoClip'; wrap.className='demo-clip';+  wrap.innerHTML='<video id="demoVideo" poster="'+DEMO_VIDEO_POSTER+'" preload="none" playsinline controls controlslist="nodownload"></video>'++    '<button type="button" class="clip-play" aria-label="Play the recording"><svg viewBox="0 0 24 24" width="28" height="28" fill="currentColor"><path d="M8 5v14l11-7z"/></svg></button>'++    '<div class="clip-cap">The demo, recorded (2:51)</div>';+  col.appendChild(wrap);+  const v=wrap.querySelector('video'), play=wrap.querySelector('.clip-play');+  play.addEventListener('click',()=>{ if(!v.src){ v.src=DEMO_VIDEO_URL; } wrap.classList.add('playing'); v.play().catch(()=>{}); });+  v.addEventListener('pause',()=>{ if(!document.fullscreenElement) wrap.classList.remove('playing'); });+  v.addEventListener('play',()=>wrap.classList.add('playing'));+  v.addEventListener('ended',()=>{ wrap.classList.remove('playing'); }); }-function openVideo(){-  // Hydrogen Desktop's WebView2 implements the standard Fullscreen API by growing-  // the webview to 90% of the HD window (the shotlog lightbox relies on it). The-  // request must run straight from the click (no await before it) or the gesture-  // is lost; the fixed overlay is the fallback when the host refuses.-  let box=document.getElementById('vidBox');-  if(!box){-    box=document.createElement('div'); box.id='vidBox';-    box.innerHTML='<div class="vb-bar"><span>KiCad Bridge demo, recorded</span><span class="vb-sp"></span>'+-      '<button type="button" id="vbFull" title="Fullscreen">&#x26F6; Fullscreen</button><button type="button" id="vbClose" title="Close">&#x2715;</button></div>'+-      '<video id="vbVideo" controls autoplay playsinline preload="metadata"></video>';-    document.body.appendChild(box);-    box.querySelector('#vbClose').addEventListener('click',closeVideo);-    box.addEventListener('click',e=>{ if(e.target===box) closeVideo(); });-    box.querySelector('#vbFull').addEventListener('click',()=>{ goFull(box); });-    document.addEventListener('keydown',e=>{ if(e.key==='Escape'&&box.style.display!=='none'&&!document.fullscreenElement) closeVideo(); });-    document.addEventListener('fullscreenchange',()=>{ if(!document.fullscreenElement&&box.dataset.wasFull==='1'){ box.dataset.wasFull=''; closeVideo(); } });-  }-  const v=box.querySelector('#vbVideo'); v.src=DEMO_VIDEO_URL; box.style.display='flex';-  goFull(box);-  v.play().catch(()=>{});-}-function goFull(box){-  try{-    if(box.requestFullscreen){ box.dataset.wasFull='1'; box.requestFullscreen().catch(()=>{ box.dataset.wasFull=''; }); }-  }catch(e){ box.dataset.wasFull=''; }-}-function closeVideo(){ const box=document.getElementById('vidBox'); if(!box)return; const v=box.querySelector('#vbVideo'); v.pause(); v.removeAttribute('src'); v.load(); box.style.display='none'; } // Guided demo with a REAL progress bar + the stepShot stream (one screenshot per finished beat). async function startDemo(){   toast(demoMuted()?'starting the guided demo MUTED (narration off): click the speaker on the pill or the remote to unmute':'starting the guided demo');
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "kicad-bridge",-  "version": "1.0.118",+  "version": "1.0.119",   "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": [