From 6ae3286de4fbc5271a20cbdc05a23bfbe21272f2 Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Wed, 12 Aug 2026 17:38:13 -0400 Subject: [PATCH] feat: rotate readers on screenshots --- scripts/capture-status-docs.mjs | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/scripts/capture-status-docs.mjs b/scripts/capture-status-docs.mjs index 0ef9048..497d470 100644 --- a/scripts/capture-status-docs.mjs +++ b/scripts/capture-status-docs.mjs @@ -144,6 +144,26 @@ const STUB_LABELERS = [ // Real detection over the network; generous next to the local fixtures. const SETTLE_MS = 45000 +/** + * The reader each card capture is preset to open in (storage.local's + * `defaultReader`, the key the popup reads), so the set shows the readers the + * extension offers rather than the default four times over. + * + * Only readers with a publication view can be preset here: every capture shows + * a publication and no capture has a document, so a reader whose publication + * URL is null (anisota.net, see src/lib/readers.ts) would be captured as a + * disabled button. The value is the vendored icon the popup draws for that + * reader, which is the only thing in the popup's DOM that names the reader by + * id — the label comes from the Waypoints catalog. A stored id the catalog no + * longer has falls back to the first reader, so checking the icon is what + * makes that fail the capture instead of quietly reshooting the default. + */ +const READER_ICONS = { + standardReader: 'standard.svg', + leaflet: 'leaflet.png', + pdsls: 'pdsls.png', +} + /** Standard Reader's view of a publication: a real page that is not its home. */ function readerUrl(pub) { return `https://standard-reader.app/p/${pub.did}/${pub.uri.split('/').pop()}` @@ -520,6 +540,7 @@ async function captureRealStates({ cdp, inWorker, popupUrl }) { { name: 'popup-publication', url: REAL.standardSite, + reader: 'standardReader', click: '#subscribe', expectPills: 1, expectCard: true, @@ -530,6 +551,7 @@ async function captureRealStates({ cdp, inWorker, popupUrl }) { { name: 'popup-subscribed', url: REAL.permadeath, + reader: 'leaflet', needsPub: true, state: (detected) => ({ ...detected, subscriptionRkey: '3kcapturesub' }), session: true, @@ -547,6 +569,7 @@ async function captureRealStates({ cdp, inWorker, popupUrl }) { { name: 'popup-blocked', url: REAL.atprotoBlog, + reader: 'standardReader', needsPub: true, state: (detected) => ({ ...detected, @@ -568,6 +591,7 @@ async function captureRealStates({ cdp, inWorker, popupUrl }) { { name: 'popup-unverified', url: readerUrl(atproto), + reader: 'leaflet', state: (detected) => ({ ...detected, pub: { ...atproto, verified: false }, @@ -589,6 +613,7 @@ async function captureRealStates({ cdp, inWorker, popupUrl }) { { name: 'popup-labeled', url: plainUrl, + reader: 'pdsls', session: true, popupOffline: true, owner: BAD_BLOG_OWNER, @@ -756,6 +781,8 @@ async function screenshotPage(cdp, url, { width, height }) { * @property {boolean} [needsPub] wait for real detection to find a * publication before seeding (the seed derives from it) * @property {boolean} [session] install the fixture account mirror + * @property {keyof READER_ICONS} [reader] reader this capture is preset to + * open in, checked against the button the popup rendered * @property {boolean} [popupOffline] * @property {boolean} [workerOffline] * @property {object} [owner] publication-owner card to seed the popup's @@ -815,6 +842,10 @@ async function captureScenario(cdp, inWorker, popupUrl, s) { // account's own labeler subscriptions. await inWorker(`chrome.storage.local.set({ labelers: ${JSON.stringify(s.labelers)} })`) } + if (s.reader) { + if (!READER_ICONS[s.reader]) throw new Error(`${s.name}: no icon known for reader ${s.reader}`) + await inWorker(`chrome.storage.local.set({ defaultReader: ${JSON.stringify(s.reader)} })`) + } // Put the worker's connection state where this scenario wants it. Restoring // means putting the *native* accessor back: deleting it leaves // navigator.onLine undefined, which computeState reads as being offline, so @@ -947,6 +978,32 @@ async function captureScenario(cdp, inWorker, popupUrl, s) { throw new Error(`${s.name}: version reads "${version}", expected "v${BUILT_VERSION}"`) } + if (s.reader) { + // The preset has to be the reader in the shot: an id the catalog dropped + // falls back to the first reader, and one with no publication view + // renders disabled. Either would be a capture of the wrong button. + const open = await evaluate( + cdp, + sessionId, + `(() => { + const btn = document.getElementById('open-default') + if (!btn) return null + return { + icon: btn.querySelector('img.reader-icon')?.getAttribute('src') ?? null, + label: btn.textContent, + disabled: btn.disabled, + } + })()`, + ) + const want = `/vendored/${READER_ICONS[s.reader]}` + if (!open || open.icon !== want || open.disabled) { + throw new Error( + `${s.name}: expected the ${s.reader} button (${want}), got ${JSON.stringify(open)}`, + ) + } + console.log(`capture: ${s.name} opens in ${s.reader} — "${open.label}"`) + } + const box = await evaluate( cdp, sessionId, -- 2.51.2