← Commit history

Publish 0.28.4

John Lauer ·8d1bc64c9d ·1mo ago ·parent b109b96
7 files changed +47−5
Cargo.lock+1−1
@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"  [[package]] name = "adom-shotlog"-version = "0.28.3"+version = "0.28.4" dependencies = [  "axum",  "base64",
Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "adom-shotlog"-version = "0.28.3"+version = "0.28.4" edition = "2021" description = "Screenshot log viewer and CLI for Adom" license = "MIT"
VERSION+1−1
@@ -1 +1 @@-0.28.3+0.28.4
bin/adom-shotlog
⋯ 1 unchanged line ⋯
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-shotlog",-  "version": "0.28.3",+  "version": "0.28.4",   "type": "app",   "title": "Shotlog - Screenshot Log",   "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 Bridge child-window arrays via --meta.",
page.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-shotlog",-  "version": "0.28.3",+  "version": "0.28.4",   "type": "app",   "title": "Shotlog - Screenshot Log",   "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 Bridge child-window arrays via --meta.",
src/html/index.html+42
@@ -257,6 +257,14 @@ body.compact .card-popups .ph { padding-top: 4px; } .card-refbar { display: flex; align-items: center; gap: 8px; padding: 3px 10px 2px; min-height: 16px;   font: 600 10.5px/1.3 'JetBrains Mono', monospace; color: var(--text3); } .card-refbar .rb-ref { letter-spacing: .2px; }+/* copy button (Ray, PR #5): hover-revealed like ⛶, never on the thumbnail */+.card-refbar .rb-copy { margin-left: 4px; padding: 0 5px; border-radius: 5px; cursor: pointer;+  font: inherit; line-height: 1.5; color: var(--text3); background: transparent;+  border: 1px solid var(--border-muted); opacity: 0; transition: opacity .12s, color .12s, border-color .12s; }+.shot-card:hover .card-refbar .rb-copy, .card-refbar .rb-copy:focus-visible { opacity: 1; }+.card-refbar .rb-copy:hover { color: var(--accent-bright); border-color: rgba(0,184,176,.5); }+.card-refbar .rb-copy.done { opacity: 1; color: var(--accent-bright); border-color: rgba(0,184,176,.5); }+@media (hover: none) { .card-refbar .rb-copy { opacity: .8; } } .card-refbar .rb-tag { color: var(--accent-bright); background: rgba(0,184,176,.12); border: 1px solid rgba(0,184,176,.45);   border-radius: 5px; padding: 0 6px; max-width: 70%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .shot-card:not(.has-refbar) .card-refbar { }@@ -966,6 +974,21 @@ body.compact .card-popups .ph { padding-top: 4px; }   })();    // ── Helpers ──────────────────────────────────────────────────────────────+  // execCommand('copy') is deprecated but is the only thing that works in a+  // sandboxed frame with no clipboard permission, which is where this viewer+  // sometimes lives. Used only when navigator.clipboard is missing or rejects.+  // (Ray, PR #5)+  function legacyCopy(text, done) {+    try {+      const ta = document.createElement('textarea');+      ta.value = text; ta.setAttribute('readonly', '');+      ta.style.cssText = 'position:fixed;top:-1000px;opacity:0';+      document.body.appendChild(ta); ta.select();+      const ok = document.execCommand('copy');+      document.body.removeChild(ta);+      if (ok && done) done();+    } catch (e) { /* nothing else to try; leave the label alone */ }+  }   let toastTimer=null;   function showToast(msg, ms){ toast.textContent=msg; toast.classList.add('show');     toast.classList.toggle('lifted', !!document.querySelector('.cdown')); // never under the countdown card@@ -1212,6 +1235,25 @@ body.compact .card-popups .ph { padding-top: 4px; }       if (e.tag){ const tg=document.createElement('span'); tg.className='rb-tag'; tg.textContent=e.tag;         tg.setAttribute('data-tooltip','Handle "'+e.tag+'" given by the AI that injected this shot (--tag). Say "'+e.tag+'" to mean exactly this shot.');         rb.appendChild(tg); }+      // Copy the WHOLE reference, "#158 hero-final", not just one half (Ray,+      // PR #5): the ref is globally unambiguous and the handle is what a human+      // actually says, so pasting both lets the AI resolve it either way and+      // survives a handle being reused later. Untagged shots copy just "#158".+      { const txt = '#' + e.id + (e.tag ? ' ' + e.tag : '');+        const cp = document.createElement('button'); cp.className = 'rb-copy';+        cp.textContent = 'copy'; cp.setAttribute('aria-label', 'Copy ' + txt);+        cp.setAttribute('data-tooltip', 'Copy "' + txt + '": paste it to your AI to mean exactly this shot.');+        cp.addEventListener('click', function (ev) {+          ev.stopPropagation();          // never let it open the shot+          const done = function () {+            cp.textContent = 'copied'; cp.classList.add('done');+            setTimeout(function () { cp.textContent = 'copy'; cp.classList.remove('done'); }, 1200);+          };+          if (navigator.clipboard && navigator.clipboard.writeText) {+            navigator.clipboard.writeText(txt).then(done, function () { legacyCopy(txt, done); });+          } else { legacyCopy(txt, done); }+        });+        rb.appendChild(cp); }       c.appendChild(rb); }   // info (hidden in compact) -> refbar -> imgWrap (appended below)     // COMPACT mode's reveal chip: hover (or tap, on touch) the ⓘ on the image     // to overlay the full info block; it hides again when the pointer leaves