Skip to content

Commit 545f7fa

Browse files
committed
Refactor detectBarcodes function.
1 parent 1a3aeef commit 545f7fa

File tree

3 files changed

+73
-62
lines changed

3 files changed

+73
-62
lines changed

components/BarcodeScanner.vue

+47-8
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
/*!
1818
* Copyright (c) 2024-2025 Digital Bazaar, Inc. All rights reserved.
1919
*/
20-
import {_detectBarcode, _mapFormats} from '../lib/helpers';
21-
import {Html5Qrcode, Html5QrcodeScannerState} from 'html5-qrcode';
20+
import {Html5Qrcode, Html5QrcodeScannerState, Html5QrcodeSupportedFormats}
21+
from 'html5-qrcode';
2222
import {inject, onMounted, onUnmounted, reactive, ref} from 'vue';
23+
import {detectBarcodes} from '../lib/barcodes.js';
2324
import ScannerUI from './ScannerUI.vue';
2425
import {useQuasar} from 'quasar';
2526
@@ -47,6 +48,7 @@ export default {
4748
4849
// Constants
4950
let scanner = null;
51+
const abortController = new AbortController();
5052
5153
// Refs
5254
const cameraList = ref([]);
@@ -130,6 +132,7 @@ export default {
130132
// Helper functions
131133
function handleClose() {
132134
emit('close');
135+
abortController.abort();
133136
}
134137
135138
// Toggle camera light on and off
@@ -153,13 +156,11 @@ export default {
153156
}
154157
155158
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;
157162
if(result?.format && result?.rawValue) {
158163
emit('result', {type: result.format, text: result.rawValue});
159-
} else {
160-
video.requestVideoFrameCallback(() => {
161-
emitScanResult({barcodeDetector, video});
162-
});
163164
}
164165
}
165166
@@ -197,7 +198,9 @@ export default {
197198
}
198199
199200
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+
}
201204
}
202205
203206
function getCameraScanConfig() {
@@ -264,6 +267,42 @@ export default {
264267
};
265268
}
266269
};
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+
}
267306
</script>
268307
269308
<style>

lib/barcodes.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export function detectBarcodes({barcodeDetector, video, signal} = {}) {
2+
return new Promise((resolve, reject) => {
3+
// schedule barcode detection
4+
video.requestVideoFrameCallback(() => _detect({
5+
barcodeDetector, video, signal, resolve, reject
6+
}));
7+
});
8+
}
9+
10+
async function _detect({barcodeDetector, video, signal, resolve, reject}) {
11+
try {
12+
// detect barcodes in the current video frame
13+
const barcodes = await barcodeDetector.detect(video);
14+
if(barcodes.length > 0) {
15+
return resolve(barcodes);
16+
}
17+
// abort as needed
18+
signal?.throwIfAborted();
19+
// no barcodes found, schedule to try again
20+
video.requestVideoFrameCallback(() => _detect({
21+
barcodeDetector, video, signal, resolve, reject
22+
}));
23+
} catch(error) {
24+
reject(error);
25+
}
26+
}

lib/helpers.js

-54
This file was deleted.

0 commit comments

Comments
 (0)