fix(review): add localStorage theme-forcing fallback for visual capture#4127
Conversation
…re (#4109) Verified emulateMediaFeatures only affects CSS media queries/matchMedia, so it has zero effect on a target whose theme is driven by a stored preference instead -- reproducible today against gittensory-ui's own dark-mode-only build. Adds an opt-in review.visual.theme_storage_key config that ALSO forces the theme via localStorage.setItem + a reload, alongside the existing emulateMediaFeatures call. The desktop/mobile viewport pair is documented as a deliberate keep, not a silent inconsistency with metagraphed's manual 3-viewport convention.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
gittensory-ui | f04bcb9 | Commit Preview URL Branch Preview URL |
Jul 08 2026, 04:40 AM |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4127 +/- ##
=======================================
Coverage 93.66% 93.67%
=======================================
Files 384 384
Lines 35936 35963 +27
Branches 13188 13196 +8
=======================================
+ Hits 33660 33687 +27
Misses 1618 1618
Partials 658 658
🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-08 05:14:31 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 6 non-blocking
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Summary
page.emulateMediaFeatures([{ name: "prefers-color-scheme", ... }])actually changes the rendered theme for a real capture target, per fix(review): verify + fix theme-forcing and viewport matrix in visual capture #4109.Emulation.setEmulatedMedia(whatemulateMediaFeaturesmaps to) only changes what CSS media queries andwindow.matchMediareport -- it cannot writelocalStorageand has zero effect on any theme mechanism that reads an explicit stored preference instead. This is reproducible today against gittensory's own UI:apps/gittensory-ui/src/components/site/theme-toggle.tsxforces dark mode unconditionally (never consultingprefers-color-scheme), so alightvsdarkcapture of gittensory's own site would render byte-identical today.review.visual.theme_storage_keyconfig field that ALSO forcesthemevialocalStorage.setItem(key, theme)+ a page reload before capture, alongside the existingemulateMediaFeaturescall. Threaded throughcaptureShot/captureScrollFrames(src/review/visual/shot.ts),capturePage/captureScrollGif/buildCapture(src/review/visual/capture.ts), the on-demand?url=render route's&themeStorageKey=param, the R2 cache fingerprint (so a differently-keyed capture never collides), and the full config-as-code round trip (packages/gittensory-engine/src/focus-manifest.ts: type + empty default + parse + present-check + overlay + serialize, plus both.gittensory.yml.exampleandconfig/examples/gittensory.full.ymldocs). Fully opt-in and additive -- omitted (every existing repo) is byte-identical to today.shot.ts) -- a 3rd viewport would raise Browser Rendering wall-clock by 50% (4 -> 6 renders/route) for every repo, every review, not just the reviewer who wants tablet coverage, and gittensory's own pair already straddles a real breakpoint on each side.Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Closes #123) — a linked open issue is required for every contributor PR.Validation
git diff --checknpm run actionlint(vianpm run test:ci)npm run typechecknpm run test:coveragelocally;codecov/patchrequires ≥99% coverage of the lines AND branches you changed (aim for 100% on your diff so CI variance does not fail near the threshold). Global coverage is a non-blocking trend with a loose 90% backstop, not the gate.npm run test:workers(vianpm run test:ci)npm run build:mcp(vianpm run test:ci)npm run test:mcp-pack(vianpm run test:ci)npm run ui:openapi:check(vianpm run test:ci; no API/schema change in this PR)npm run ui:lint(vianpm run test:ci)npm run ui:typecheck(vianpm run test:ci)npm run ui:build(vianpm run test:ci)npm audit --audit-level=moderateRan the full local gate:
npm run test:ci(all steps green, includingtest:engine-parity,manifest:drift-check,selfhost:validate-observability,db:migrations:check/db:schema-drift:check-- no migration needed, this feature has no DB surface) andnpm audit --audit-level=moderate(0 vulnerabilities). Additionally manually verified branch-level patch coverage of every changed line insrc/review/visual/shot.ts,src/review/visual/capture.ts, andpackages/gittensory-engine/src/focus-manifest.tsagainst the local v8 lcov report -- every newif/&&/ternary in the diff has both sides exercised.Safety
review.visual.*is a.gittensory.yml-only manifest field, like itspreview/routes/themes/gifsiblings; no OpenAPI/DB/MCP surface.)UI Evidencesection below with JPG/JPEG or PNG screenshots arranged as organized, captioned, clickable thumbnails. (N/A -- backend-only capture-pipeline change, no visible UI.)CHANGELOG.mduntouched.)UI Evidence
N/A -- this PR has no visible UI surface; it changes the server-side visual-capture pipeline (
src/review/visual/**) and its.gittensory.ymlconfig schema only.Notes
emulateMediaFeaturesa no-op" question is answered by direct code inspection rather than a live network probe (sandboxed environment has no network access to a real deployed preview):Emulation.setEmulatedMedia's documented scope is CSS-media-query/matchMediaonly, andapps/gittensory-ui's own theme-toggle source confirms it as a concrete, reproducible instance of a target this option cannot affect.src/review/visual/shot.ts, aboveDESKTOP_VIEWPORT/MOBILE_VIEWPORT), per the issue's "either is acceptable, must be explicit" framing -- no viewport dimensions changed.Closes #4109