@@ -21,24 +21,44 @@ declare global {
21
21
let barcodeDetector : BarcodeDetector
22
22
23
23
/**
24
- * Seamlessly updates the set of used barcode formats during scanning.
24
+ * Constructs a `BarcodeDetector` instance, given a list of targeted barcode formats.
25
+ * Preferably, we want to use the native `BarcodeDetector` implementation if supported.
26
+ * Otherwise, we fall back to the polyfill implementation.
27
+ *
28
+ * Note, that we can't just monkey patch the polyfill on load, i.e.
29
+ *
30
+ * window.BarcodeDetector ??= BarcodeDetector
31
+ *
32
+ * for two reasons. Firstly, this is not SSR compatible, because `window` is not available
33
+ * during SSR. Secondly, even if the native implementation is availabe, we still might
34
+ * want to use the polyfill. For example, if the native implementation only supports the
35
+ * format `"qr_code"` but the user wants to scan `["qr_code", "aztec"]` (see #450).
25
36
*/
26
- export function setScanningFormats ( formats : BarcodeFormat [ ] ) {
27
- // Only use the `BarcodeDetector` polyfill if the API is not supported natively.
28
- //
29
- // Note, that we can't just monkey patch the API on load, i.e.
30
- //
31
- // globalThis.BarcodeDetector ??= BarcodeDetector
32
- //
33
- // because that is not SSR compatible. If the polyfill is applied during SSR, then
34
- // it's actually missing at runtime. Thus, we have to check the API support at runtime:
37
+ async function createBarcodeDetector ( formats : BarcodeFormat [ ] ) : Promise < BarcodeDetector > {
35
38
if ( window . BarcodeDetector === undefined ) {
36
- console . debug ( '[vue-qrcode-reader] BarcodeDetector not available: will use polyfill.' )
37
- barcodeDetector = new BarcodeDetector ( { formats } )
38
- } else {
39
- console . debug ( '[vue-qrcode-reader] BarcodeDetector available: will use native API.' )
40
- barcodeDetector = new window . BarcodeDetector ( { formats } )
39
+ console . debug ( '[vue-qrcode-reader] Native BarcodeDetector not supported. Will use polyfill.' )
40
+ return new BarcodeDetector ( { formats } )
41
+ }
42
+
43
+ const allSupportedFormats = await window . BarcodeDetector . getSupportedFormats ( )
44
+ const unsupportedFormats = formats . filter ( format => ! allSupportedFormats . includes ( format ) )
45
+
46
+ if ( unsupportedFormats . length > 0 ) {
47
+ console . debug ( `[vue-qrcode-reader] Native BarcodeDetector does not support formats ${ JSON . stringify ( unsupportedFormats ) } . Will use polyfill.` )
48
+ return new BarcodeDetector ( { formats } )
41
49
}
50
+
51
+ console . debug ( '[vue-qrcode-reader] Will use native BarcodeDetector.' )
52
+ return new window . BarcodeDetector ( { formats } )
53
+ }
54
+
55
+ /**
56
+ * Update the set of targeted barcode formats. In particular, this function
57
+ * can be called during scanning and the camera stream doesn't have to be
58
+ * interrupted.
59
+ */
60
+ export async function setScanningFormats ( formats : BarcodeFormat [ ] ) {
61
+ barcodeDetector = await createBarcodeDetector ( formats )
42
62
}
43
63
44
64
type ScanHandler = ( _ : DetectedBarcode [ ] ) => void
@@ -62,7 +82,7 @@ export const keepScanning = async (
62
82
}
63
83
) => {
64
84
console . debug ( '[vue-qrcode-reader] start scanning' )
65
- setScanningFormats ( formats )
85
+ await setScanningFormats ( formats )
66
86
67
87
const processFrame =
68
88
( state : { lastScanned : number ; contentBefore : string [ ] ; lastScanHadContent : boolean } ) =>
0 commit comments