Add camera barcode/QR scanner to batch scan and book edit#440
Open
gunwald wants to merge 5 commits into
Open
Conversation
Adds a camera icon inside the ISBN input field (right side, same pattern as Google search). Tapping it opens a fullscreen camera overlay with a scan guide frame and animated sweep line. ZXing (@zxing/browser + @zxing/library) handles decoding. Only EAN-13/ISBN-10/13 shaped values are passed through — other barcode types are silently ignored. NotFoundException (fires on every frame with no barcode) is suppressed. On mobile the back camera is preferred automatically. If multiple cameras are available a switch button appears in the header. Permission denied and no-camera states show an error with a retry button. On detection the overlay closes, the camera stream stops, and the ISBN is fed directly into processIsbn — the same path as manual input, so cover fetching, quantity increment, and sound effects all work identically. Scan animation keyframe added to globals.css.
- Add camera icon button inside ISBN input on /book/new and book edit page (same ZXing overlay as batch scan; detection fills isbn field) - Fix csrfToken undefined serialization on login page (getCsrfToken returns undefined in newer next-auth; coerce to null) - Add dev:https npm script for phone testing over local network (mkcert cert, pins port 3002, inlines NEXTAUTH_URL override) - Gitignore /certs/ directory for local mkcert files
- CameraScanner: fix race where decode callback fires before
decodeFromVideoDevice resolves; use a session-local `detected` flag
to prevent duplicate onDetected calls and stop the stream cleanly
- BookField: disable camera button when editable={false} so scans
cannot overwrite a read-only form
- BookEditForm: remove book from handleCameraDetected useCallback deps
via bookRef pattern to avoid stale closure clobbering concurrent edits
- login: remove dead csrfToken prop and getServerSideProps — the
authorize function never reads hiddenFieldName, so the CSRF token
fetch was unused and caused a serialization crash in newer next-auth
- BookField/i18n: replace hardcoded German aria-label with t() key
(openCameraScanner added to de/en/es)
- CameraScanner: stop the MediaStream when the component is closed or
unmounted before decodeFromVideoDevice() resolves. A cancelledRef is
set in the unmount cleanup and checked after the await, so controls
returned late are stopped instead of orphaned (camera light staying on)
- CameraScanner: replace loose /^\d{10,13}$/ check (accepted 11/12-digit
non-ISBN barcodes) with the canonical isIsbnLike()/normalizeIsbn()
utils, so only real ISBN-10/13 codes are accepted
- batchscan: restore the "invalid ISBN" warning for non-numeric manual
input. handleScan now cleans non-digits before the empty check, so
junk input warns and keeps the field instead of silently clearing it
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.
Closes #427
Summary
BrowserMultiFormatReader) reachable from a camera icon inside the ISBN input field/book/newISBN fieldHardening (from review)
MediaStreamwhen the scanner is closed/unmounted beforedecodeFromVideoDevice()resolves, so the camera light doesn't stay on/^\d{10,13}$/check with the canonicalisIsbnLike()/normalizeIsbn()utils so only real ISBN-10/13 codes are accepted (11/12-digit non-ISBN barcodes are rejected)Test plan
/book/new— camera icon in the ISBN field fills the ISBN and autofill works