← Commit history

Publish 0.13.2

John Lauer ·79ed675a35 ·3mo ago ·parent c702f1d
7 files changed +104−13
Cargo.lock+1−1
@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"  [[package]] name = "adom-shotlog"-version = "0.13.1"+version = "0.13.2" dependencies = [  "axum",  "base64",
Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "adom-shotlog"-version = "0.13.1"+version = "0.13.2" edition = "2021" description = "Screenshot log viewer and CLI for Adom" license = "MIT"
VERSION+1−1
@@ -1 +1 @@-0.13.1+0.13.2
bin/adom-shotlog
⋯ 1 unchanged line ⋯
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-shotlog",-  "version": "0.13.1",+  "version": "0.13.2",   "type": "app",   "title": "Adom Shotlog",   "description": "See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is really watching and on which surface, and ingests Adom Desktop child-window arrays via --meta.",
page.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-shotlog",-  "version": "0.13.1",+  "version": "0.13.2",   "type": "app",   "title": "Adom Shotlog",   "description": "See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is really watching and on which surface, and ingests Adom Desktop child-window arrays via --meta.",
src/html/index.html+99−8
@@ -65,22 +65,22 @@ img { max-width: 100%; }  /* Header (adom-app-header, 44px) */ header {-  display: flex; align-items: center; gap: 10px; padding: 0 12px; height: 44px;+  display: flex; align-items: center; gap: 12px; padding: 0 16px; height: 44px;   flex-shrink: 0; background: var(--surface); border-bottom: 1px solid var(--border-muted);   position: relative; }-.brand { display: flex; align-items: center; gap: 7px; color: var(--accent);+.brand { display: flex; align-items: center; gap: 8px; color: var(--accent);   font-family: 'Familjen Grotesk', sans-serif; font-size: 13px; font-weight: 600;   cursor: default; flex-shrink: 0; outline: none; } .brand:hover .app-name { text-decoration: underline; text-underline-offset: 3px; }-.brand svg.logo { width: 15px; height: 15px; flex-shrink: 0; color: var(--text); } /* monochrome per brand */+.brand svg.logo { width: 16px; height: 16px; flex-shrink: 0; color: var(--text); } /* monochrome per brand */ .brand .sep { color: var(--text3); font-weight: 400; margin: 0 1px; } .brand .app-subtitle { color: var(--text2); font-weight: 500; font-size: 12px; } .vsep { width: 1px; height: 16px; background: var(--border); flex-shrink: 0; }-.subject { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; }-.subject-name { font-family: 'Familjen Grotesk', sans-serif; font-size: 13px; font-weight: 600;+.subject { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }+.subject-name { font-family: 'Familjen Grotesk', sans-serif; font-size: 14px; font-weight: 600;   color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }-.subject-meta { color: var(--text3); font-family: 'JetBrains Mono', monospace; font-size: 10px;+.subject-meta { color: var(--text2); font-family: 'JetBrains Mono', monospace; font-size: 11px;   white-space: nowrap; flex-shrink: 0; } /* Canonical adom-app-header: the header is ALWAYS ONE 44px row (multi-row is    anti-pattern #1 in the adom-app-header spec). To fit a skinny ~360px panel we@@ -245,6 +245,38 @@ header {   box-shadow: 0 8px 28px rgba(0,0,0,.5); } .toast.show { opacity: 1; } +/* In-app helper dialog (e.g. "pup needs Adom Desktop") - NEVER a native+   alert/confirm. Backdrop + card, dismiss via X / backdrop / Esc. */+.helper { position: fixed; inset: 0; background: rgba(0,0,0,.72); display: none;+  align-items: center; justify-content: center; z-index: 400; padding: 14px; }+.helper.open { display: flex; }+.helper-card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px;+  padding: 16px 18px 15px; width: 100%; max-width: 440px; max-height: calc(100dvh - 28px);+  overflow-y: auto; box-shadow: 0 12px 40px rgba(0,0,0,.6); position: relative; }+.helper-card .h-close { position: absolute; top: 10px; right: 10px; width: 26px; height: 26px;+  display: flex; align-items: center; justify-content: center; border-radius: 6px;+  color: var(--text3); cursor: pointer; border: none; background: transparent; font-size: 15px; }+.helper-card .h-close:hover { background: var(--overlay); color: var(--text); }+.helper-card .h-title { font: 700 15px 'Familjen Grotesk', sans-serif; color: var(--text);+  margin-bottom: 8px; padding-right: 28px; }+.helper-card .h-body { font: 13px/1.55 'Satoshi', sans-serif; color: var(--text2); margin-bottom: 12px; }+.helper-card .h-lbl { font: 600 9.5px 'Satoshi', sans-serif; letter-spacing: .05em;+  text-transform: uppercase; color: var(--text3); margin: 0 0 5px; }+.helper-card .h-prompt { background: rgba(0,184,176,.08); border: 1px solid rgba(0,184,176,.3);+  border-radius: 8px; padding: 10px 12px; font-family: 'JetBrains Mono', monospace;+  font-size: 11.5px; line-height: 1.5; color: var(--accent-bright); user-select: all;+  word-break: break-word; }+.helper-card .h-actions { display: flex; gap: 8px; margin-top: 12px; align-items: center; flex-wrap: wrap; }+.helper-card .h-btn { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 13px;+  border-radius: 7px; font: 600 12px 'Familjen Grotesk', sans-serif; cursor: pointer;+  border: 1px solid rgba(0,184,176,.4); background: rgba(0,184,176,.12); color: var(--accent-bright); }+.helper-card .h-btn:hover { background: rgba(0,184,176,.2); }+.helper-card .h-btn.secondary { border-color: var(--border); background: var(--overlay); color: var(--text2); }+.helper-card .h-btn.secondary:hover { color: var(--text); }+.helper-card .h-link { color: var(--accent); font: 600 12px 'Familjen Grotesk', sans-serif;+  text-decoration: none; margin-left: auto; }+.helper-card .h-link:hover { text-decoration: underline; }+ /* Paste progress overlay */ .paste-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.7); display: none;   align-items: center; justify-content: center; z-index: 150; }@@ -296,6 +328,20 @@ header {  <div class="feed" id="feed"><div class="empty">loading…</div></div> +<div class="helper" id="pupHelp" role="dialog" aria-modal="true" aria-label="Pup setup help">+  <div class="helper-card">+    <button class="h-close" id="pupHelpClose" data-tooltip="Close">✕</button>+    <div class="h-title" id="pupHelpTitle">Pup needs Adom Desktop</div>+    <div class="h-body" id="pupHelpBody"></div>+    <div class="h-lbl">copy this prompt into any AI thread and it will fix it for you</div>+    <div class="h-prompt" id="pupHelpPrompt"></div>+    <div class="h-actions">+      <button class="h-btn" id="pupHelpCopy">⧉ Copy prompt</button>+      <button class="h-btn secondary" id="pupHelpDismiss">Close</button>+      <a class="h-link" href="https://wiki.adom.inc/adom/adom-desktop" target="_blank" rel="noopener">Adom Desktop wiki ↗</a>+    </div>+  </div>+</div> <div class="toast" id="toast"></div> <div class="modal" id="modal"><div class="modal-card" id="modalCard">   <div class="m-desc" id="mDesc"></div><div class="m-meta" id="mMeta"></div><img id="mImg" alt="">@@ -644,9 +690,9 @@ header {           busy('checking pup…');           const sim=new URLSearchParams(location.search).get('simulate');           const chk = sim==='no-pup'-            ? {available:false, hint:'(simulated) pup needs Adom Desktop. Install it on your computer from wiki.adom.inc/adom/adom-desktop - the pup bridge is a default bridge that auto-installs right after it.'}+            ? {available:false, reason:'no-adom-desktop', simulated:true}             : await fetch('api/canvas-check').then(r=>r.json());-          if(!chk.available){ showToast(chk.hint||'pup is not available on this machine yet.', 12000); restore(); return; }+          if(!chk.available){ showPupHelp(chk); restore(); return; }         }         const baseline=await surfaceCount();         if(baseline<0){ showToast('cannot reach the shotlog broker - switch aborted, nothing changed.', 7000); restore(); return; }@@ -696,6 +742,51 @@ header {     });   })(); +  // ── Pup helper dialog: reason-specific explanation + a COPYABLE AI prompt ──+  function showPupHelp(chk){+    const reason=chk.reason||'no-adom-desktop';+    const C={+      'no-adom-desktop':{+        title:'Pup needs Adom Desktop',+        body:'Pup opens shotlog in a full browser window on YOUR computer, driven by Adom Desktop. Adom Desktop is not installed (or not reachable) yet - pup is a default bridge that installs automatically right after it.',+        prompt:'Install Adom Desktop on my computer so shotlog can open pup windows. Start from wiki.adom.inc/adom/adom-desktop, walk me through the install, make sure it connects to my container, verify the pup bridge with `adom-desktop browser_readiness`, then show my shotlog channel "'+channel+'" in pup.'},+      'desktop-not-connected':{+        title:'Adom Desktop is not connected',+        body:'Adom Desktop is installed but not linked to this container right now. Launch it on your computer and it reconnects automatically.',+        prompt:'My Adom Desktop is installed but not connected to this container. Help me get it running and linked, verify with `adom-desktop browser_readiness`, then show my shotlog channel "'+channel+'" in pup.'},+      'pup-not-ready':{+        title:'Pup bridge is still warming up',+        body:'Adom Desktop is connected, but the pup browser bridge is not ready yet. It auto-installs on first use - this usually resolves in under a minute.',+        prompt:'The pup bridge on my Adom Desktop is not ready. Run `adom-desktop browser_prewarm`, verify with `adom-desktop browser_readiness`, then show my shotlog channel "'+channel+'" in pup.'},+      'multiple-desktops':{+        title:'More than one Adom Desktop is connected',+        body:'The broker cannot tell which computer should host the pup window. It needs a target.',+        prompt:'Multiple Adom Desktops are connected to my container. Figure out which one I am actually using, set SHOTLOG_AD_TARGET=<that name> on my shotlog broker, then show my shotlog channel "'+channel+'" in pup.'}+    };+    const c=C[reason]||C['no-adom-desktop'];+    $('pupHelpTitle').textContent=(chk.simulated?'(simulated) ':'')+c.title;+    $('pupHelpBody').textContent=c.body+(chk.hint&&!chk.simulated?' ('+chk.hint+')':'');+    $('pupHelpPrompt').textContent=c.prompt;+    $('pupHelp').classList.add('open');+  }+  (function wirePupHelp(){+    const dlg=$('pupHelp'); if(!dlg) return;+    const close=()=>dlg.classList.remove('open');+    $('pupHelpClose').addEventListener('click',close);+    $('pupHelpDismiss').addEventListener('click',close);+    dlg.addEventListener('click',e=>{ if(e.target===dlg) close(); });+    document.addEventListener('keydown',e=>{ if(e.key==='Escape'&&dlg.classList.contains('open')) close(); });+    $('pupHelpCopy').addEventListener('click',()=>{+      const t=$('pupHelpPrompt').textContent;+      const done=()=>{ $('pupHelpCopy').textContent='copied ✓'; setTimeout(()=>$('pupHelpCopy').innerHTML='⧉ Copy prompt',1400); };+      if(navigator.clipboard&&navigator.clipboard.writeText){ navigator.clipboard.writeText(t).then(done).catch(()=>{fallback();}); }+      else fallback();+      function fallback(){ const r=document.createRange(); r.selectNodeContents($('pupHelpPrompt'));+        const sel=getSelection(); sel.removeAllRanges(); sel.addRange(r);+        try{ document.execCommand('copy'); done(); }catch{ showToast('select the prompt text and copy manually',5000); } }+    });+  })();+   // ── WebSocket live updates ({type:'entry', entry}) ───────────────────────   let activeWs = null;   // Gentle "you have unseen shots" cue: while this tab is backgrounded, count new