← Commit history
Cargo.lock+1−1
@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"  [[package]] name = "adom-shotlog"-version = "0.28.4"+version = "0.28.5" dependencies = [  "axum",  "base64",
Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "adom-shotlog"-version = "0.28.4"+version = "0.28.5" edition = "2021" description = "Screenshot log viewer and CLI for Adom" license = "MIT"
VERSION+1−1
@@ -1 +1 @@-0.28.4+0.28.5
bin/adom-shotlog
⋯ 1 unchanged line ⋯
dev-skills/adom-shotlog-dev/SKILL.md+9
@@ -469,3 +469,12 @@ Content is bounded anyway (context truncates at capture), so no cap needed. - The read-hook derives a handle from the source filename ONLY when the stem is wordy: at least 3 letters AND more letters than digits (Ray's PR #3, adapted). Timestamp names (`2026-09-02T12-59-09.647.png`, `IMG_1234.png`, `screenshot-2026-09-02-at-12.59.png`) get no handle; the ref (#id) already names them, and a date chip on every card is noise. - Tooltips are suppressed while ANY deliberately opened surface is up: the hovered card's `.card-info.show` AND any `.hover-popover.show` / `.card-info.show` on the page (Ray's PR #4). - Wiki PRs against this page are whole-file diffs from an older base; apply them locally (adapted where needed), release, then close the PR with a comment crediting the author. Never `pr merge` a whole-file diff over newer files.++## PR rule (John, 2026-09-02): NEVER close a PR without actually doing it++A wiki PR against adom/adom-shotlog is closed ONLY after its change has been applied locally, released (bumped, built, deployed, published, pushed), and verified. Closing is the last step, and the closing reply names the version that carries the change. If a PR should NOT be applied, leave it open, reply with the reason, and tell John; do not close it to tidy the list. "Applied, adapted" is fine (say what changed and why); "closed, not applied" is not.++## Tell Ray (John, 2026-09-02)++When you fix something Ray reported (issue or PR), DM him one simple line on Google Chat as John via `adom-google chat send` (to [email protected]): what shipped and the version. One line, no essay; the detail lives in the issue/PR reply.+
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-shotlog",-  "version": "0.28.4",+  "version": "0.28.5",   "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.4",+  "version": "0.28.5",   "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+19−4
@@ -258,7 +258,9 @@ body.compact .card-popups .ph { padding-top: 4px; }   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;+.card-refbar .rb-copy svg { width: 13px; height: 13px; display: block; }+.card-refbar .rb-copy { margin-left: 4px; padding: 2px 4px; border-radius: 5px; cursor: pointer;+  display: inline-flex; align-items: center; justify-content: center;   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; }@@ -978,6 +980,19 @@ body.compact .card-popups .ph { padding-top: 4px; }   // 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)+  // The two-overlapping-squares copy glyph everyone recognises (John: "usually+  // there's a nice copy to clipboard button used out there in the wild of the+  // double square"). Inline SVG rather than a unicode glyph like ⧉ on purpose:+  // the ⛶ in card-fill-btn already renders as tofu in some headless captures,+  // and this button has to read at 13px in a slim panel. (Ray, PR #6)+  const ICON_COPY = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" ' ++    'stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' ++    '<rect x="9" y="9" width="12" height="12" rx="2"/>' ++    '<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';+  const ICON_DONE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" ' ++    'stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' ++    '<polyline points="20 6 9 17 4 12"/></svg>';+   function legacyCopy(text, done) {     try {       const ta = document.createElement('textarea');@@ -1241,13 +1256,13 @@ body.compact .card-popups .ph { padding-top: 4px; }       // 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.innerHTML = ICON_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);+            cp.innerHTML = ICON_DONE; cp.classList.add('done');+            setTimeout(function () { cp.innerHTML = ICON_COPY; cp.classList.remove('done'); }, 1200);           };           if (navigator.clipboard && navigator.clipboard.writeText) {             navigator.clipboard.writeText(txt).then(done, function () { legacyCopy(txt, done); });