mebjas / html5-qrcode

A cross platform HTML5 QR code reader. See end to end implementation at: https://scanapp.org
https://qrcode.minhazav.dev
Apache License 2.0
5.1k stars 983 forks source link

HTML5Qrcode + BarcodeDetector format enums inconsistencies. #824

Open Snurppa opened 1 year ago

Snurppa commented 1 year ago

Describe the bug

Background: I have used only the Html5Qrcode, I don't have any experience with Html5QrcodeScanner.

I wanted to use "DATA_MATRIX" format, so passed ["DATA_MATRIX"] as formatsToSupport option value.

For zxing that seems to work fine. But in browsers that support BarcodeDetector, its constructor is mad from that: native-bar-code-detector.js:164 Uncaught TypeError: Failed to construct 'BarcodeDetector': Hint option provided, but is empty. This is because "DATA_MATRIX" gets eventually filtered before reaching the constructor, thats why error says it is empty.

I was checking out the code and tried ["data_matrix"] which was how it was in BarcodeDetector's enum, but zxing didn't like that:

html5-qrcode.js:490 Uncaught None of formatsToSupport match supported values.
    Html5Qrcode.getSupportedFormats @   html5-qrcode.js:490
    Html5Qrcode @   html5-qrcode.js:142

Next I thought I will make both happy with ["DATA_MATRIX", "data_matrix"] , but no:

native-bar-code-detector.js:164 Uncaught TypeError: Failed to construct 'BarcodeDetector': Hint option provided, but is empty.
    new BarcodeDetectorDelegate (native-bar-code-detector.js:164:21)
    new Html5QrcodeShim (code-decoder.js:163:29)
    new Html5Qrcode (html5-qrcode.js:142:19)

So did some research on TypeScript enums and how they are represented in JS in the end. From that information and from the fact that the enums for both, zxing and BarcodeDetector, are more-or-less in same order, I was able to hack my way through by using ["DATA_MATRIX", 6]... 🙃

You could also add "data_matrix" there, because it is actually discarded before reaching either of the constructors. Discarded because HTML5Qrcode.getSupportedFormats would remove from the array all items that are not in the enum Html5QrcodeSupportedFormats, which basically means uppercase string comparison that happens in isValidHtml5QrcodeSupportedFormats.

To Reproduce

  1. Use a browser that has BarcodeDetector API
  2. Initialize HTML5Qrcode with formats that are in BarcodeDetectorDelegate.formatMap, as in lower case values:
    • new Html5Qrcode("your-element-id", {formatsToSupport: ["data_matrix"]})
  3. You should see errors described above, because of the filtering of the getSupportedFormats and mismatch of the two enums.

Expected behavior

I should be able to use common set of formats, that should work with both zxing/BarcodeDetector. Ideally the "format" of formats should be implementation detail.

Or separate the formats option declaration for both libraries, because if there are some future API changes e.g. in BarcodeDetector that can't be mapped to zxing formats, then users' hands are tied if it is not possible to give API compatible values.

Desktop (please complete the following information):

Additional context

I like the solution where you utilize both zxing and BarcodeDetector.

WizardCM commented 2 months ago

Experienced this myself. Solution is to use the enum values directly.

import { Html5Qrcode, Html5QrcodeSupportedFormats } from 'html5-qrcode';

const html5QrCode = new Html5Qrcode('reader', {
    formatsToSupport: [
        Html5QrcodeSupportedFormats.DATA_MATRIX,
        Html5QrcodeSupportedFormats.CODE_128,
        Html5QrcodeSupportedFormats.CODE_39
    ]
});

This way the barcodes scan correctly in both BarcodeDetector and zxing.