17
17
/* !
18
18
* Copyright (c) 2024-2025 Digital Bazaar, Inc. All rights reserved.
19
19
*/
20
- import {_detectBarcode , _mapFormats } from ' ../lib/helpers ' ;
21
- import { Html5Qrcode , Html5QrcodeScannerState } from ' html5-qrcode' ;
20
+ import {Html5Qrcode , Html5QrcodeScannerState , Html5QrcodeSupportedFormats }
21
+ from ' html5-qrcode' ;
22
22
import {inject , onMounted , onUnmounted , reactive , ref } from ' vue' ;
23
+ import {detectBarcodes } from ' ../lib/barcodes.js' ;
23
24
import ScannerUI from ' ./ScannerUI.vue' ;
24
25
import {useQuasar } from ' quasar' ;
25
26
@@ -47,6 +48,7 @@ export default {
47
48
48
49
// Constants
49
50
let scanner = null ;
51
+ const abortController = new AbortController ();
50
52
51
53
// Refs
52
54
const cameraList = ref ([]);
@@ -130,6 +132,7 @@ export default {
130
132
// Helper functions
131
133
function handleClose () {
132
134
emit (' close' );
135
+ abortController .abort ();
133
136
}
134
137
135
138
// Toggle camera light on and off
@@ -153,13 +156,11 @@ export default {
153
156
}
154
157
155
158
async function emitScanResult ({barcodeDetector, video}) {
156
- const result = await _detectBarcode ({barcodeDetector, video});
159
+ const {signal } = abortController;
160
+ const barcodes = await detectBarcodes ({barcodeDetector, video, signal});
161
+ const [result ] = barcodes;
157
162
if (result? .format && result? .rawValue ) {
158
163
emit (' result' , {type: result .format , text: result .rawValue });
159
- } else {
160
- video .requestVideoFrameCallback (() => {
161
- emitScanResult ({barcodeDetector, video});
162
- });
163
164
}
164
165
}
165
166
@@ -197,7 +198,9 @@ export default {
197
198
}
198
199
199
200
function onError (error ) {
200
- console .error (' BarcodeScanner error:' , error);
201
+ if (! String (error).startsWith (' QR code parse error' )) {
202
+ console .error (' BarcodeScanner error:' , error);
203
+ }
201
204
}
202
205
203
206
function getCameraScanConfig () {
@@ -264,6 +267,42 @@ export default {
264
267
};
265
268
}
266
269
};
270
+
271
+ // see: `BarcodeFormat`
272
+ // https://wicg.github.io/shape-detection-api/#enumdef-barcodeformat
273
+ const FORMAT_MAP = new Map ([
274
+ [' aztec' , Html5QrcodeSupportedFormats .AZTEC ],
275
+ [' code_128' , Html5QrcodeSupportedFormats .CODE_128 ],
276
+ [' code_39' , Html5QrcodeSupportedFormats .CODE_39 ],
277
+ [' code_93' , Html5QrcodeSupportedFormats .CODE_93 ],
278
+ [' codabar' , Html5QrcodeSupportedFormats .CODABAR ],
279
+ [' data_matrix' , Html5QrcodeSupportedFormats .DATA_MATRIX ],
280
+ [' ean_13' , Html5QrcodeSupportedFormats .EAN_13 ],
281
+ [' ean_8' , Html5QrcodeSupportedFormats .EAN_8 ],
282
+ [' itf' , Html5QrcodeSupportedFormats .ITF ],
283
+ [' pdf417' , Html5QrcodeSupportedFormats .PDF_417 ],
284
+ [' qr_code' , Html5QrcodeSupportedFormats .QR_CODE ],
285
+ [' upc_a' , Html5QrcodeSupportedFormats .UPC_A ],
286
+ [' upc_e' , Html5QrcodeSupportedFormats .UPC_E ],
287
+ ]);
288
+
289
+ // map from Web-native format to `Html5QrcodeSupportedFormats`
290
+ export function _mapFormats (formats ) {
291
+ return formats .map (format => {
292
+ const result = FORMAT_MAP .get (format);
293
+ if (result === undefined ) {
294
+ if (typeof result !== ' string' || ! isNaN (Number .parseInt (result, 10 ))) {
295
+ throw new TypeError (
296
+ ` Unsupported format "${ format} "; ` +
297
+ ' a string supported by the "BarcodeFormat" enumeration ' +
298
+ ' must be given, e.g., "qr_code", not a number.'
299
+ );
300
+ }
301
+ throw new TypeError (` Unsupported format "${ format} ".` );
302
+ }
303
+ return result;
304
+ });
305
+ }
267
306
< / script>
268
307
269
308
< style>
0 commit comments