149 jsQR attempts at full 720x1280 with px:ok and no detection means
the QR in the frame has perspective skew, motion blur, or glare under
jsQR's threshold but well within what real-world phone scanning needs
to handle. jsQR is fast but brittle.
Vendor @zxing/library 0.21.3 (Apache 2.0, ~328KB UMD) and make it the
default decoder. ZXing's HybridBinarizer + perspective transform are
the same algorithm family the iOS Camera app uses internally and they
recover from the cases jsQR rejects.
Decoder selection order:
1. ZXing-js (window.ZXing.BrowserMultiFormatReader) -- new default
2. native BarcodeDetector -- if ZXing missing
3. jsQR -- last-resort
Implementation details:
- Hint ZXing to QR_CODE only so it doesn't waste frames probing
Code 128 / EAN / PDF417.
- Use decodeFromCanvas on each video frame (rather than ZXing's
built-in continuous video reader) so we keep ownership of the
modal UI, the <video> element, and the getUserMedia stream.
- Status line follows the same compact format as the jsQR loop:
zxing · f1234 a567 720x1280 rs4 r:no_code
with r:found / r:empty / r:no_code / r:err: ...
Version: shopfloor 19.0.21 -> 19.0.22.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>