← Commit history

The Settings preview becomes six mini-taskbar rows over ONE fixed sample set of live windows, so every state renders the exact same windows apples-to-apples: name tiles per thread with real badges, per-window registered icons, and the actual Chrome icon for plain, each row click-switchable with the current state highlighted.

John Lauer ·bc810603bd ·2mo ago ·parent cca912a
4 files changed +54−91
adom-bridge-puppeteer-manifest.json+4−4
@@ -1,10 +1,10 @@ {   "manifest_version": 1,   "name": "puppeteer",-  "version": "2.0.202",-  "url": "https://wiki.adom.inc/download/adom/pup-bridge/2.0.202/adom-bridge-puppeteer-v2.0.202.zip",-  "sha256": "ad657873e6df523380bcb2c6e5d41c2c7350f9f11060cf4eab5f07919e9c1b00",-  "size": 927908,+  "version": "2.0.203",+  "url": "https://wiki.adom.inc/download/adom/pup-bridge/2.0.203/adom-bridge-puppeteer-v2.0.203.zip",+  "sha256": "6677a5929f07004cb9389fc121ac459b8fc671cd90ac8f4913a144976424f464",+  "size": 927180,   "verbPrefixes": [     "browser_",     "desktop_recorder_",
src/BRIDGE_VERSION+1−1
@@ -1 +1 @@-2.0.202+2.0.203
src/bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "puppeteer",   "displayName": "Puppeteer (Chrome for Testing + Native)",-  "version": "2.0.202",+  "version": "2.0.203",   "description": "Drives a browser ALREADY on the machine \u2014 installed Chrome, else Microsoft Edge (every Windows PC ships with Edge) \u2014 launched with a FRESH isolated profile, so the common case has NO ~150 MB Chrome-for-Testing download and it never touches the user's real tabs/logins. Binds its local server to LOOPBACK (127.0.0.1) only, so no Windows Firewall 'allow Node through the firewall' prompt ever pops. Chrome for Testing is fetched only as a LAST RESORT if the machine has no Chromium browser at all. SPAWN-VERIFIED fallback: pup tries each detected browser (Chrome \u2192 Edge \u2192 CfT) and actually launches it, falling through to the next if one won't start (and handling browsers like Edge that relaunch onto another PID), so a corrupt/partial install never hard-fails an open. The browser that launches is cached as the default (persisted across restarts) so it isn't re-probed each time. On spawn the bridge SELF-WARMS: detects browsers + disk, and only if the box has no Chrome/Edge and no cached CfT does it background-fetch CfT so the first open is instant. pup_use pins a specific browser (chrome | edge | cft | auto); {browser:'chrome',install:true} downloads & installs REAL Google Chrome (user-scoped, no admin) on an Edge-only box. pup_readiness (READ-ONLY) reports which browser will be used + the full candidate list + the default + free disk. Every failure returns a specific errorCode + _hint (chrome_install_no_disk, chrome_download_network, chrome_install_permission, chrome_stable_not_detected, \u2026). Launches with FULL browser permissions by default for full debug (strictPermissions:true opts out). Headful automation: open/close windows+tabs, navigate, screenshot, eval JS, record. pup is a GENERIC, non-profile browser only \u2014 every session is a fresh isolated Chrome/Edge process, never the user's real signed-in browser; profile defaults to sessionId. To drive the user's REAL Chrome/Edge (their profile, cookies, SSO), use the Adom browser EXTENSION's nbrowser_* verbs \u2014 a separate bridge, not pup's job. macOS (v1.9.74+): full parity with mac-native mechanics \u2014 background-by-default is the app-level hide (windows stay drivable/screenshottable while hidden), raise/lower map to unhide+activate/hide, pup_alert_window posts a native toast whose click focuses the window, pup_use {browser:'chrome',install:true} installs Chrome from the official dmg, and taskbar identity/badging remains Windows-only.",   "homepage": "https://wiki.adom.inc/adom/adom-bridge",   "author": "Adom Inc.",
src/server.js+48−85
@@ -11383,6 +11383,12 @@ select,input{background:#111b23;color:#e6edf3;border:1px solid #23303c;border-ra .mic .mbadge{position:absolute;top:-7px;right:-7px;width:20px;height:20px;border-radius:5px} .texnames{display:flex;flex-wrap:wrap;gap:12px;padding-top:10px;border-top:1px solid #30363d} .texdim{opacity:.45}+.st6{display:flex;flex-direction:column;gap:8px}+.strow6{display:flex;align-items:center;gap:12px;padding:7px 10px;border:1px solid #30363d;border-radius:8px;cursor:pointer}+.strow6:hover{border-color:#8b949e}+.strow6.mcur{border-color:#00b8b1;box-shadow:0 0 0 1px #00b8b1 inset}+.stlbl{flex:0 0 175px;font:600 12px 'Familjen Grotesk',sans-serif;color:#c9d1d9}+.sticons{display:flex;gap:10px;flex-wrap:wrap;align-items:center} .srow{display:flex;align-items:flex-start;gap:12px;padding:11px 0;border-bottom:1px solid #21262d} .srow:last-child{border-bottom:none} .srow .stxt{flex:1 1 auto;min-width:0}@@ -11795,102 +11801,59 @@ function renderDlg(){ // so the strip always shows a range of name lengths. function paintThreadExamples(){   const strip=_q('#texstrip'); if(!strip) return;-  // v2.0.196 (John: "you are not showing TRUE icon states — why are you being lazy?"). He was-  // right: the cells were hand-drawn approximations, including the Adom-mark badge that 2.0.192-  // REMOVED from real badges. The preview is now DERIVED from the same sources as the taskbar:-  //   tiles base   = the real name-tile algorithm (drawNameTile, same code as the .ico renderer)-  //   aumid base   = /dashboard/stampicon (the REAL registered category icon for a live session)-  //   plain base   = /dashboard/baseicon  (the REAL browser exe icon)-  //   overlay      = /dashboard/badge     (the EXACT composed PNG Windows was handed)-  // Drawn fallbacks (mark-free) appear only when no live window exists to source from.+  // v2.0.203 (John: "show the EXACT SAME sample windows' taskbar icons for each of the 6 states").+  // The preview is now SIX MINI-TASKBAR ROWS over ONE fixed sample set (the live windows), so every+  // state is an apples-to-apples rendering of the same windows:+  //   tiles rows  -> one name tile per THREAD (real tile renderer) + that thread's real badge+  //   aumid rows  -> one icon per WINDOW (the actual registered icon via stampicon) + real badge+  //   plain rows  -> ONE stock Chrome button (actual exe icon) + one real badge when overlay is on+  // Rows highlight the CURRENT state, carry the default chip, and click-to-switch.   const st2=(SNAP&&SNAP.bridge&&SNAP.bridge.settings)||{};   const mode=st2.aumidIcons!=='on'?'plain':(st2.threadTiles==='on'?'tiles':'aumid');   const ovOn=st2.overlayBadges!=='off';-  const wins=(SNAP&&SNAP.windows)||[];-  const live=[]; const sidByOwner={};-  wins.forEach(function(w){const t=w.owner||w.ownerThread;const sid=w.sessionId||w.id;-    if(t&&live.indexOf(t)<0){live.push(t);} if(t&&sid&&!sidByOwner[t])sidByOwner[t]=sid;});-  const liveSid=wins.length?(wins[0].sessionId||wins[0].id||''):'';-  const sampleName=live[0]||'kicad';+  const wins=((SNAP&&SNAP.windows)||[]).filter(function(w){return (w.sessionId||w.id);});   const V='&v='+(typeof PAGE_VERSION!=='undefined'?PAGE_VERSION:'0');-  const cells=[];-  [true,false].forEach(function(ov){ ['tiles','aumid','plain'].forEach(function(m){ cells.push([m,ov]); }); });-  function baseHtml(m){-    if(m==='tiles') return '<canvas width="128" height="128" class="mbase" data-mtile="1"></canvas>';-    if(m==='aumid') return liveSid?'<img class="mbase" src="/dashboard/stampicon?session='+encodeURIComponent(liveSid)+V+'" data-fb="aumid">':'<canvas width="128" height="128" class="mbase" data-mfb="aumid"></canvas>';-    return '<img class="mbase" src="/dashboard/baseicon?profile=adom-you'+V+'" data-fb="plain">';-  }-  function badgeHtml(){-    // v2.0.201: bestbadge = the newest composed badge whose favicon is REAL — the matrix never-    // shows a blank or generic circle while any live window carries an accurate favicon badge.-    return '<img class="mbadge" src="/dashboard/bestbadge?'+V.slice(1)+'" data-fbb="1">';-  }-  var matrixHtml='<div class="texmatrix">'+cells.map(function(c,i){-    const m=c[0],ov=c[1];+  const threads=[]; const sidByOwner={};+  wins.forEach(function(w){const t=w.owner||w.ownerThread||'window';const sid=w.sessionId||w.id;+    if(threads.indexOf(t)<0)threads.push(t); if(!sidByOwner[t])sidByOwner[t]=sid;});+  function badge(sid){ return '<img class="mbadge" src="/dashboard/badge?session='+encodeURIComponent(sid)+V+'" data-fbb="1">'; }+  function tileIc(name,withBadge){ return '<span class="mic"><canvas width="128" height="128" data-tname="'+esc(name)+'"></canvas>'+(withBadge&&sidByOwner[name]?badge(sidByOwner[name]):'')+'</span>'; }+  function aumidIc(sid,withBadge){ return '<span class="mic"><img class="mbase" src="/dashboard/stampicon?session='+encodeURIComponent(sid)+V+'" data-fb="1">'+(withBadge?badge(sid):'')+'</span>'; }+  function plainIc(withBadge){ return '<span class="mic"><img class="mbase" src="/dashboard/baseicon?profile=adom-you'+V+'">'+(withBadge?'<img class="mbadge" src="/dashboard/bestbadge?'+V.slice(1)+'" data-fbb="1">':'')+'</span>'; }+  const states=[+    ['tiles',true, '1. tiles + overlay'],+    ['tiles',false,'2. tiles'],+    ['aumid',true, '3. aumid + overlay'],+    ['aumid',false,'4. aumid'],+    ['plain',true, '5. plain + overlay'],+    ['plain',false,'6. plain'],+  ];+  strip.innerHTML='<div class="st6">'+states.map(function(cfg,i){+    const m=cfg[0],ov=cfg[1],lbl=cfg[2];     const cur=(m===mode&&ov===ovOn);     const isDefault=(m==='tiles'&&ov);-    return '<div class="mcell'+(cur?' mcur':'')+'" data-mi="'+i+'" title="click to switch to this combination">'-      +(isDefault?'<span class="mdef">default</span>':'')-      +'<div class="mic">'+baseHtml(m)+(ov?badgeHtml():'')+'</div>'-      +'<span class="texn">'+m+(ov?' + overlay':'')+(cur?' (current)':'')+'</span></div>';+    let icons='';+    if(!wins.length){ icons='<span class="texn">(no live windows to sample — open a pup window and reopen Settings)</span>'; }+    else if(m==='tiles'){ icons=threads.map(function(t){return tileIc(t,ov);}).join(''); }+    else if(m==='aumid'){ icons=wins.map(function(w){return aumidIc(w.sessionId||w.id,ov);}).join(''); }+    else { icons=plainIc(ov); }+    return '<div class="strow6'+(cur?' mcur':'')+'" data-si="'+i+'" title="click to switch to this state">'+      +'<span class="stlbl">'+lbl+(cur?' (current)':'')+(isDefault?' <span class="mdef">default</span>':'')+'</span>'+      +'<div class="sticons">'+icons+'</div></div>';   }).join('')+'</div>';-  var namesHtml='';-  var names=[];-  if(mode==='tiles'){-    const fill=['kicad','nb','fusion','ah build','shotlog','adom-tts','pup bridge maintenance'];-    names=live.concat(fill.filter(function(f){return live.indexOf(f)<0;})).slice(0,8);-    // v2.0.202 (John: "your overlay icons are a lie — some anyway"): a thread with NO live window-    // used to get a drawn generic globe styled EXACTLY like the real composed badges — samples-    // masquerading as truth. Live threads keep their REAL badge; sample threads now render dimmed,-    // badge-less, and labeled "(sample)" so nothing in the strip claims more than it knows.-    namesHtml='<div class="texnames">'+names.map(function(n){-      const sid=sidByOwner[n];-      const badge=(ovOn&&sid)?'<img class="mbadge" src="/dashboard/badge?session='+encodeURIComponent(sid)+V+'" data-fbb="1">':'';-      const dim=sid?'':' texdim';-      const lbl=sid?esc(n):esc(n)+' (sample)';-      return '<div class="tex'+dim+'"><div class="mic"><canvas width="128" height="128" data-tname="'+esc(n)+'"></canvas>'+badge+'</div><span class="texn">'+lbl+'</span></div>';}).join('')+'</div>';-  }-  strip.innerHTML=matrixHtml+namesHtml;   const cap=strip.parentElement?strip.parentElement.querySelector('.texcap'):null;-  if(cap)cap.textContent='All six taskbar states, sourced from the REAL machinery: tiles are drawn by the same code as the actual .ico; the aumid and plain bases and every overlay badge are the actual images pup registered with Windows (live window: "'+(liveSid||'none open')+'"). Click any cell to switch to it.';-  strip.querySelectorAll('canvas[data-mtile]').forEach(function(cv){ drawNameTile(cv.getContext('2d'),128,sampleName); });+  if(cap)cap.textContent='The SAME sample windows rendered under every state: tiles rows show one name tile per thread (drawn by the real tile renderer) with that thread\u2019s real composed badge; aumid rows show each window\u2019s actual registered icon; plain rows show the actual Chrome-for-Testing icon. Badges are the exact PNGs pup handed Windows. Click a row to switch. Sampling '+wins.length+' live window(s) across '+threads.length+' thread(s).';   strip.querySelectorAll('canvas[data-tname]').forEach(function(cv){ drawNameTile(cv.getContext('2d'),128,cv.getAttribute('data-tname')); });-  strip.querySelectorAll('canvas[data-mfb="aumid"]').forEach(function(cv){-    const ctx=cv.getContext('2d'),box=128;-    rr(ctx,0,0,box,box,box*0.14,'#00b8b1');-    rr(ctx,box*0.18,box*0.18,box*0.64,box*0.64,box*0.1,'#053b38');-    ctx.strokeStyle='#7fe7e2';ctx.lineWidth=box*0.045;-    ctx.beginPath();ctx.arc(box/2,box/2,box*0.19,0,7);ctx.stroke();-  });-  strip.querySelectorAll('canvas[data-genb]').forEach(function(cv){-    // mark-free generic badge fallback: light card + gray globe, mirroring the compositor generic-    const ctx=cv.getContext('2d'),b=44;-    rr(ctx,0,0,b,b,b*0.16,'#f1f3f4');-    ctx.strokeStyle='#5f6368';ctx.lineWidth=2.6;-    ctx.beginPath();ctx.arc(b/2,b/2,b*0.28,0,7);ctx.stroke();-    ctx.beginPath();ctx.ellipse(b/2,b/2,b*0.12,b*0.28,0,0,7);ctx.stroke();-    ctx.beginPath();ctx.moveTo(b*0.22,b/2);ctx.lineTo(b*0.78,b/2);ctx.stroke();-  });-  // real-image fallbacks: a 1x1 transparent badge (no composed overlay yet) or a failed base image-  // falls back to the drawn stand-in so a cell is never empty   strip.querySelectorAll('img.mbadge[data-fbb]').forEach(function(im){-    im.onload=function(){ if(im.naturalWidth<=2){ swapGenB(im); } };-    im.onerror=function(){ swapGenB(im); };+    im.onload=function(){ if(im.naturalWidth<=2){ im.remove(); } };+    im.onerror=function(){ im.remove(); };   });-  function swapGenB(im){-    // full Chrome-style generic globe (card + circle + meridian + equator), not a bare ring-    const cv=document.createElement('canvas'); cv.width=44; cv.height=44; cv.className='mbadge';-    const ctx=cv.getContext('2d'),b=44;-    rr(ctx,0,0,b,b,b*0.16,'#f1f3f4');-    ctx.strokeStyle='#5f6368';ctx.lineWidth=2.6;-    ctx.beginPath();ctx.arc(b/2,b/2,b*0.28,0,7);ctx.stroke();-    ctx.beginPath();ctx.ellipse(b/2,b/2,b*0.12,b*0.28,0,0,7);ctx.stroke();-    ctx.beginPath();ctx.moveTo(b*0.22,b/2);ctx.lineTo(b*0.78,b/2);ctx.stroke();-    im.replaceWith(cv);-  }-  strip.querySelectorAll('.mcell').forEach(function(cell,i){-    cell.onclick=function(){-      const c=cells[i];+  strip.querySelectorAll('img.mbase[data-fb]').forEach(function(im){+    im.onerror=function(){ im.style.display='none'; };+  });+  strip.querySelectorAll('.strow6').forEach(function(row,i){+    row.onclick=function(){+      const c=states[i];       setSetting('taskbarMode',c[0]);       setSetting('overlayBadges',c[1]?'on':'off');     };