Blog/Components/Pages/QRCodeScan.razor.js 2.9 K · 96 lines · raw · history

1 import { getById, writeError, writeInfo, h } from "/common.module.js";
2
3 // regexr.com/2rj36
4 const url_like_regex =
5 /^[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?$/i;
6
7 ///https://stackoverflow.com/questions/3115982/how-to-check-if-two-arrays-are-equal-with-javascript
8 function arraysEqual(a, b) {
9 if (a === b) return true;
10 if (a == null || b == null) return false;
11 if (a.length !== b.length) return false;
12
13 for (let i = 0; i < a.length; ++i) {
14 if (a[i] !== b[i]) return false;
15 }
16 return true;
17 }
18
19 function logQRValue(value) {
20 if (URL.canParse(value)) {
21 writeInfo([h("a", { href: new URL(value).href }, value)]);
22 } else if (url_like_regex.test(value)) {
23 // Not a true URL but close enough for me to create an anchor tag.
24 if (!value.startsWith("http://") && !value.startsWith("https://")) {
25 value = "https://" + value;
26 }
27 writeInfo([h("a", { href: value }, value)]);
28 } else {
29 writeInfo(value);
30 }
31 }
32
33 // check compatibility
34 if (!("BarcodeDetector" in globalThis)) {
35 writeError(
36 "Barcode Detector is not supported by this browser. Make sure Shape Detection API is turned on.",
37 );
38 } else {
39 writeInfo("Barcode Detector supported!");
40
41 // create new detector
42 const barcodeDetector = new BarcodeDetector({
43 formats: ["qr_code"],
44 });
45
46 const initBarcodescan = (stream) => {
47 writeInfo("Starting scanner...");
48 let lastbarcodes = [];
49 setInterval(() => {
50 barcodeDetector
51 .detect(stream)
52 .then((barcodes) => {
53 if (barcodes.length === 0) {
54 } else {
55 const values = barcodes.map(
56 (barcode) => barcode.rawValue,
57 );
58 if (arraysEqual(values, lastbarcodes)) {
59 return;
60 }
61
62 values.forEach(logQRValue);
63 lastbarcodes = values;
64 }
65 })
66 .catch((err) => {
67 writeError(err);
68 });
69 }, 1000);
70 };
71
72 const video = getById("video");
73 video.setAttribute("playsinline", "");
74 video.setAttribute("autoplay", "");
75 video.setAttribute("muted", "");
76
77 /* Setting up the constraint */
78 const facingMode = "environment"; // Can be 'user' or 'environment' to access back or front camera (NEAT!)
79 const constraints = {
80 audio: false,
81 video: {
82 facingMode: facingMode,
83 },
84 };
85
86 /* Stream it to video element */
87 navigator.mediaDevices
88 .getUserMedia(constraints)
89 .then(function success(stream) {
90 video.srcObject = stream;
91 })
92 .finally(() => {
93 writeInfo("Initialized video stream");
94 initBarcodescan(video);
95 });
96 }