app
Shotlog - Screenshot Log
Public Made by Adomby adom
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 Bridge child-window arrays via --meta.
← Commit history
Publish 0.4.2
9 files changed
+78−12
Cargo.lock+1−1@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "adom-shotlog"-version = "0.4.1"+version = "0.4.2" dependencies = [ "axum", "base64",
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-shotlog"-version = "0.4.1"+version = "0.4.2" edition = "2021" description = "Screenshot log viewer and CLI for Adom"
VERSION+1−1@@ -1 +1 @@-0.4.1+0.4.2
bin/adom-shotlog⋯ 1 unchanged line ⋯
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-shotlog",- "version": "0.4.1",+ "version": "0.4.2", "type": "app", "title": "adom-shotlog", "description": "See the shots your AI never showed you. Your AI screenshots your app while it tests but never surfaces them (it thinks in text) \u2014 adom-shotlog streams every shot it gathered into a live gallery you open in a webview, pup, your browser, or your phone. Now ingests Adom Desktop owned-popup arrays + coordMap via --meta.",
page.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-shotlog",- "version": "0.4.1",+ "version": "0.4.2", "type": "app", "title": "adom-shotlog", "description": "See the shots your AI never showed you. Your AI screenshots your app while it tests but never surfaces them (it thinks in text) — adom-shotlog streams every shot it gathered into a live gallery you open in a webview, pup, your browser, or your phone. Now ingests Adom Desktop owned-popup arrays + coordMap via --meta.",
screenshots/hero.png⋯ 1 unchanged line ⋯
screenshots/popups.png⋯ 1 unchanged line ⋯
src/html/index.html+73−7@@ -107,8 +107,32 @@ header { /* Popup-array badge + nerd info chip on a card */ .shot-card-meta .badge-pop { background: rgba(0,184,176,.16); color: var(--accent); border: 1px solid rgba(0,184,176,.4); border-radius: 999px; padding: 0 7px; font-weight: 600; cursor: help; }-.shot-card-meta .badge-nerd { color: var(--text3); cursor: help; border: 1px solid var(--border);- border-radius: 4px; padding: 0 5px; }+.shot-card-meta .badge-nerd { color: var(--text3); cursor: pointer; border: 1px solid var(--border);+ border-radius: 4px; padding: 0 5px; user-select: none; }+.shot-card-meta .badge-nerd:hover { color: var(--accent); border-color: rgba(0,184,176,.4); }+.shot-card-meta .badge-nerd.active { color: var(--accent); border-color: rgba(0,184,176,.5); background: rgba(0,184,176,.10); }+/* Owned-popup row, inline on the card — all array shots in ONE row, no zoom needed */+.card-popups { display: flex; gap: 8px; padding: 9px 13px 4px; overflow-x: auto; flex-shrink: 0; }+.card-popups .ph { flex: 0 0 auto; align-self: center; font: 600 10px 'Familjen Grotesk', sans-serif;+ color: var(--text2); white-space: nowrap; padding-right: 2px; }+.card-popups .pc { flex: 0 0 auto; width: 168px; background: #000; border: 1px solid var(--border);+ border-radius: 8px; overflow: hidden; cursor: zoom-in; transition: border-color .12s; }+.card-popups .pc:hover { border-color: rgba(0,184,176,.5); }+.card-popups .pc img { width: 100%; height: 96px; object-fit: contain; background: #111; display: block; }+.card-popups .pc .cap { padding: 3px 7px; font-family: 'JetBrains Mono', monospace; font-size: 9px;+ color: var(--text3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }+/* Nerd metadata revealed INLINE on the card (not just the zoom modal) */+.card-nerd { display: none; margin: 6px 13px 12px; border: 1px solid var(--border); border-radius: 8px;+ background: var(--elevated); flex-shrink: 0; }+.card-nerd.open { display: block; }+.card-nerd .nhead { display: flex; align-items: center; gap: 8px; padding: 7px 11px; font: 600 10px 'JetBrains Mono', monospace; color: var(--text2); }+.card-nerd .nhead .copy { margin-left: auto; font-size: 9px; color: var(--accent); border: 1px solid rgba(0,184,176,.4);+ border-radius: 4px; padding: 1px 7px; cursor: pointer; }+.card-nerd .nbody { padding: 0 11px 9px; }+.card-nerd .row { display: flex; gap: 8px; font-family: 'JetBrains Mono', monospace; font-size: 10px;+ padding: 2px 0; border-top: 1px solid rgba(255,255,255,.04); }+.card-nerd .row .k { color: var(--text3); min-width: 120px; }+.card-nerd .row .v { color: var(--text); user-select: all; word-break: break-all; } /* Zoom modal — full card */ .modal { position: fixed; inset: 0; background: rgba(0,0,0,.88); display: none;@@ -300,9 +324,27 @@ header { } } + // Inline nerd-metadata panel, rendered ON the card (revealed in place — no zoom).+ function buildNerdInline(e) {+ const pops=popList(e);+ const raw=JSON.stringify({meta:e.meta||null, popups:pops.length?pops:undefined}, null, 2);+ const panel=document.createElement('div'); panel.className='card-nerd';+ const head=document.createElement('div'); head.className='nhead'; head.textContent='⌗ capture metadata';+ const cp=document.createElement('span'); cp.className='copy'; cp.textContent='copy JSON';+ cp.addEventListener('click', ev=>{ ev.stopPropagation();+ navigator.clipboard?.writeText(raw).then(()=>{ cp.textContent='copied ✓'; setTimeout(()=>cp.textContent='copy JSON',1200); }); });+ head.appendChild(cp); panel.appendChild(head);+ const body=document.createElement('div'); body.className='nbody';+ metaRows(e).forEach(([k,v])=>{ const r=document.createElement('div'); r.className='row';+ const kk=document.createElement('span'); kk.className='k'; kk.textContent=k;+ const vv=document.createElement('span'); vv.className='v'; vv.textContent=v;+ r.appendChild(kk); r.appendChild(vv); body.appendChild(r); });+ panel.appendChild(body);+ return panel;+ }+ function card(e) { const c=document.createElement('div'); c.className='shot-card'; c.dataset.id=e.id;- c.addEventListener('click',()=>openModal(e)); const desc=document.createElement('div'); if (e.description) { desc.className='shot-card-desc'; desc.textContent=e.description; } else { desc.className='shot-card-desc no-desc'; desc.textContent='⚠ No description — inject with -d "what and why"'; }@@ -318,15 +360,39 @@ header { const pops=popList(e); if (pops.length){ const s=document.createElement('span'); s.className='sep'; s.textContent='·'; meta.appendChild(s); const b=document.createElement('span'); b.className='badge-pop'; b.textContent='+'+pops.length+' popup'+(pops.length>1?'s':'');- b.setAttribute('data-tooltip','This shot captured '+pops.length+' owned popup'+(pops.length>1?'s':'')+' (dropdowns / dialogs). Open the shot to view each one.');+ b.setAttribute('data-tooltip','This shot also captured '+pops.length+' owned popup'+(pops.length>1?'s':'')+' (dropdowns / dialogs) — shown below.'); meta.appendChild(b); }+ // ⓘ meta chip toggles the inline metadata panel right here on the card.+ let nerd=null, chip=null; if (e.meta){ const s=document.createElement('span'); s.className='sep'; s.textContent='·'; meta.appendChild(s);- const n=document.createElement('span'); n.className='badge-nerd'; n.textContent='ⓘ meta';- n.setAttribute('data-tooltip', metaRows(e).map(([k,v])=>k+': '+v).join(' ')||'capture metadata');- meta.appendChild(n); }+ chip=document.createElement('span'); chip.className='badge-nerd'; chip.textContent='ⓘ meta';+ chip.setAttribute('data-tooltip','Tap to reveal the capture metadata (coordMap, DPI, screen rect) inline.');+ meta.appendChild(chip); } c.appendChild(meta); const img=document.createElement('img'); img.className='shot-card-img'; img.src=imgUrl(e); img.alt=e.description||e.filename;+ img.addEventListener('click', ()=>openModal(e)); // image still zooms if you want it c.appendChild(img);+ // All owned popups in ONE row, inline — no need to open the shot.+ if (pops.length){+ const row=document.createElement('div'); row.className='card-popups';+ const ph=document.createElement('span'); ph.className='ph'; ph.textContent='popups ▸'; row.appendChild(ph);+ pops.forEach(p=>{+ const cell=document.createElement('div'); cell.className='pc';+ const im=document.createElement('img'); im.src=popUrl(p.filename); im.alt=p.title||p.kind||'popup'; im.loading='lazy';+ const cap=document.createElement('div'); cap.className='cap';+ cap.textContent=(p.kind?p.kind+' · ':'')+(p.title||p.filename)+(p.w&&p.h?' '+p.w+'×'+p.h:'');+ cell.appendChild(im); cell.appendChild(cap);+ cell.addEventListener('click', ev=>{ ev.stopPropagation();+ openModal({filename:p.filename, description:p.title||p.kind||'popup', w:p.w, h:p.h, kb:p.kb,+ timestamp:e.timestamp, source:'popup', meta:p.coordMap?{coordMap:p.coordMap,shotId:p.shotId}:null}); });+ row.appendChild(cell);+ });+ c.appendChild(row);+ }+ // Inline nerd panel + wire the chip to toggle it in place.+ if (e.meta){ nerd=buildNerdInline(e); c.appendChild(nerd);+ chip.addEventListener('click', ev=>{ ev.stopPropagation();+ const open=nerd.classList.toggle('open'); chip.classList.toggle('active', open); }); } return c; }