Add a QR code — six presets, and the ones you saved in Universal QR - #158
Merged
Merged
Conversation
A QR button in the toolbar (desktop: beside the image button; mobile: beside Image) opens a cut-down Universal QR — a link box and six style presets — and drops the generated code on the page. It is an image annotation, not a new type. "Add to page" renders a 1024px PNG, hands it to setUploadedImageSrc and arms the existing image tool, so placing, moving, resizing, undoing and baking into the export are all machinery that already existed. At the default ~200pt that works out around 360dpi, so the code scans off a printed page rather than only off a screen. src/lib/qr/ is a port of Universal QR's renderer, kept faithful on purpose: QrDesign is a field-for-field copy of its QrConfig, the presets are its PRESETS verbatim, and the shaped-plate geometry and decoration come across whole. The EDITOR is what is simplified, not the format — a design imported from Universal QR is restored whole, and a code that rendered differently in the two apps would be the version of this feature nobody trusts. Checked by rendering all six presets through both pipelines and diffing the pixels: identical, the sole delta being the centre mark's antialiasing (Universal QR inlines a 256px data URI; here the shipped icon is downscaled by the browser). Your saved codes arrive with no backend at all. Universal QR keeps designs in localStorage under unisim.qr.designs.v1, and in production the two apps are the same origin — opensource.unisim.co.uk/pdf and /qr — so the dialog simply lists them, and clicking one restores its link, colours, plate and logo. That store is read-only here: it belongs to another app, is capped at 12 entries, and evicting someone's design because they added a QR to a PDF would be a bad trade. The origin is not guaranteed either (pdf.unisim.co.uk, Electron), so a .uniqr.json backup import covers everywhere else. qrContrastIssue warns on an inverted or thin-contrast code. The six presets all pass; the check is for designs arriving from Universal QR's full studio, where a code can scan on a screen and fail in print — and an exported PDF is the place nobody notices until the poster comes back. Verified end to end in a browser: design → place → export → re-render the exported page with pdf.js → decode the QR back out of it. All six presets decode with @zxing/library at every size the app renders. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J76Zc6mr4RsdYpqVGenDdk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A QR button in the toolbar (desktop: beside the image button; mobile: beside Image) opens a cut-down Universal QR — a link box and six style presets — and drops the generated code on the page.
It is an image annotation, not a new type
"Add to page" renders a 1024px PNG, hands it to
setUploadedImageSrcand arms the existingimagetool, so placing, moving, resizing, undoing and baking into the export are all machinery that already existed. At the default ~200pt that works out around 360dpi, so the code scans off a printed page rather than only off a screen.Sharing a design model with Universal QR
src/lib/qr/is a port of Universal QR's renderer, kept faithful on purpose:design.tslib/qr.tsQrDesignis a field-for-field copy of itsQrConfig; the six presets are itsPRESETSverbatimframes.tslib/frames.tsdecor.tslib/decor.tsrender.tslib/compose.tsThe editor is what is simplified, not the format — a design imported from Universal QR is restored whole, and a code that rendered differently in the two apps would be the version of this feature nobody trusts.
Your saved codes, with no backend
Universal QR keeps designs in
localStorageunderunisim.qr.designs.v1, and in production the two apps are the same origin (opensource.unisim.co.uk/pdfand/qr, both behind the opensource-portal Worker) — so the dialog simply lists them, and clicking one restores its link, colours, plate and any uploaded logo. No account, no API, no round trip.That store is read-only here: it belongs to another app, is capped at 12 entries, and evicting someone's saved design because they added a QR to a PDF would be a bad trade. The origin is not guaranteed either (
pdf.unisim.co.uk, the Electron build), so a.uniqr.jsonbackup import covers everywhere else.Colours
qrContrastIssuewarns on an inverted code (light modules on dark — strict decoders reject those) or a low-contrast one (right polarity, too thin a ratio). The six presets all pass; the check is for designs arriving from Universal QR's full studio, where a code can scan on a screen and fail in print — and an exported PDF is the place nobody notices until the poster comes back.Verification
Driven in a real headless browser, not eyeballed:
unisim-icon.pngis downscaled by the browser).@zxing/library(the decoder Universal QR validated against) at every size the app renders. They fail only at 96px and, for Star, 256px — sizes nothing renders at; placement is 1024px, preview 448px.sm.npm run typecheckandnpm run buildboth clean. No new dependencies —qr-code-stylingwas already here for the sign-on-phone QR.Note, unrelated to this change
src/lib/brandedQr.ts(the sign-on-phone QR) renders orange modules on near-black — an inverted code by the standard Universal QR documents at length, and one its own scanner rejects. It evidently works in practice for that flow, so it is untouched here, but it may be worth a look.🤖 Generated with Claude Code
https://claude.ai/code/session_01J76Zc6mr4RsdYpqVGenDdk
Generated by Claude Code