Identify scan requests to worker by unique id's

This avoids that parallel scans on the same worker instance ALL interpret
the first incoming scan result as their result. Instead, now each scan
request to the worker waits for their individual response.

Fixes #149
This commit is contained in:
Daniel committed 2022-02-22 23:27:02 +01:00
1 parent 9373237718
commit 2714cb9944
11 files changed
+110 -85

No files matched your search

+1 -1
View File
@@ -166,7 +166,7 @@
}
QrScanner.scanImage(file, { returnDetailedScanResult: true })
.then(result => setResult(fileQrResult, result))
.catch(e => setResult(fileQrResult, e || 'No QR code found.'));
.catch(e => setResult(fileQrResult, { data: e || 'No QR code found.' }));
});
</script>
+2 -2
View File
@@ -93,6 +93,6 @@ function X(a,b,c,d={}){let e=Object.create(null);W(e,ta);W(e,d);d="onlyInvert"==
g.blue*a[r+2]+128>>8)}else for(n=0;n<c;n++)for(q=0;q<b;q++)r=4*(n*b+q),l.set(q,n,g.red*a[r]+g.green*a[r+1]+g.blue*a[r+2]);g=Math.ceil(b/8);n=Math.ceil(c/8);q=g*n;if(h){var u=new Uint8ClampedArray(a.buffer,m,q);m+=q}u=new A(g,n,u);for(q=0;q<n;q++)for(r=0;r<g;r++){var p=Infinity,t=0;for(var v=0;8>v;v++)for(let w=0;8>w;w++){let aa=l.get(8*r+w,8*q+v);p=Math.min(p,aa);t=Math.max(t,aa)}v=(p+t)/2;v=Math.min(255,1.11*v);24>=t-p&&(v=p/2,0<q&&0<r&&(t=(u.get(r,q-1)+2*u.get(r-1,q)+u.get(r-1,q-1))/4,p<t&&(v=t)));
u.set(r,q,v)}h?(q=new Uint8ClampedArray(a.buffer,m,k),m+=k,q=new x(q,b)):q=x.createEmpty(b,c);r=null;f&&(h?(a=new Uint8ClampedArray(a.buffer,m,k),r=new x(a,b)):r=x.createEmpty(b,c));for(b=0;b<n;b++)for(a=0;a<g;a++){c=g-3;c=2>a?2:a>c?c:a;h=n-3;h=2>b?2:b>h?h:b;k=0;for(m=-2;2>=m;m++)for(p=-2;2>=p;p++)k+=u.get(c+m,h+p);c=k/25;for(h=0;8>h;h++)for(k=0;8>k;k++)m=8*a+h,p=8*b+k,t=l.get(m,p),q.set(m,p,t<=c),f&&r.set(m,p,!(t<=c))}f=f?{binarized:q,inverted:r}:{binarized:q};let {binarized:z,inverted:y}=f;(f=V(d?
y:z))||"attemptBoth"!==e.inversionAttempts&&"invertFirst"!==e.inversionAttempts||(f=V(d?z:y));return f}X.default=X;let Y="dontInvert",Z={red:77,green:150,blue:29,useIntegerApproximation:!0};
self.onmessage=a=>{let b=a.data.data;switch(a.data.type){case "decode":(a=X(b.data,b.width,b.height,{inversionAttempts:Y,greyScaleWeights:Z}))?self.postMessage({type:"qrResult",data:a.data,cornerPoints:[a.location.topLeftCorner,a.location.topRightCorner,a.location.bottomRightCorner,a.location.bottomLeftCorner]}):self.postMessage({type:"qrResult",data:null});break;case "grayscaleWeights":Z.red=b.red;Z.green=b.green;Z.blue=b.blue;Z.useIntegerApproximation=b.useIntegerApproximation;break;case "inversionMode":switch(b){case "original":Y=
"dontInvert";break;case "invert":Y="onlyInvert";break;case "both":Y="attemptBoth";break;default:throw Error("Invalid inversion mode");}break;case "close":self.close()}}
self.onmessage=a=>{let b=a.data.id,c=a.data.data;switch(a.data.type){case "decode":(a=X(c.data,c.width,c.height,{inversionAttempts:Y,greyScaleWeights:Z}))?self.postMessage({id:b,type:"qrResult",data:a.data,cornerPoints:[a.location.topLeftCorner,a.location.topRightCorner,a.location.bottomRightCorner,a.location.bottomLeftCorner]}):self.postMessage({id:b,type:"qrResult",data:null});break;case "grayscaleWeights":Z.red=c.red;Z.green=c.green;Z.blue=c.blue;Z.useIntegerApproximation=c.useIntegerApproximation;
break;case "inversionMode":switch(c){case "original":Y="dontInvert";break;case "invert":Y="onlyInvert";break;case "both":Y="attemptBoth";break;default:throw Error("Invalid inversion mode");}break;case "close":self.close()}}
`]),{type:"application/javascript"}))//# sourceMappingURL=qr-scanner-worker.min.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"qr-scanner-worker.min.js","sources":["node_modules/jsqr-es6/src/BitMatrix.ts","node_modules/jsqr-es6/src/binarizer/index.ts","node_modules/jsqr-es6/src/decoder/decodeData/BitStream.ts","node_modules/jsqr-es6/src/decoder/decodeData/index.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/GenericGFPoly.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/GenericGF.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/index.ts","node_modules/jsqr-es6/src/decoder/version.ts","node_modules/jsqr-es6/src/decoder/decoder.ts","node_modules/jsqr-es6/src/extractor/index.ts","node_modules/jsqr-es6/src/locator/index.ts","node_modules/jsqr-es6/src/index.ts","src/worker.ts"],"sourcesContent":["export class BitMatrix {\n public static createEmpty(width: number, height: number) {\n return new BitMatrix(new Uint8ClampedArray(width * height), width);\n }\n\n public width: number;\n public height: number;\n private data: Uint8ClampedArray;\n\n constructor(data: Uint8ClampedArray, width: number) {\n this.width = width;\n this.height = data.length / width;\n this.data = data;\n }\n\n public get(x: number, y: number): boolean {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) {\n return false;\n }\n return !!this.data[y * this.width + x];\n }\n\n public set(x: number, y: number, v: boolean) {\n this.data[y * this.width + x] = v ? 1 : 0;\n }\n\n public setRegion(left: number, top: number, width: number, height: number, v: boolean) {\n for (let y = top; y < top + height; y++) {\n for (let x = left; x < left + width; x++) {\n this.set(x, y, !!v);\n }\n }\n }\n}\n","import {BitMatrix} from \"../BitMatrix\";\nimport {GreyscaleWeights} from \"../index\";\n\nconst REGION_SIZE = 8;\nconst MIN_DYNAMIC_RANGE = 24;\n\nfunction numBetween(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n\n// Like BitMatrix but accepts arbitry Uint8 values\nclass Matrix {\n private data: Uint8ClampedArray;\n private width: number;\n constructor(width: number, height: number, buffer?: Uint8ClampedArray) {\n this.width = width;\n const bufferSize = width * height;\n if (buffer && buffer.length !== bufferSize) {\n throw new Error(\"Wrong buffer size\");\n }\n this.data = buffer || new Uint8ClampedArray(bufferSize);\n }\n public get(x: number, y: number) {\n return this.data[y * this.width + x];\n }\n public set(x: number, y: number, value: number) {\n this.data[y * this.width + x] = value;\n }\n}\n\nexport function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean,\n greyscaleWeights: GreyscaleWeights, canOverwriteImage: boolean) {\n const pixelCount = width * height;\n if (data.length !== pixelCount * 4) {\n throw new Error(\"Malformed data passed to binarizer.\");\n }\n // assign the greyscale and binary image within the rgba buffer as the rgba image will not be needed after conversion\n let bufferOffset = 0;\n // Convert image to greyscale\n let greyscaleBuffer: Uint8ClampedArray;\n if (canOverwriteImage) {\n greyscaleBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount);\n bufferOffset += pixelCount;\n }\n const greyscalePixels = new Matrix(width, height, greyscaleBuffer);\n if (greyscaleWeights.useIntegerApproximation) {\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const pixelPosition = (y * width + x) * 4;\n const r = data[pixelPosition];\n const g = data[pixelPosition + 1];\n const b = data[pixelPosition + 2];\n greyscalePixels.set(x, y,\n // tslint:disable-next-line no-bitwise\n (greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b + 128) >> 8);\n }\n }\n } else {\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const pixelPosition = (y * width + x) * 4;\n const r = data[pixelPosition];\n const g = data[pixelPosition + 1];\n const b = data[pixelPosition + 2];\n greyscalePixels.set(x, y,\n greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b);\n }\n }\n }\n const horizontalRegionCount = Math.ceil(width / REGION_SIZE);\n const verticalRegionCount = Math.ceil(height / REGION_SIZE);\n const blackPointsCount = horizontalRegionCount * verticalRegionCount;\n\n let blackPointsBuffer: Uint8ClampedArray;\n if (canOverwriteImage) {\n blackPointsBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, blackPointsCount);\n bufferOffset += blackPointsCount;\n }\n const blackPoints = new Matrix(horizontalRegionCount, verticalRegionCount, blackPointsBuffer);\n for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {\n for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizLine truncated
{"version":3,"file":"qr-scanner-worker.min.js","sources":["node_modules/jsqr-es6/src/BitMatrix.ts","node_modules/jsqr-es6/src/binarizer/index.ts","node_modules/jsqr-es6/src/decoder/decodeData/BitStream.ts","node_modules/jsqr-es6/src/decoder/decodeData/index.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/GenericGFPoly.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/GenericGF.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/index.ts","node_modules/jsqr-es6/src/decoder/version.ts","node_modules/jsqr-es6/src/decoder/decoder.ts","node_modules/jsqr-es6/src/extractor/index.ts","node_modules/jsqr-es6/src/locator/index.ts","node_modules/jsqr-es6/src/index.ts","src/worker.ts"],"sourcesContent":["export class BitMatrix {\n public static createEmpty(width: number, height: number) {\n return new BitMatrix(new Uint8ClampedArray(width * height), width);\n }\n\n public width: number;\n public height: number;\n private data: Uint8ClampedArray;\n\n constructor(data: Uint8ClampedArray, width: number) {\n this.width = width;\n this.height = data.length / width;\n this.data = data;\n }\n\n public get(x: number, y: number): boolean {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) {\n return false;\n }\n return !!this.data[y * this.width + x];\n }\n\n public set(x: number, y: number, v: boolean) {\n this.data[y * this.width + x] = v ? 1 : 0;\n }\n\n public setRegion(left: number, top: number, width: number, height: number, v: boolean) {\n for (let y = top; y < top + height; y++) {\n for (let x = left; x < left + width; x++) {\n this.set(x, y, !!v);\n }\n }\n }\n}\n","import {BitMatrix} from \"../BitMatrix\";\nimport {GreyscaleWeights} from \"../index\";\n\nconst REGION_SIZE = 8;\nconst MIN_DYNAMIC_RANGE = 24;\n\nfunction numBetween(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n\n// Like BitMatrix but accepts arbitry Uint8 values\nclass Matrix {\n private data: Uint8ClampedArray;\n private width: number;\n constructor(width: number, height: number, buffer?: Uint8ClampedArray) {\n this.width = width;\n const bufferSize = width * height;\n if (buffer && buffer.length !== bufferSize) {\n throw new Error(\"Wrong buffer size\");\n }\n this.data = buffer || new Uint8ClampedArray(bufferSize);\n }\n public get(x: number, y: number) {\n return this.data[y * this.width + x];\n }\n public set(x: number, y: number, value: number) {\n this.data[y * this.width + x] = value;\n }\n}\n\nexport function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean,\n greyscaleWeights: GreyscaleWeights, canOverwriteImage: boolean) {\n const pixelCount = width * height;\n if (data.length !== pixelCount * 4) {\n throw new Error(\"Malformed data passed to binarizer.\");\n }\n // assign the greyscale and binary image within the rgba buffer as the rgba image will not be needed after conversion\n let bufferOffset = 0;\n // Convert image to greyscale\n let greyscaleBuffer: Uint8ClampedArray;\n if (canOverwriteImage) {\n greyscaleBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount);\n bufferOffset += pixelCount;\n }\n const greyscalePixels = new Matrix(width, height, greyscaleBuffer);\n if (greyscaleWeights.useIntegerApproximation) {\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const pixelPosition = (y * width + x) * 4;\n const r = data[pixelPosition];\n const g = data[pixelPosition + 1];\n const b = data[pixelPosition + 2];\n greyscalePixels.set(x, y,\n // tslint:disable-next-line no-bitwise\n (greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b + 128) >> 8);\n }\n }\n } else {\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const pixelPosition = (y * width + x) * 4;\n const r = data[pixelPosition];\n const g = data[pixelPosition + 1];\n const b = data[pixelPosition + 2];\n greyscalePixels.set(x, y,\n greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b);\n }\n }\n }\n const horizontalRegionCount = Math.ceil(width / REGION_SIZE);\n const verticalRegionCount = Math.ceil(height / REGION_SIZE);\n const blackPointsCount = horizontalRegionCount * verticalRegionCount;\n\n let blackPointsBuffer: Uint8ClampedArray;\n if (canOverwriteImage) {\n blackPointsBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, blackPointsCount);\n bufferOffset += blackPointsCount;\n }\n const blackPoints = new Matrix(horizontalRegionCount, verticalRegionCount, blackPointsBuffer);\n for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {\n for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizLine truncated
+52 -52
View File
@@ -1,55 +1,55 @@
'use strict';var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.ISOLATE_POLYFILLS=!1;$jscomp.FORCE_POLYFILL_PROMISE=!1;$jscomp.FORCE_POLYFILL_PROMISE_WHEN_NO_UNHANDLED_REJECTION=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(c,e,a){if(c==Array.prototype||c==Object.prototype)return c;c[e]=a.value;return c};
$jscomp.getGlobal=function(c){c=["object"==typeof globalThis&&globalThis,c,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var e=0;e<c.length;++e){var a=c[e];if(a&&a.Math==Math)return a}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this);$jscomp.IS_SYMBOL_NATIVE="function"===typeof Symbol&&"symbol"===typeof Symbol("x");$jscomp.TRUST_ES6_POLYFILLS=!$jscomp.ISOLATE_POLYFILLS||$jscomp.IS_SYMBOL_NATIVE;$jscomp.polyfills={};
$jscomp.propertyToPolyfillSymbol={};$jscomp.POLYFILL_PREFIX="$jscp$";var $jscomp$lookupPolyfilledValue=function(c,e){var a=$jscomp.propertyToPolyfillSymbol[e];if(null==a)return c[e];a=c[a];return void 0!==a?a:c[e]};$jscomp.polyfill=function(c,e,a,b){e&&($jscomp.ISOLATE_POLYFILLS?$jscomp.polyfillIsolated(c,e,a,b):$jscomp.polyfillUnisolated(c,e,a,b))};
$jscomp.polyfillUnisolated=function(c,e,a,b){a=$jscomp.global;c=c.split(".");for(b=0;b<c.length-1;b++){var d=c[b];if(!(d in a))return;a=a[d]}c=c[c.length-1];b=a[c];e=e(b);e!=b&&null!=e&&$jscomp.defineProperty(a,c,{configurable:!0,writable:!0,value:e})};
$jscomp.polyfillIsolated=function(c,e,a,b){var d=c.split(".");c=1===d.length;b=d[0];b=!c&&b in $jscomp.polyfills?$jscomp.polyfills:$jscomp.global;for(var f=0;f<d.length-1;f++){var g=d[f];if(!(g in b))return;b=b[g]}d=d[d.length-1];a=$jscomp.IS_SYMBOL_NATIVE&&"es6"===a?b[d]:null;e=e(a);null!=e&&(c?$jscomp.defineProperty($jscomp.polyfills,d,{configurable:!0,writable:!0,value:e}):e!==a&&(void 0===$jscomp.propertyToPolyfillSymbol[d]&&(a=1E9*Math.random()>>>0,$jscomp.propertyToPolyfillSymbol[d]=$jscomp.IS_SYMBOL_NATIVE?
$jscomp.global.Symbol(d):$jscomp.POLYFILL_PREFIX+a+"$"+d),$jscomp.defineProperty(b,$jscomp.propertyToPolyfillSymbol[d],{configurable:!0,writable:!0,value:e})))};$jscomp.underscoreProtoCanBeSet=function(){var c={a:!0},e={};try{return e.__proto__=c,e.a}catch(a){}return!1};
$jscomp.setPrototypeOf=$jscomp.TRUST_ES6_POLYFILLS&&"function"==typeof Object.setPrototypeOf?Object.setPrototypeOf:$jscomp.underscoreProtoCanBeSet()?function(c,e){c.__proto__=e;if(c.__proto__!==e)throw new TypeError(c+" is not extensible");return c}:null;$jscomp.arrayIteratorImpl=function(c){var e=0;return function(){return e<c.length?{done:!1,value:c[e++]}:{done:!0}}};$jscomp.arrayIterator=function(c){return{next:$jscomp.arrayIteratorImpl(c)}};
$jscomp.makeIterator=function(c){var e="undefined"!=typeof Symbol&&Symbol.iterator&&c[Symbol.iterator];return e?e.call(c):$jscomp.arrayIterator(c)};$jscomp.generator={};$jscomp.generator.ensureIteratorResultIsObject_=function(c){if(!(c instanceof Object))throw new TypeError("Iterator result "+c+" is not an object");};
'use strict';var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.ISOLATE_POLYFILLS=!1;$jscomp.FORCE_POLYFILL_PROMISE=!1;$jscomp.FORCE_POLYFILL_PROMISE_WHEN_NO_UNHANDLED_REJECTION=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(b,e,a){if(b==Array.prototype||b==Object.prototype)return b;b[e]=a.value;return b};
$jscomp.getGlobal=function(b){b=["object"==typeof globalThis&&globalThis,b,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var e=0;e<b.length;++e){var a=b[e];if(a&&a.Math==Math)return a}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this);$jscomp.IS_SYMBOL_NATIVE="function"===typeof Symbol&&"symbol"===typeof Symbol("x");$jscomp.TRUST_ES6_POLYFILLS=!$jscomp.ISOLATE_POLYFILLS||$jscomp.IS_SYMBOL_NATIVE;$jscomp.polyfills={};
$jscomp.propertyToPolyfillSymbol={};$jscomp.POLYFILL_PREFIX="$jscp$";var $jscomp$lookupPolyfilledValue=function(b,e){var a=$jscomp.propertyToPolyfillSymbol[e];if(null==a)return b[e];a=b[a];return void 0!==a?a:b[e]};$jscomp.polyfill=function(b,e,a,c){e&&($jscomp.ISOLATE_POLYFILLS?$jscomp.polyfillIsolated(b,e,a,c):$jscomp.polyfillUnisolated(b,e,a,c))};
$jscomp.polyfillUnisolated=function(b,e,a,c){a=$jscomp.global;b=b.split(".");for(c=0;c<b.length-1;c++){var d=b[c];if(!(d in a))return;a=a[d]}b=b[b.length-1];c=a[b];e=e(c);e!=c&&null!=e&&$jscomp.defineProperty(a,b,{configurable:!0,writable:!0,value:e})};
$jscomp.polyfillIsolated=function(b,e,a,c){var d=b.split(".");b=1===d.length;c=d[0];c=!b&&c in $jscomp.polyfills?$jscomp.polyfills:$jscomp.global;for(var f=0;f<d.length-1;f++){var g=d[f];if(!(g in c))return;c=c[g]}d=d[d.length-1];a=$jscomp.IS_SYMBOL_NATIVE&&"es6"===a?c[d]:null;e=e(a);null!=e&&(b?$jscomp.defineProperty($jscomp.polyfills,d,{configurable:!0,writable:!0,value:e}):e!==a&&(void 0===$jscomp.propertyToPolyfillSymbol[d]&&(a=1E9*Math.random()>>>0,$jscomp.propertyToPolyfillSymbol[d]=$jscomp.IS_SYMBOL_NATIVE?
$jscomp.global.Symbol(d):$jscomp.POLYFILL_PREFIX+a+"$"+d),$jscomp.defineProperty(c,$jscomp.propertyToPolyfillSymbol[d],{configurable:!0,writable:!0,value:e})))};$jscomp.underscoreProtoCanBeSet=function(){var b={a:!0},e={};try{return e.__proto__=b,e.a}catch(a){}return!1};
$jscomp.setPrototypeOf=$jscomp.TRUST_ES6_POLYFILLS&&"function"==typeof Object.setPrototypeOf?Object.setPrototypeOf:$jscomp.underscoreProtoCanBeSet()?function(b,e){b.__proto__=e;if(b.__proto__!==e)throw new TypeError(b+" is not extensible");return b}:null;$jscomp.arrayIteratorImpl=function(b){var e=0;return function(){return e<b.length?{done:!1,value:b[e++]}:{done:!0}}};$jscomp.arrayIterator=function(b){return{next:$jscomp.arrayIteratorImpl(b)}};
$jscomp.makeIterator=function(b){var e="undefined"!=typeof Symbol&&Symbol.iterator&&b[Symbol.iterator];return e?e.call(b):$jscomp.arrayIterator(b)};$jscomp.generator={};$jscomp.generator.ensureIteratorResultIsObject_=function(b){if(!(b instanceof Object))throw new TypeError("Iterator result "+b+" is not an object");};
$jscomp.generator.Context=function(){this.isRunning_=!1;this.yieldAllIterator_=null;this.yieldResult=void 0;this.nextAddress=1;this.finallyAddress_=this.catchAddress_=0;this.finallyContexts_=this.abruptCompletion_=null};$jscomp.generator.Context.prototype.start_=function(){if(this.isRunning_)throw new TypeError("Generator is already running");this.isRunning_=!0};$jscomp.generator.Context.prototype.stop_=function(){this.isRunning_=!1};
$jscomp.generator.Context.prototype.jumpToErrorHandler_=function(){this.nextAddress=this.catchAddress_||this.finallyAddress_};$jscomp.generator.Context.prototype.next_=function(c){this.yieldResult=c};$jscomp.generator.Context.prototype.throw_=function(c){this.abruptCompletion_={exception:c,isException:!0};this.jumpToErrorHandler_()};$jscomp.generator.Context.prototype.return=function(c){this.abruptCompletion_={return:c};this.nextAddress=this.finallyAddress_};
$jscomp.generator.Context.prototype.jumpThroughFinallyBlocks=function(c){this.abruptCompletion_={jumpTo:c};this.nextAddress=this.finallyAddress_};$jscomp.generator.Context.prototype.yield=function(c,e){this.nextAddress=e;return{value:c}};$jscomp.generator.Context.prototype.yieldAll=function(c,e){c=$jscomp.makeIterator(c);var a=c.next();$jscomp.generator.ensureIteratorResultIsObject_(a);if(a.done)this.yieldResult=a.value,this.nextAddress=e;else return this.yieldAllIterator_=c,this.yield(a.value,e)};
$jscomp.generator.Context.prototype.jumpTo=function(c){this.nextAddress=c};$jscomp.generator.Context.prototype.jumpToEnd=function(){this.nextAddress=0};$jscomp.generator.Context.prototype.setCatchFinallyBlocks=function(c,e){this.catchAddress_=c;void 0!=e&&(this.finallyAddress_=e)};$jscomp.generator.Context.prototype.setFinallyBlock=function(c){this.catchAddress_=0;this.finallyAddress_=c||0};$jscomp.generator.Context.prototype.leaveTryBlock=function(c,e){this.nextAddress=c;this.catchAddress_=e||0};
$jscomp.generator.Context.prototype.enterCatchBlock=function(c){this.catchAddress_=c||0;c=this.abruptCompletion_.exception;this.abruptCompletion_=null;return c};$jscomp.generator.Context.prototype.enterFinallyBlock=function(c,e,a){a?this.finallyContexts_[a]=this.abruptCompletion_:this.finallyContexts_=[this.abruptCompletion_];this.catchAddress_=c||0;this.finallyAddress_=e||0};
$jscomp.generator.Context.prototype.leaveFinallyBlock=function(c,e){e=this.finallyContexts_.splice(e||0)[0];if(e=this.abruptCompletion_=this.abruptCompletion_||e){if(e.isException)return this.jumpToErrorHandler_();void 0!=e.jumpTo&&this.finallyAddress_<e.jumpTo?(this.nextAddress=e.jumpTo,this.abruptCompletion_=null):this.nextAddress=this.finallyAddress_}else this.nextAddress=c};$jscomp.generator.Context.prototype.forIn=function(c){return new $jscomp.generator.Context.PropertyIterator(c)};
$jscomp.generator.Context.PropertyIterator=function(c){this.object_=c;this.properties_=[];for(var e in c)this.properties_.push(e);this.properties_.reverse()};$jscomp.generator.Context.PropertyIterator.prototype.getNext=function(){for(;0<this.properties_.length;){var c=this.properties_.pop();if(c in this.object_)return c}return null};$jscomp.generator.Engine_=function(c){this.context_=new $jscomp.generator.Context;this.program_=c};
$jscomp.generator.Engine_.prototype.next_=function(c){this.context_.start_();if(this.context_.yieldAllIterator_)return this.yieldAllStep_(this.context_.yieldAllIterator_.next,c,this.context_.next_);this.context_.next_(c);return this.nextStep_()};
$jscomp.generator.Engine_.prototype.return_=function(c){this.context_.start_();var e=this.context_.yieldAllIterator_;if(e)return this.yieldAllStep_("return"in e?e["return"]:function(a){return{value:a,done:!0}},c,this.context_.return);this.context_.return(c);return this.nextStep_()};
$jscomp.generator.Engine_.prototype.throw_=function(c){this.context_.start_();if(this.context_.yieldAllIterator_)return this.yieldAllStep_(this.context_.yieldAllIterator_["throw"],c,this.context_.next_);this.context_.throw_(c);return this.nextStep_()};
$jscomp.generator.Engine_.prototype.yieldAllStep_=function(c,e,a){try{var b=c.call(this.context_.yieldAllIterator_,e);$jscomp.generator.ensureIteratorResultIsObject_(b);if(!b.done)return this.context_.stop_(),b;var d=b.value}catch(f){return this.context_.yieldAllIterator_=null,this.context_.throw_(f),this.nextStep_()}this.context_.yieldAllIterator_=null;a.call(this.context_,d);return this.nextStep_()};
$jscomp.generator.Engine_.prototype.nextStep_=function(){for(;this.context_.nextAddress;)try{var c=this.program_(this.context_);if(c)return this.context_.stop_(),{value:c.value,done:!1}}catch(e){this.context_.yieldResult=void 0,this.context_.throw_(e)}this.context_.stop_();if(this.context_.abruptCompletion_){c=this.context_.abruptCompletion_;this.context_.abruptCompletion_=null;if(c.isException)throw c.exception;return{value:c.return,done:!0}}return{value:void 0,done:!0}};
$jscomp.generator.Generator_=function(c){this.next=function(e){return c.next_(e)};this.throw=function(e){return c.throw_(e)};this.return=function(e){return c.return_(e)};this[Symbol.iterator]=function(){return this}};$jscomp.generator.createGenerator=function(c,e){e=new $jscomp.generator.Generator_(new $jscomp.generator.Engine_(e));$jscomp.setPrototypeOf&&c.prototype&&$jscomp.setPrototypeOf(e,c.prototype);return e};
$jscomp.asyncExecutePromiseGenerator=function(c){function e(b){return c.next(b)}function a(b){return c.throw(b)}return new Promise(function(b,d){function f(g){g.done?b(g.value):Promise.resolve(g.value).then(e,a).then(f,d)}f(c.next())})};$jscomp.asyncExecutePromiseGeneratorFunction=function(c){return $jscomp.asyncExecutePromiseGenerator(c())};$jscomp.asyncExecutePromiseGeneratorProgram=function(c){return $jscomp.asyncExecutePromiseGenerator(new $jscomp.generator.Generator_(new $jscomp.generator.Engine_(c)))};
(function(c,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"===typeof define&&define.amd?define(e):(c="undefined"!==typeof globalThis?globalThis:c||self,c.QrScanner=e())})(this,function(){class c{constructor(a,b,d,f,g){this._legacyCanvasSize=c.DEFAULT_CANVAS_SIZE;this._preferredCamera="environment";this._maxScansPerSecond=25;this._lastScanTimestamp=-1;this._destroyed=this._flashOn=this._paused=this._active=!1;this.$video=a;this.$canvas=document.createElement("canvas");
d&&"object"===typeof d?this._onDecode=b:(d||f||g?console.warn("You're using a deprecated version of the QrScanner constructor which will be removed in the future"):console.warn("Note that the type of the scan result passed to onDecode will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true."),this._legacyOnDecode=b);b="object"===typeof d?d:{};this._onDecodeError=b.onDecodeError||("function"===typeof d?d:this._onDecodeError);this._calculateScanRegion=
b.calculateScanRegion||("function"===typeof f?f:this._calculateScanRegion);this._preferredCamera=b.preferredCamera||g||this._preferredCamera;this._legacyCanvasSize="number"===typeof d?d:"number"===typeof f?f:this._legacyCanvasSize;this._maxScansPerSecond=b.maxScansPerSecond||this._maxScansPerSecond;this._onPlay=this._onPlay.bind(this);this._onLoadedMetaData=this._onLoadedMetaData.bind(this);this._onVisibilityChange=this._onVisibilityChange.bind(this);this._updateOverlay=this._updateOverlay.bind(this);
a.disablePictureInPicture=!0;a.playsInline=!0;a.muted=!0;let k=!1;a.hidden&&(a.hidden=!1,k=!0);document.body.contains(a)||(document.body.appendChild(a),k=!0);d=a.parentElement;if(b.highlightScanRegion||b.highlightCodeOutline){f=!!b.overlay;this.$overlay=b.overlay||document.createElement("div");g=this.$overlay.style;g.position="absolute";g.display="none";g.pointerEvents="none";this.$overlay.classList.add("scan-region-highlight");if(!f&&b.highlightScanRegion){this.$overlay.innerHTML='<svg class="scan-region-highlight-svg" viewBox="0 0 238 238" preserveAspectRatio="none" style="position:absolute;width:100%;height:100%;left:0;top:0;fill:none;stroke:#e9b213;stroke-width:4;stroke-linecap:round;stroke-linejoin:round"><path d="M31 2H10a8 8 0 0 0-8 8v21M207 2h21a8 8 0 0 1 8 8v21m0 176v21a8 8 0 0 1-8 8h-21m-176 0H10a8 8 0 0 1-8-8v-21"/></svg>';
try{this.$overlay.firstElementChild.animate({transform:["scale(.98)","scale(1.01)"]},{duration:400,iterations:Infinity,direction:"alternate",easing:"ease-in-out"})}catch(l){}d.insertBefore(this.$overlay,this.$video.nextSibling)}b.highlightCodeOutline&&(this.$overlay.insertAdjacentHTML("beforeend",'<svg class="code-outline-highlight" preserveAspectRatio="none" style="display:none;width:100%;height:100%;fill:none;stroke:#e9b213;stroke-width:5;stroke-dasharray:25;stroke-linecap:round;stroke-linejoin:round"><polygon/></svg>'),
$jscomp.generator.Context.prototype.jumpToErrorHandler_=function(){this.nextAddress=this.catchAddress_||this.finallyAddress_};$jscomp.generator.Context.prototype.next_=function(b){this.yieldResult=b};$jscomp.generator.Context.prototype.throw_=function(b){this.abruptCompletion_={exception:b,isException:!0};this.jumpToErrorHandler_()};$jscomp.generator.Context.prototype.return=function(b){this.abruptCompletion_={return:b};this.nextAddress=this.finallyAddress_};
$jscomp.generator.Context.prototype.jumpThroughFinallyBlocks=function(b){this.abruptCompletion_={jumpTo:b};this.nextAddress=this.finallyAddress_};$jscomp.generator.Context.prototype.yield=function(b,e){this.nextAddress=e;return{value:b}};$jscomp.generator.Context.prototype.yieldAll=function(b,e){b=$jscomp.makeIterator(b);var a=b.next();$jscomp.generator.ensureIteratorResultIsObject_(a);if(a.done)this.yieldResult=a.value,this.nextAddress=e;else return this.yieldAllIterator_=b,this.yield(a.value,e)};
$jscomp.generator.Context.prototype.jumpTo=function(b){this.nextAddress=b};$jscomp.generator.Context.prototype.jumpToEnd=function(){this.nextAddress=0};$jscomp.generator.Context.prototype.setCatchFinallyBlocks=function(b,e){this.catchAddress_=b;void 0!=e&&(this.finallyAddress_=e)};$jscomp.generator.Context.prototype.setFinallyBlock=function(b){this.catchAddress_=0;this.finallyAddress_=b||0};$jscomp.generator.Context.prototype.leaveTryBlock=function(b,e){this.nextAddress=b;this.catchAddress_=e||0};
$jscomp.generator.Context.prototype.enterCatchBlock=function(b){this.catchAddress_=b||0;b=this.abruptCompletion_.exception;this.abruptCompletion_=null;return b};$jscomp.generator.Context.prototype.enterFinallyBlock=function(b,e,a){a?this.finallyContexts_[a]=this.abruptCompletion_:this.finallyContexts_=[this.abruptCompletion_];this.catchAddress_=b||0;this.finallyAddress_=e||0};
$jscomp.generator.Context.prototype.leaveFinallyBlock=function(b,e){e=this.finallyContexts_.splice(e||0)[0];if(e=this.abruptCompletion_=this.abruptCompletion_||e){if(e.isException)return this.jumpToErrorHandler_();void 0!=e.jumpTo&&this.finallyAddress_<e.jumpTo?(this.nextAddress=e.jumpTo,this.abruptCompletion_=null):this.nextAddress=this.finallyAddress_}else this.nextAddress=b};$jscomp.generator.Context.prototype.forIn=function(b){return new $jscomp.generator.Context.PropertyIterator(b)};
$jscomp.generator.Context.PropertyIterator=function(b){this.object_=b;this.properties_=[];for(var e in b)this.properties_.push(e);this.properties_.reverse()};$jscomp.generator.Context.PropertyIterator.prototype.getNext=function(){for(;0<this.properties_.length;){var b=this.properties_.pop();if(b in this.object_)return b}return null};$jscomp.generator.Engine_=function(b){this.context_=new $jscomp.generator.Context;this.program_=b};
$jscomp.generator.Engine_.prototype.next_=function(b){this.context_.start_();if(this.context_.yieldAllIterator_)return this.yieldAllStep_(this.context_.yieldAllIterator_.next,b,this.context_.next_);this.context_.next_(b);return this.nextStep_()};
$jscomp.generator.Engine_.prototype.return_=function(b){this.context_.start_();var e=this.context_.yieldAllIterator_;if(e)return this.yieldAllStep_("return"in e?e["return"]:function(a){return{value:a,done:!0}},b,this.context_.return);this.context_.return(b);return this.nextStep_()};
$jscomp.generator.Engine_.prototype.throw_=function(b){this.context_.start_();if(this.context_.yieldAllIterator_)return this.yieldAllStep_(this.context_.yieldAllIterator_["throw"],b,this.context_.next_);this.context_.throw_(b);return this.nextStep_()};
$jscomp.generator.Engine_.prototype.yieldAllStep_=function(b,e,a){try{var c=b.call(this.context_.yieldAllIterator_,e);$jscomp.generator.ensureIteratorResultIsObject_(c);if(!c.done)return this.context_.stop_(),c;var d=c.value}catch(f){return this.context_.yieldAllIterator_=null,this.context_.throw_(f),this.nextStep_()}this.context_.yieldAllIterator_=null;a.call(this.context_,d);return this.nextStep_()};
$jscomp.generator.Engine_.prototype.nextStep_=function(){for(;this.context_.nextAddress;)try{var b=this.program_(this.context_);if(b)return this.context_.stop_(),{value:b.value,done:!1}}catch(e){this.context_.yieldResult=void 0,this.context_.throw_(e)}this.context_.stop_();if(this.context_.abruptCompletion_){b=this.context_.abruptCompletion_;this.context_.abruptCompletion_=null;if(b.isException)throw b.exception;return{value:b.return,done:!0}}return{value:void 0,done:!0}};
$jscomp.generator.Generator_=function(b){this.next=function(e){return b.next_(e)};this.throw=function(e){return b.throw_(e)};this.return=function(e){return b.return_(e)};this[Symbol.iterator]=function(){return this}};$jscomp.generator.createGenerator=function(b,e){e=new $jscomp.generator.Generator_(new $jscomp.generator.Engine_(e));$jscomp.setPrototypeOf&&b.prototype&&$jscomp.setPrototypeOf(e,b.prototype);return e};
$jscomp.asyncExecutePromiseGenerator=function(b){function e(c){return b.next(c)}function a(c){return b.throw(c)}return new Promise(function(c,d){function f(g){g.done?c(g.value):Promise.resolve(g.value).then(e,a).then(f,d)}f(b.next())})};$jscomp.asyncExecutePromiseGeneratorFunction=function(b){return $jscomp.asyncExecutePromiseGenerator(b())};$jscomp.asyncExecutePromiseGeneratorProgram=function(b){return $jscomp.asyncExecutePromiseGenerator(new $jscomp.generator.Generator_(new $jscomp.generator.Engine_(b)))};
(function(b,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"===typeof define&&define.amd?define(e):(b="undefined"!==typeof globalThis?globalThis:b||self,b.QrScanner=e())})(this,function(){class b{constructor(a,c,d,f,g){this._legacyCanvasSize=b.DEFAULT_CANVAS_SIZE;this._preferredCamera="environment";this._maxScansPerSecond=25;this._lastScanTimestamp=-1;this._destroyed=this._flashOn=this._paused=this._active=!1;this.$video=a;this.$canvas=document.createElement("canvas");
d&&"object"===typeof d?this._onDecode=c:(d||f||g?console.warn("You're using a deprecated version of the QrScanner constructor which will be removed in the future"):console.warn("Note that the type of the scan result passed to onDecode will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true."),this._legacyOnDecode=c);c="object"===typeof d?d:{};this._onDecodeError=c.onDecodeError||("function"===typeof d?d:this._onDecodeError);this._calculateScanRegion=
c.calculateScanRegion||("function"===typeof f?f:this._calculateScanRegion);this._preferredCamera=c.preferredCamera||g||this._preferredCamera;this._legacyCanvasSize="number"===typeof d?d:"number"===typeof f?f:this._legacyCanvasSize;this._maxScansPerSecond=c.maxScansPerSecond||this._maxScansPerSecond;this._onPlay=this._onPlay.bind(this);this._onLoadedMetaData=this._onLoadedMetaData.bind(this);this._onVisibilityChange=this._onVisibilityChange.bind(this);this._updateOverlay=this._updateOverlay.bind(this);
a.disablePictureInPicture=!0;a.playsInline=!0;a.muted=!0;let k=!1;a.hidden&&(a.hidden=!1,k=!0);document.body.contains(a)||(document.body.appendChild(a),k=!0);d=a.parentElement;if(c.highlightScanRegion||c.highlightCodeOutline){f=!!c.overlay;this.$overlay=c.overlay||document.createElement("div");g=this.$overlay.style;g.position="absolute";g.display="none";g.pointerEvents="none";this.$overlay.classList.add("scan-region-highlight");if(!f&&c.highlightScanRegion){this.$overlay.innerHTML='<svg class="scan-region-highlight-svg" viewBox="0 0 238 238" preserveAspectRatio="none" style="position:absolute;width:100%;height:100%;left:0;top:0;fill:none;stroke:#e9b213;stroke-width:4;stroke-linecap:round;stroke-linejoin:round"><path d="M31 2H10a8 8 0 0 0-8 8v21M207 2h21a8 8 0 0 1 8 8v21m0 176v21a8 8 0 0 1-8 8h-21m-176 0H10a8 8 0 0 1-8-8v-21"/></svg>';
try{this.$overlay.firstElementChild.animate({transform:["scale(.98)","scale(1.01)"]},{duration:400,iterations:Infinity,direction:"alternate",easing:"ease-in-out"})}catch(l){}d.insertBefore(this.$overlay,this.$video.nextSibling)}c.highlightCodeOutline&&(this.$overlay.insertAdjacentHTML("beforeend",'<svg class="code-outline-highlight" preserveAspectRatio="none" style="display:none;width:100%;height:100%;fill:none;stroke:#e9b213;stroke-width:5;stroke-dasharray:25;stroke-linecap:round;stroke-linejoin:round"><polygon/></svg>'),
this.$codeOutlineHighlight=this.$overlay.lastElementChild)}this._scanRegion=this._calculateScanRegion(a);requestAnimationFrame(()=>{let l=window.getComputedStyle(a);"none"===l.display&&(a.style.setProperty("display","block","important"),k=!0);"visible"!==l.visibility&&(a.style.setProperty("visibility","visible","important"),k=!0);k&&(console.warn("QrScanner has overwritten the video hiding style to avoid Safari stopping the playback."),a.style.opacity="0",a.style.width="0",a.style.height="0",this.$overlay&&
this.$overlay.parentElement&&this.$overlay.parentElement.removeChild(this.$overlay),delete this.$overlay,delete this.$codeOutlineHighlight);this.$overlay&&this._updateOverlay()});a.addEventListener("play",this._onPlay);a.addEventListener("loadedmetadata",this._onLoadedMetaData);document.addEventListener("visibilitychange",this._onVisibilityChange);window.addEventListener("resize",this._updateOverlay);this._qrEnginePromise=c.createQrEngine()}static set WORKER_PATH(a){console.warn("Setting QrScanner.WORKER_PATH is not required and not supported anymore. Have a look at the README for new setup instructions.")}static hasCamera(){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){try{return!!(yield c.listCameras(!1)).length}catch(a){return!1}})}static listCameras(a=
!1){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(!navigator.mediaDevices)return[];let b=()=>$jscomp.asyncExecutePromiseGeneratorFunction(function*(){return(yield navigator.mediaDevices.enumerateDevices()).filter(f=>"videoinput"===f.kind)}),d;try{a&&(yield b()).every(f=>!f.label)&&(d=yield navigator.mediaDevices.getUserMedia({audio:!1,video:!0}))}catch(f){}try{return(yield b()).map((f,g)=>({id:f.deviceId,label:f.label||(0===g?"Default Camera":`Camera ${g+1}`)}))}finally{d&&(console.warn("Call listCameras after successfully starting a QR scanner to avoid creating a temporary video stream"),
c._stopVideoStream(d))}})}hasFlash(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){let b;try{if(a.$video.srcObject){if(!(a.$video.srcObject instanceof MediaStream))return!1;b=a.$video.srcObject}else b=(yield a._getCameraStream()).stream;return"torch"in b.getVideoTracks()[0].getSettings()}catch(d){return!1}finally{b&&b!==a.$video.srcObject&&(console.warn("Call hasFlash after successfully starting the scanner to avoid creating a temporary video stream"),c._stopVideoStream(b))}})}isFlashOn(){return this._flashOn}toggleFlash(){const a=
this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a._flashOn?yield a.turnFlashOff():yield a.turnFlashOn()})}turnFlashOn(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(!a._flashOn&&!a._destroyed&&(a._flashOn=!0,a._active&&!a._paused))try{if(!(yield a.hasFlash()))throw"No flash available";yield a.$video.srcObject.getVideoTracks()[0].applyConstraints({advanced:[{torch:!0}]})}catch(b){throw a._flashOn=!1,b;}})}turnFlashOff(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a._flashOn&&
(a._flashOn=!1,yield a._restartVideoStream())})}destroy(){this.$video.removeEventListener("loadedmetadata",this._onLoadedMetaData);this.$video.removeEventListener("play",this._onPlay);document.removeEventListener("visibilitychange",this._onVisibilityChange);window.removeEventListener("resize",this._updateOverlay);this._destroyed=!0;this._flashOn=!1;this.stop();c._postWorkerMessage(this._qrEnginePromise,"close")}start(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(a._destroyed)throw Error("The QR scanner can not be started as it had been destroyed.");
if(!a._active||a._paused)if("https:"!==window.location.protocol&&console.warn("The camera stream is only accessible if the page is transferred via https."),a._active=!0,!document.hidden)if(a._paused=!1,a.$video.srcObject)yield a.$video.play();else try{let {stream:b,facingMode:d}=yield a._getCameraStream();!a._active||a._paused?c._stopVideoStream(b):(a._setVideoMirror(d),a.$video.srcObject=b,yield a.$video.play(),a._flashOn&&(a._flashOn=!1,a.turnFlashOn().catch(()=>{})))}catch(b){if(!a._paused)throw a._active=
!1,b;}})}stop(){this.pause();this._active=!1}pause(a=!1){const b=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){b._paused=!0;if(!b._active)return!0;b.$video.pause();b.$overlay&&(b.$overlay.style.display="none");let d=()=>{b.$video.srcObject instanceof MediaStream&&(c._stopVideoStream(b.$video.srcObject),b.$video.srcObject=null)};if(a)return d(),!0;yield new Promise(f=>setTimeout(f,300));if(!b._paused)return!1;d();return!0})}setCamera(a){const b=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a!==
b._preferredCamera&&(b._preferredCamera=a,yield b._restartVideoStream())})}static scanImage(a,b,d,f,g=!1,k=!1){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){let l,p=!1;b&&("scanRegion"in b||"qrEngine"in b||"canvas"in b||"disallowCanvasResizing"in b||"alsoTryWithoutScanRegion"in b||"returnDetailedScanResult"in b)?(l=b.scanRegion,d=b.qrEngine,f=b.canvas,g=b.disallowCanvasResizing||!1,k=b.alsoTryWithoutScanRegion||!1,p=!0):b||d||f||g||k?console.warn("You're using a deprecated api for scanImage which will be removed in the future."):
console.warn("Note that the return type of scanImage will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true.");let r=!!d;try{let m,q;[d,m]=yield Promise.all([d||c.createQrEngine(),c._loadImage(a)]);[f,q]=c._drawToCanvas(m,l,f,g);let n;if(d instanceof Worker){let h=d;r||h.postMessage({type:"inversionMode",data:"both"});n=yield new Promise((t,z)=>{let x,v,w;v=u=>{"qrResult"===u.data.type&&(h.removeEventListener("message",v),h.removeEventListener("error",
w),clearTimeout(x),null!==u.data.data?t({data:u.data.data,cornerPoints:c._convertPoints(u.data.cornerPoints,l)}):z(c.NO_QR_CODE_FOUND))};w=u=>{h.removeEventListener("message",v);h.removeEventListener("error",w);clearTimeout(x);z("Scanner error: "+(u?u.message||u:"Unknown Error"))};h.addEventListener("message",v);h.addEventListener("error",w);x=setTimeout(()=>w("timeout"),1E4);let y=q.getImageData(0,0,f.width,f.height);h.postMessage({type:"decode",data:y},[y.data.buffer])})}else n=yield Promise.race([new Promise((h,
t)=>window.setTimeout(()=>t("Scanner error: timeout"),1E4)),(()=>$jscomp.asyncExecutePromiseGeneratorFunction(function*(){try{var [h]=yield d.detect(f);if(!h)throw c.NO_QR_CODE_FOUND;return{data:h.rawValue,cornerPoints:c._convertPoints(h.cornerPoints,l)}}catch(t){h=t.message||t;if(/not implemented|service unavailable/.test(h))return c._disableBarcodeDetector=!0,c.scanImage(a,{scanRegion:l,canvas:f,disallowCanvasResizing:g,alsoTryWithoutScanRegion:k});throw`Scanner error: ${h}`;}}))()]);return p?n:
n.data}catch(m){if(!l||!k)throw m;let q=yield c.scanImage(a,{qrEngine:d,canvas:f,disallowCanvasResizing:g});return p?q:q.data}finally{r||c._postWorkerMessage(d,"close")}})}setGrayscaleWeights(a,b,d,f=!0){c._postWorkerMessage(this._qrEnginePromise,"grayscaleWeights",{red:a,green:b,blue:d,useIntegerApproximation:f})}setInversionMode(a){c._postWorkerMessage(this._qrEnginePromise,"inversionMode",a)}static createQrEngine(a){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a&&console.warn("Specifying a worker path is not required and not supported anymore.");
return!c._disableBarcodeDetector&&"BarcodeDetector"in window&&BarcodeDetector.getSupportedFormats&&(yield BarcodeDetector.getSupportedFormats()).includes("qr_code")?new BarcodeDetector({formats:["qr_code"]}):Promise.resolve().then(function(){return e}).then(b=>b.createWorker())})}_onPlay(){this._scanRegion=this._calculateScanRegion(this.$video);this._updateOverlay();this.$overlay&&(this.$overlay.style.display="");this._scanFrame()}_onLoadedMetaData(){this._scanRegion=this._calculateScanRegion(this.$video);
this._updateOverlay()}_onVisibilityChange(){document.hidden?this.pause():this._active&&this.start()}_calculateScanRegion(a){let b=Math.round(2/3*Math.min(a.videoWidth,a.videoHeight));return{x:Math.round((a.videoWidth-b)/2),y:Math.round((a.videoHeight-b)/2),width:b,height:b,downScaledWidth:this._legacyCanvasSize,downScaledHeight:this._legacyCanvasSize}}_updateOverlay(){requestAnimationFrame(()=>{if(this.$overlay){var a=this.$video,b=a.videoWidth,d=a.videoHeight,f=a.offsetWidth,g=a.offsetHeight,k=a.offsetLeft,
l=a.offsetTop,p=window.getComputedStyle(a),r=p.objectFit,m=b/d,q=f/g;switch(r){case "none":var n=b;var h=d;break;case "fill":n=f;h=g;break;default:("cover"===r?m>q:m<q)?(h=g,n=h*m):(n=f,h=n/m),"scale-down"===r&&(n=Math.min(n,b),h=Math.min(h,d))}var [t,z]=p.objectPosition.split(" ").map((v,w)=>{const y=parseFloat(v);return v.endsWith("%")?(w?g-h:f-n)*y/100:y});p=this._scanRegion.width||b;q=this._scanRegion.height||d;r=this._scanRegion.x||0;var x=this._scanRegion.y||0;m=this.$overlay.style;m.width=
`${p/b*n}px`;m.height=`${q/d*h}px`;m.top=`${l+z+x/d*h}px`;d=/scaleX\(-1\)/.test(a.style.transform);m.left=`${k+(d?f-t-n:t)+(d?b-r-p:r)/b*n}px`;m.transform=a.style.transform}})}static _convertPoints(a,b){if(!b)return a;let d=b.x||0,f=b.y||0,g=b.width&&b.downScaledWidth?b.width/b.downScaledWidth:1;b=b.height&&b.downScaledHeight?b.height/b.downScaledHeight:1;for(let k of a)k.x=k.x*g+d,k.y=k.y*b+f;return a}_scanFrame(){!this._active||this.$video.paused||this.$video.ended||("requestVideoFrameCallback"in
this.$video?this.$video.requestVideoFrameCallback.bind(this.$video):requestAnimationFrame)(()=>{const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(!(1>=a.$video.readyState)){var b=Date.now()-a._lastScanTimestamp,d=1E3/a._maxScansPerSecond;b<d&&(yield new Promise(g=>setTimeout(g,d-b)));a._lastScanTimestamp=Date.now();try{var f=yield c.scanImage(a.$video,{scanRegion:a._scanRegion,qrEngine:a._qrEnginePromise,canvas:a.$canvas})}catch(g){if(!a._active)return;a._onDecodeError(g)}!c._disableBarcodeDetector||
(yield a._qrEnginePromise)instanceof Worker||(a._qrEnginePromise=c.createQrEngine());f?(a._onDecode?a._onDecode(f):a._legacyOnDecode&&a._legacyOnDecode(f.data),a.$codeOutlineHighlight&&(clearTimeout(a._codeOutlineHighlightRemovalTimeout),a._codeOutlineHighlightRemovalTimeout=void 0,a.$codeOutlineHighlight.setAttribute("viewBox",`${a._scanRegion.x||0} `+`${a._scanRegion.y||0} `+`${a._scanRegion.width||a.$video.videoWidth} `+`${a._scanRegion.height||a.$video.videoHeight}`),a.$codeOutlineHighlight.firstElementChild.setAttribute("points",
f.cornerPoints.map(({x:g,y:k})=>`${g},${k}`).join(" ")),a.$codeOutlineHighlight.style.display="")):a.$codeOutlineHighlight&&!a._codeOutlineHighlightRemovalTimeout&&(a._codeOutlineHighlightRemovalTimeout=setTimeout(()=>a.$codeOutlineHighlight.style.display="none",100))}a._scanFrame()})})}_onDecodeError(a){a!==c.NO_QR_CODE_FOUND&&console.log(a)}_getCameraStream(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(!navigator.mediaDevices)throw"Camera not found.";let b=/^(environment|user)$/.test(a._preferredCamera)?
"facingMode":"deviceId",d=[{width:{min:1024}},{width:{min:768}},{}],f=d.map(g=>Object.assign({},g,{[b]:{exact:a._preferredCamera}}));for(let g of[...f,...d])try{let k=yield navigator.mediaDevices.getUserMedia({video:g,audio:!1}),l=a._getFacingMode(k)||(g.facingMode?a._preferredCamera:"environment"===a._preferredCamera?"user":"environment");return{stream:k,facingMode:l}}catch(k){}throw"Camera not found.";})}_restartVideoStream(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){let b=
a._paused;(yield a.pause(!0))&&!b&&a._active&&(yield a.start())})}static _stopVideoStream(a){for(let b of a.getTracks())b.stop(),a.removeTrack(b)}_setVideoMirror(a){this.$video.style.transform="scaleX("+("user"===a?-1:1)+")"}_getFacingMode(a){return(a=a.getVideoTracks()[0])?/rear|back|environment/i.test(a.label)?"environment":/front|user|face/i.test(a.label)?"user":null:null}static _drawToCanvas(a,b,d,f=!1){d=d||document.createElement("canvas");let g=b&&b.x?b.x:0,k=b&&b.y?b.y:0,l=b&&b.width?b.width:
a.videoWidth||a.width,p=b&&b.height?b.height:a.videoHeight||a.height;f||(f=b&&b.downScaledWidth?b.downScaledWidth:l,b=b&&b.downScaledHeight?b.downScaledHeight:p,d.width!==f&&(d.width=f),d.height!==b&&(d.height=b));b=d.getContext("2d",{alpha:!1});b.imageSmoothingEnabled=!1;b.drawImage(a,g,k,l,p,0,0,d.width,d.height);return[d,b]}static _loadImage(a){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(a instanceof Image)return yield c._awaitImageLoad(a),a;if(a instanceof HTMLVideoElement||
a instanceof HTMLCanvasElement||a instanceof SVGImageElement||"OffscreenCanvas"in window&&a instanceof OffscreenCanvas||"ImageBitmap"in window&&a instanceof ImageBitmap)return a;if(a instanceof File||a instanceof Blob||a instanceof URL||"string"===typeof a){let b=new Image;b.src=a instanceof File||a instanceof Blob?URL.createObjectURL(a):a.toString();try{return yield c._awaitImageLoad(b),b}finally{(a instanceof File||a instanceof Blob)&&URL.revokeObjectURL(b.src)}}else throw"Unsupported image type.";
})}static _awaitImageLoad(a){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a.complete&&0!==a.naturalWidth||(yield new Promise((b,d)=>{let f=g=>{a.removeEventListener("load",f);a.removeEventListener("error",f);g instanceof ErrorEvent?d("Image load error"):b()};a.addEventListener("load",f);a.addEventListener("error",f)}))})}static _postWorkerMessage(a,b,d){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){let f=yield a;f instanceof Worker&&f.postMessage({type:b,data:d})})}}
c.DEFAULT_CANVAS_SIZE=400;c.NO_QR_CODE_FOUND="No QR code found";c._disableBarcodeDetector=!1;var e=Object.freeze({__proto__:null,createWorker:()=>new Worker(URL.createObjectURL(new Blob(['class x{constructor(a,b){this.width=b;this.height=a.length/b;this.data=a}static createEmpty(a,b){return new x(new Uint8ClampedArray(a*b),a)}get(a,b){return 0>a||a>=this.width||0>b||b>=this.height?!1:!!this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c?1:0}setRegion(a,b,c,d,e){for(let f=b;f<b+d;f++)for(let g=a;g<a+c;g++)this.set(g,f,!!e)}}\nclass A{constructor(a,b,c){this.width=a;a*=b;if(c&&c.length!==a)throw Error("Wrong buffer size");this.data=c||new Uint8ClampedArray(a)}get(a,b){return this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c}}\nclass ba{constructor(a){this.bitOffset=this.byteOffset=0;this.bytes=a}readBits(a){if(1>a||32<a||a>this.available())throw Error("Cannot read "+a.toString()+" bits");var b=0;if(0<this.bitOffset){b=8-this.bitOffset;var c=a<b?a:b;b-=c;b=(this.bytes[this.byteOffset]&255>>8-c<<b)>>b;a-=c;this.bitOffset+=c;8===this.bitOffset&&(this.bitOffset=0,this.byteOffset++)}if(0<a){for(;8<=a;)b=b<<8|this.bytes[this.byteOffset]&255,this.byteOffset++,a-=8;0<a&&(c=8-a,b=b<<a|(this.bytes[this.byteOffset]&255>>c<<c)>>c,\nthis.bitOffset+=a)}return b}available(){return 8*(this.bytes.length-this.byteOffset)-this.bitOffset}}var B,C=B||(B={});C.Numeric="numeric";C.Alphanumeric="alphanumeric";C.Byte="byte";C.Kanji="kanji";C.ECI="eci";C.StructuredAppend="structuredappend";var D,E=D||(D={});E[E.Terminator=0]="Terminator";E[E.Numeric=1]="Numeric";E[E.Alphanumeric=2]="Alphanumeric";E[E.Byte=4]="Byte";E[E.Kanji=8]="Kanji";E[E.ECI=7]="ECI";E[E.StructuredAppend=3]="StructuredAppend";let F="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".split("");\nfunction ca(a,b){let c=[],d="";b=a.readBits([8,16,16][b]);for(let e=0;e<b;e++){let f=a.readBits(8);c.push(f)}try{d+=decodeURIComponent(c.map(e=>`%${("0"+e.toString(16)).substr(-2)}`).join(""))}catch(e){}return{bytes:c,text:d}}\nfunction da(a,b){a=new ba(a);let c=9>=b?0:26>=b?1:2;for(b={text:"",bytes:[],chunks:[],version:b};4<=a.available();){var d=a.readBits(4);if(d===D.Terminator)return b;if(d===D.ECI)0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(7)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(14)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(21)}):b.chunks.push({type:B.ECI,assignmentNumber:-1});else if(d===D.Numeric){var e=a,f=[];d="";for(var g=\ne.readBits([10,12,14][c]);3<=g;){var h=e.readBits(10);if(1E3<=h)throw Error("Invalid numeric value above 999");var k=Math.floor(h/100),m=Math.floor(h/10)%10;h%=10;f.push(48+k,48+m,48+h);d+=k.toString()+m.toString()+h.toString();g-=3}if(2===g){g=e.readBits(7);if(100<=g)throw Error("Invalid numeric value above 99");e=Math.floor(g/10);g%=10;f.push(48+e,48+g);d+=e.toString()+g.toString()}else if(1===g){e=e.readBits(4);if(10<=e)throw Error("Invalid numeric value above 9");f.push(48+e);d+=e.toString()}b.text+=\nd;b.bytes.push(...f);b.chunks.push({type:B.Numeric,text:d})}else if(d===D.Alphanumeric){e=a;f=[];d="";for(g=e.readBits([9,11,13][c]);2<=g;)m=e.readBits(11),k=Math.floor(m/45),m%=45,f.push(F[k].charCodeAt(0),F[m].charCodeAt(0)),d+=F[k]+F[m],g-=2;1===g&&(e=e.readBits(6),f.push(F[e].charCodeAt(0)),d+=F[e]);b.text+=d;b.bytes.push(...f);b.chunks.push({type:B.Alphanumeric,text:d})}else if(d===D.Byte)d=ca(a,c),b.text+=d.text,b.bytes.push(...d.bytes),b.chunks.push({type:B.Byte,bytes:d.bytes,text:d.text});\nelse if(d===D.Kanji){f=a;d=[];e=f.readBits([8,10,12][c]);for(g=0;g<e;g++)k=f.readBits(13),k=Math.floor(k/192)<<8|k%192,k=7936>k?k+33088:k+49472,d.push(k>>8,k&255);f=(new TextDecoder("shift-jis")).decode(Uint8Array.from(d));b.text+=f;b.bytes.push(...d);b.chunks.push({type:B.Kanji,bytes:d,text:f})}else d===D.StructuredAppend&&b.chunks.push({type:B.StructuredAppend,currentSequence:a.readBits(4),totalSequence:a.readBits(4),parity:a.readBits(8)})}if(0===a.available()||0===a.readBits(a.available()))return b}\nclass G{constructor(a,b){if(0===b.length)throw Error("No coefficients.");this.field=a;let c=b.length;if(1<c&&0===b[0]){let d=1;for(;d<c&&0===b[d];)d++;if(d===c)this.coefficients=a.zero.coefficients;else for(this.coefficients=new Uint8ClampedArray(c-d),a=0;a<this.coefficients.length;a++)this.coefficients[a]=b[d+a]}else this.coefficients=b}degree(){return this.coefficients.length-1}isZero(){return 0===this.coefficients[0]}getCoefficient(a){return this.coefficients[this.coefficients.length-1-a]}addOrSubtract(a){if(this.isZero())return a;\nif(a.isZero())return this;let b=this.coefficients;a=a.coefficients;b.length>a.length&&([b,a]=[a,b]);let c=new Uint8ClampedArray(a.length),d=a.length-b.length;for(var e=0;e<d;e++)c[e]=a[e];for(e=d;e<a.length;e++)c[e]=b[e-d]^a[e];return new G(this.field,c)}multiply(a){if(0===a)return this.field.zero;if(1===a)return this;let b=this.coefficients.length,c=new Uint8ClampedArray(b);for(let d=0;d<b;d++)c[d]=Line truncated
{type:"application/javascript"}))});return c})
this.$overlay.parentElement&&this.$overlay.parentElement.removeChild(this.$overlay),delete this.$overlay,delete this.$codeOutlineHighlight);this.$overlay&&this._updateOverlay()});a.addEventListener("play",this._onPlay);a.addEventListener("loadedmetadata",this._onLoadedMetaData);document.addEventListener("visibilitychange",this._onVisibilityChange);window.addEventListener("resize",this._updateOverlay);this._qrEnginePromise=b.createQrEngine()}static set WORKER_PATH(a){console.warn("Setting QrScanner.WORKER_PATH is not required and not supported anymore. Have a look at the README for new setup instructions.")}static hasCamera(){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){try{return!!(yield b.listCameras(!1)).length}catch(a){return!1}})}static listCameras(a=
!1){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(!navigator.mediaDevices)return[];let c=()=>$jscomp.asyncExecutePromiseGeneratorFunction(function*(){return(yield navigator.mediaDevices.enumerateDevices()).filter(f=>"videoinput"===f.kind)}),d;try{a&&(yield c()).every(f=>!f.label)&&(d=yield navigator.mediaDevices.getUserMedia({audio:!1,video:!0}))}catch(f){}try{return(yield c()).map((f,g)=>({id:f.deviceId,label:f.label||(0===g?"Default Camera":`Camera ${g+1}`)}))}finally{d&&(console.warn("Call listCameras after successfully starting a QR scanner to avoid creating a temporary video stream"),
b._stopVideoStream(d))}})}hasFlash(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){let c;try{if(a.$video.srcObject){if(!(a.$video.srcObject instanceof MediaStream))return!1;c=a.$video.srcObject}else c=(yield a._getCameraStream()).stream;return"torch"in c.getVideoTracks()[0].getSettings()}catch(d){return!1}finally{c&&c!==a.$video.srcObject&&(console.warn("Call hasFlash after successfully starting the scanner to avoid creating a temporary video stream"),b._stopVideoStream(c))}})}isFlashOn(){return this._flashOn}toggleFlash(){const a=
this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a._flashOn?yield a.turnFlashOff():yield a.turnFlashOn()})}turnFlashOn(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(!a._flashOn&&!a._destroyed&&(a._flashOn=!0,a._active&&!a._paused))try{if(!(yield a.hasFlash()))throw"No flash available";yield a.$video.srcObject.getVideoTracks()[0].applyConstraints({advanced:[{torch:!0}]})}catch(c){throw a._flashOn=!1,c;}})}turnFlashOff(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a._flashOn&&
(a._flashOn=!1,yield a._restartVideoStream())})}destroy(){this.$video.removeEventListener("loadedmetadata",this._onLoadedMetaData);this.$video.removeEventListener("play",this._onPlay);document.removeEventListener("visibilitychange",this._onVisibilityChange);window.removeEventListener("resize",this._updateOverlay);this._destroyed=!0;this._flashOn=!1;this.stop();b._postWorkerMessage(this._qrEnginePromise,"close")}start(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(a._destroyed)throw Error("The QR scanner can not be started as it had been destroyed.");
if(!a._active||a._paused)if("https:"!==window.location.protocol&&console.warn("The camera stream is only accessible if the page is transferred via https."),a._active=!0,!document.hidden)if(a._paused=!1,a.$video.srcObject)yield a.$video.play();else try{let {stream:c,facingMode:d}=yield a._getCameraStream();!a._active||a._paused?b._stopVideoStream(c):(a._setVideoMirror(d),a.$video.srcObject=c,yield a.$video.play(),a._flashOn&&(a._flashOn=!1,a.turnFlashOn().catch(()=>{})))}catch(c){if(!a._paused)throw a._active=
!1,c;}})}stop(){this.pause();this._active=!1}pause(a=!1){const c=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){c._paused=!0;if(!c._active)return!0;c.$video.pause();c.$overlay&&(c.$overlay.style.display="none");let d=()=>{c.$video.srcObject instanceof MediaStream&&(b._stopVideoStream(c.$video.srcObject),c.$video.srcObject=null)};if(a)return d(),!0;yield new Promise(f=>setTimeout(f,300));if(!c._paused)return!1;d();return!0})}setCamera(a){const c=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a!==
c._preferredCamera&&(c._preferredCamera=a,yield c._restartVideoStream())})}static scanImage(a,c,d,f,g=!1,k=!1){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){let l,p=!1;c&&("scanRegion"in c||"qrEngine"in c||"canvas"in c||"disallowCanvasResizing"in c||"alsoTryWithoutScanRegion"in c||"returnDetailedScanResult"in c)?(l=c.scanRegion,d=c.qrEngine,f=c.canvas,g=c.disallowCanvasResizing||!1,k=c.alsoTryWithoutScanRegion||!1,p=!0):c||d||f||g||k?console.warn("You're using a deprecated api for scanImage which will be removed in the future."):
console.warn("Note that the return type of scanImage will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true.");let r=!!d;try{let m,q;[d,m]=yield Promise.all([d||b.createQrEngine(),b._loadImage(a)]);[f,q]=b._drawToCanvas(m,l,f,g);let n;if(d instanceof Worker){let h=d;r||b._postWorkerMessageSync(h,"inversionMode","both");n=yield new Promise((t,z)=>{let x,v,w,y=-1;v=u=>{u.data.id===y&&(h.removeEventListener("message",v),h.removeEventListener("error",
w),clearTimeout(x),null!==u.data.data?t({data:u.data.data,cornerPoints:b._convertPoints(u.data.cornerPoints,l)}):z(b.NO_QR_CODE_FOUND))};w=u=>{h.removeEventListener("message",v);h.removeEventListener("error",w);clearTimeout(x);z("Scanner error: "+(u?u.message||u:"Unknown Error"))};h.addEventListener("message",v);h.addEventListener("error",w);x=setTimeout(()=>w("timeout"),1E4);let A=q.getImageData(0,0,f.width,f.height);y=b._postWorkerMessageSync(h,"decode",A,[A.data.buffer])})}else n=yield Promise.race([new Promise((h,
t)=>window.setTimeout(()=>t("Scanner error: timeout"),1E4)),(()=>$jscomp.asyncExecutePromiseGeneratorFunction(function*(){try{var [h]=yield d.detect(f);if(!h)throw b.NO_QR_CODE_FOUND;return{data:h.rawValue,cornerPoints:b._convertPoints(h.cornerPoints,l)}}catch(t){h=t.message||t;if(/not implemented|service unavailable/.test(h))return b._disableBarcodeDetector=!0,b.scanImage(a,{scanRegion:l,canvas:f,disallowCanvasResizing:g,alsoTryWithoutScanRegion:k});throw`Scanner error: ${h}`;}}))()]);return p?n:
n.data}catch(m){if(!l||!k)throw m;let q=yield b.scanImage(a,{qrEngine:d,canvas:f,disallowCanvasResizing:g});return p?q:q.data}finally{r||b._postWorkerMessage(d,"close")}})}setGrayscaleWeights(a,c,d,f=!0){b._postWorkerMessage(this._qrEnginePromise,"grayscaleWeights",{red:a,green:c,blue:d,useIntegerApproximation:f})}setInversionMode(a){b._postWorkerMessage(this._qrEnginePromise,"inversionMode",a)}static createQrEngine(a){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a&&console.warn("Specifying a worker path is not required and not supported anymore.");
return!b._disableBarcodeDetector&&"BarcodeDetector"in window&&BarcodeDetector.getSupportedFormats&&(yield BarcodeDetector.getSupportedFormats()).includes("qr_code")?new BarcodeDetector({formats:["qr_code"]}):Promise.resolve().then(function(){return e}).then(c=>c.createWorker())})}_onPlay(){this._scanRegion=this._calculateScanRegion(this.$video);this._updateOverlay();this.$overlay&&(this.$overlay.style.display="");this._scanFrame()}_onLoadedMetaData(){this._scanRegion=this._calculateScanRegion(this.$video);
this._updateOverlay()}_onVisibilityChange(){document.hidden?this.pause():this._active&&this.start()}_calculateScanRegion(a){let c=Math.round(2/3*Math.min(a.videoWidth,a.videoHeight));return{x:Math.round((a.videoWidth-c)/2),y:Math.round((a.videoHeight-c)/2),width:c,height:c,downScaledWidth:this._legacyCanvasSize,downScaledHeight:this._legacyCanvasSize}}_updateOverlay(){requestAnimationFrame(()=>{if(this.$overlay){var a=this.$video,c=a.videoWidth,d=a.videoHeight,f=a.offsetWidth,g=a.offsetHeight,k=a.offsetLeft,
l=a.offsetTop,p=window.getComputedStyle(a),r=p.objectFit,m=c/d,q=f/g;switch(r){case "none":var n=c;var h=d;break;case "fill":n=f;h=g;break;default:("cover"===r?m>q:m<q)?(h=g,n=h*m):(n=f,h=n/m),"scale-down"===r&&(n=Math.min(n,c),h=Math.min(h,d))}var [t,z]=p.objectPosition.split(" ").map((v,w)=>{const y=parseFloat(v);return v.endsWith("%")?(w?g-h:f-n)*y/100:y});p=this._scanRegion.width||c;q=this._scanRegion.height||d;r=this._scanRegion.x||0;var x=this._scanRegion.y||0;m=this.$overlay.style;m.width=
`${p/c*n}px`;m.height=`${q/d*h}px`;m.top=`${l+z+x/d*h}px`;d=/scaleX\(-1\)/.test(a.style.transform);m.left=`${k+(d?f-t-n:t)+(d?c-r-p:r)/c*n}px`;m.transform=a.style.transform}})}static _convertPoints(a,c){if(!c)return a;let d=c.x||0,f=c.y||0,g=c.width&&c.downScaledWidth?c.width/c.downScaledWidth:1;c=c.height&&c.downScaledHeight?c.height/c.downScaledHeight:1;for(let k of a)k.x=k.x*g+d,k.y=k.y*c+f;return a}_scanFrame(){!this._active||this.$video.paused||this.$video.ended||("requestVideoFrameCallback"in
this.$video?this.$video.requestVideoFrameCallback.bind(this.$video):requestAnimationFrame)(()=>{const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(!(1>=a.$video.readyState)){var c=Date.now()-a._lastScanTimestamp,d=1E3/a._maxScansPerSecond;c<d&&(yield new Promise(g=>setTimeout(g,d-c)));a._lastScanTimestamp=Date.now();try{var f=yield b.scanImage(a.$video,{scanRegion:a._scanRegion,qrEngine:a._qrEnginePromise,canvas:a.$canvas})}catch(g){if(!a._active)return;a._onDecodeError(g)}!b._disableBarcodeDetector||
(yield a._qrEnginePromise)instanceof Worker||(a._qrEnginePromise=b.createQrEngine());f?(a._onDecode?a._onDecode(f):a._legacyOnDecode&&a._legacyOnDecode(f.data),a.$codeOutlineHighlight&&(clearTimeout(a._codeOutlineHighlightRemovalTimeout),a._codeOutlineHighlightRemovalTimeout=void 0,a.$codeOutlineHighlight.setAttribute("viewBox",`${a._scanRegion.x||0} `+`${a._scanRegion.y||0} `+`${a._scanRegion.width||a.$video.videoWidth} `+`${a._scanRegion.height||a.$video.videoHeight}`),a.$codeOutlineHighlight.firstElementChild.setAttribute("points",
f.cornerPoints.map(({x:g,y:k})=>`${g},${k}`).join(" ")),a.$codeOutlineHighlight.style.display="")):a.$codeOutlineHighlight&&!a._codeOutlineHighlightRemovalTimeout&&(a._codeOutlineHighlightRemovalTimeout=setTimeout(()=>a.$codeOutlineHighlight.style.display="none",100))}a._scanFrame()})})}_onDecodeError(a){a!==b.NO_QR_CODE_FOUND&&console.log(a)}_getCameraStream(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(!navigator.mediaDevices)throw"Camera not found.";let c=/^(environment|user)$/.test(a._preferredCamera)?
"facingMode":"deviceId",d=[{width:{min:1024}},{width:{min:768}},{}],f=d.map(g=>Object.assign({},g,{[c]:{exact:a._preferredCamera}}));for(let g of[...f,...d])try{let k=yield navigator.mediaDevices.getUserMedia({video:g,audio:!1}),l=a._getFacingMode(k)||(g.facingMode?a._preferredCamera:"environment"===a._preferredCamera?"user":"environment");return{stream:k,facingMode:l}}catch(k){}throw"Camera not found.";})}_restartVideoStream(){const a=this;return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){let c=
a._paused;(yield a.pause(!0))&&!c&&a._active&&(yield a.start())})}static _stopVideoStream(a){for(let c of a.getTracks())c.stop(),a.removeTrack(c)}_setVideoMirror(a){this.$video.style.transform="scaleX("+("user"===a?-1:1)+")"}_getFacingMode(a){return(a=a.getVideoTracks()[0])?/rear|back|environment/i.test(a.label)?"environment":/front|user|face/i.test(a.label)?"user":null:null}static _drawToCanvas(a,c,d,f=!1){d=d||document.createElement("canvas");let g=c&&c.x?c.x:0,k=c&&c.y?c.y:0,l=c&&c.width?c.width:
a.videoWidth||a.width,p=c&&c.height?c.height:a.videoHeight||a.height;f||(f=c&&c.downScaledWidth?c.downScaledWidth:l,c=c&&c.downScaledHeight?c.downScaledHeight:p,d.width!==f&&(d.width=f),d.height!==c&&(d.height=c));c=d.getContext("2d",{alpha:!1});c.imageSmoothingEnabled=!1;c.drawImage(a,g,k,l,p,0,0,d.width,d.height);return[d,c]}static _loadImage(a){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){if(a instanceof Image)return yield b._awaitImageLoad(a),a;if(a instanceof HTMLVideoElement||
a instanceof HTMLCanvasElement||a instanceof SVGImageElement||"OffscreenCanvas"in window&&a instanceof OffscreenCanvas||"ImageBitmap"in window&&a instanceof ImageBitmap)return a;if(a instanceof File||a instanceof Blob||a instanceof URL||"string"===typeof a){let c=new Image;c.src=a instanceof File||a instanceof Blob?URL.createObjectURL(a):a.toString();try{return yield b._awaitImageLoad(c),c}finally{(a instanceof File||a instanceof Blob)&&URL.revokeObjectURL(c.src)}}else throw"Unsupported image type.";
})}static _awaitImageLoad(a){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){a.complete&&0!==a.naturalWidth||(yield new Promise((c,d)=>{let f=g=>{a.removeEventListener("load",f);a.removeEventListener("error",f);g instanceof ErrorEvent?d("Image load error"):c()};a.addEventListener("load",f);a.addEventListener("error",f)}))})}static _postWorkerMessage(a,c,d,f){return $jscomp.asyncExecutePromiseGeneratorFunction(function*(){return b._postWorkerMessageSync(yield a,c,d,f)})}static _postWorkerMessageSync(a,
c,d,f){if(!(a instanceof Worker))return-1;let g=b._workerMessageId++;a.postMessage({id:g,type:c,data:d},f);return g}}b.DEFAULT_CANVAS_SIZE=400;b.NO_QR_CODE_FOUND="No QR code found";b._disableBarcodeDetector=!1;b._workerMessageId=0;var e=Object.freeze({__proto__:null,createWorker:()=>new Worker(URL.createObjectURL(new Blob(['class x{constructor(a,b){this.width=b;this.height=a.length/b;this.data=a}static createEmpty(a,b){return new x(new Uint8ClampedArray(a*b),a)}get(a,b){return 0>a||a>=this.width||0>b||b>=this.height?!1:!!this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c?1:0}setRegion(a,b,c,d,e){for(let f=b;f<b+d;f++)for(let g=a;g<a+c;g++)this.set(g,f,!!e)}}\nclass A{constructor(a,b,c){this.width=a;a*=b;if(c&&c.length!==a)throw Error("Wrong buffer size");this.data=c||new Uint8ClampedArray(a)}get(a,b){return this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c}}\nclass ba{constructor(a){this.bitOffset=this.byteOffset=0;this.bytes=a}readBits(a){if(1>a||32<a||a>this.available())throw Error("Cannot read "+a.toString()+" bits");var b=0;if(0<this.bitOffset){b=8-this.bitOffset;var c=a<b?a:b;b-=c;b=(this.bytes[this.byteOffset]&255>>8-c<<b)>>b;a-=c;this.bitOffset+=c;8===this.bitOffset&&(this.bitOffset=0,this.byteOffset++)}if(0<a){for(;8<=a;)b=b<<8|this.bytes[this.byteOffset]&255,this.byteOffset++,a-=8;0<a&&(c=8-a,b=b<<a|(this.bytes[this.byteOffset]&255>>c<<c)>>c,\nthis.bitOffset+=a)}return b}available(){return 8*(this.bytes.length-this.byteOffset)-this.bitOffset}}var B,C=B||(B={});C.Numeric="numeric";C.Alphanumeric="alphanumeric";C.Byte="byte";C.Kanji="kanji";C.ECI="eci";C.StructuredAppend="structuredappend";var D,E=D||(D={});E[E.Terminator=0]="Terminator";E[E.Numeric=1]="Numeric";E[E.Alphanumeric=2]="Alphanumeric";E[E.Byte=4]="Byte";E[E.Kanji=8]="Kanji";E[E.ECI=7]="ECI";E[E.StructuredAppend=3]="StructuredAppend";let F="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".split("");\nfunction ca(a,b){let c=[],d="";b=a.readBits([8,16,16][b]);for(let e=0;e<b;e++){let f=a.readBits(8);c.push(f)}try{d+=decodeURIComponent(c.map(e=>`%${("0"+e.toString(16)).substr(-2)}`).join(""))}catch(e){}return{bytes:c,text:d}}\nfunction da(a,b){a=new ba(a);let c=9>=b?0:26>=b?1:2;for(b={text:"",bytes:[],chunks:[],version:b};4<=a.available();){var d=a.readBits(4);if(d===D.Terminator)return b;if(d===D.ECI)0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(7)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(14)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(21)}):b.chunks.push({type:B.ECI,assignmentNumber:-1});else if(d===D.Numeric){var e=a,f=[];d="";for(var g=\ne.readBits([10,12,14][c]);3<=g;){var h=e.readBits(10);if(1E3<=h)throw Error("Invalid numeric value above 999");var k=Math.floor(h/100),m=Math.floor(h/10)%10;h%=10;f.push(48+k,48+m,48+h);d+=k.toString()+m.toString()+h.toString();g-=3}if(2===g){g=e.readBits(7);if(100<=g)throw Error("Invalid numeric value above 99");e=Math.floor(g/10);g%=10;f.push(48+e,48+g);d+=e.toString()+g.toString()}else if(1===g){e=e.readBits(4);if(10<=e)throw Error("Invalid numeric value above 9");f.push(48+e);d+=e.toString()}b.text+=\nd;b.bytes.push(...f);b.chunks.push({type:B.Numeric,text:d})}else if(d===D.Alphanumeric){e=a;f=[];d="";for(g=e.readBits([9,11,13][c]);2<=g;)m=e.readBits(11),k=Math.floor(m/45),m%=45,f.push(F[k].charCodeAt(0),F[m].charCodeAt(0)),d+=F[k]+F[m],g-=2;1===g&&(e=e.readBits(6),f.push(F[e].charCodeAt(0)),d+=F[e]);b.text+=d;b.bytes.push(...f);b.chunks.push({type:B.Alphanumeric,text:d})}else if(d===D.Byte)d=ca(a,c),b.text+=d.text,b.bytes.push(...d.bytes),b.chunks.push({type:B.Byte,bytes:d.bytes,text:d.text});\nelse if(d===D.Kanji){f=a;d=[];e=f.readBits([8,10,12][c]);for(g=0;g<e;g++)k=f.readBits(13),k=Math.floor(k/192)<<8|k%192,k=7936>k?k+33088:k+49472,d.push(k>>8,k&255);f=(new TextDecoder("shift-jis")).decode(Uint8Array.from(d));b.text+=f;b.bytes.push(...d);b.chunks.push({type:B.Kanji,bytes:d,text:f})}else d===D.StructuredAppend&&b.chunks.push({type:B.StructuredAppend,currentSequence:a.readBits(4),totalSequence:a.readBits(4),parity:a.readBits(8)})}if(0===a.available()||0===a.readBits(a.available()))return b}\nclass G{constructor(a,b){if(0===b.length)throw Error("No coefficients.");this.field=a;let c=b.length;if(1<c&&0===b[0]){let d=1;for(;d<c&&0===b[d];)d++;if(d===c)this.coefficients=a.zero.coefficients;else for(this.coefficients=new Uint8ClampedArray(c-d),a=0;a<this.coefficients.length;a++)this.coefficients[a]=b[d+a]}else this.coefficients=b}degree(){return this.coefficients.length-1}isZero(){return 0===this.coefficients[0]}getCoefficient(a){return this.coefficients[this.coefficients.length-1-a]}addOrSubtract(a){if(this.isZero())return a;\nif(a.isZero())return this;let b=this.coefficients;a=a.coefficients;b.length>a.length&&([b,a]=[a,b]);let c=new Uint8ClampedArray(a.length),d=a.length-b.length;for(var e=0;e<d;e++)c[e]=a[e];for(e=d;e<a.length;e++)c[e]=b[e-d]^a[e];return new G(this.field,c)}multiply(aLine truncated
{type:"application/javascript"}))});return b})
//# sourceMappingURL=qr-scanner.legacy.min.js.map
+7 -7
View File
@@ -12,13 +12,13 @@ this._onVisibilityChange);window.removeEventListener("resize",this._updateOverla
!1,this.$video.srcObject)await this.$video.play();else try{let {stream:a,facingMode:b}=await this._getCameraStream();!this._active||this._paused?e._stopVideoStream(a):(this._setVideoMirror(b),this.$video.srcObject=a,await this.$video.play(),this._flashOn&&(this._flashOn=!1,this.turnFlashOn().catch(()=>{})))}catch(a){if(!this._paused)throw this._active=!1,a;}}stop(){this.pause();this._active=!1}async pause(a=!1){this._paused=!0;if(!this._active)return!0;this.$video.pause();this.$overlay&&(this.$overlay.style.display=
"none");let b=()=>{this.$video.srcObject instanceof MediaStream&&(e._stopVideoStream(this.$video.srcObject),this.$video.srcObject=null)};if(a)return b(),!0;await new Promise(c=>setTimeout(c,300));if(!this._paused)return!1;b();return!0}async setCamera(a){a!==this._preferredCamera&&(this._preferredCamera=a,await this._restartVideoStream())}static async scanImage(a,b,c,d,f=!1,h=!1){let m,n=!1;b&&("scanRegion"in b||"qrEngine"in b||"canvas"in b||"disallowCanvasResizing"in b||"alsoTryWithoutScanRegion"in
b||"returnDetailedScanResult"in b)?(m=b.scanRegion,c=b.qrEngine,d=b.canvas,f=b.disallowCanvasResizing||!1,h=b.alsoTryWithoutScanRegion||!1,n=!0):b||c||d||f||h?console.warn("You're using a deprecated api for scanImage which will be removed in the future."):console.warn("Note that the return type of scanImage will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true.");b=!!c;try{let p,k;[c,p]=await Promise.all([c||e.createQrEngine(),e._loadImage(a)]);
[d,k]=e._drawToCanvas(p,m,d,f);let r;if(c instanceof Worker){let g=c;b||g.postMessage({type:"inversionMode",data:"both"});r=await new Promise((l,v)=>{let w,u,t;u=q=>{"qrResult"===q.data.type&&(g.removeEventListener("message",u),g.removeEventListener("error",t),clearTimeout(w),null!==q.data.data?l({data:q.data.data,cornerPoints:e._convertPoints(q.data.cornerPoints,m)}):v(e.NO_QR_CODE_FOUND))};t=q=>{g.removeEventListener("message",u);g.removeEventListener("error",t);clearTimeout(w);v("Scanner error: "+
(q?q.message||q:"Unknown Error"))};g.addEventListener("message",u);g.addEventListener("error",t);w=setTimeout(()=>t("timeout"),1E4);let x=k.getImageData(0,0,d.width,d.height);g.postMessage({type:"decode",data:x},[x.data.buffer])})}else r=await Promise.race([new Promise((g,l)=>window.setTimeout(()=>l("Scanner error: timeout"),1E4)),(async()=>{try{var [g]=await c.detect(d);if(!g)throw e.NO_QR_CODE_FOUND;return{data:g.rawValue,cornerPoints:e._convertPoints(g.cornerPoints,m)}}catch(l){g=l.message||l;
if(/not implemented|service unavailable/.test(g))return e._disableBarcodeDetector=!0,e.scanImage(a,{scanRegion:m,canvas:d,disallowCanvasResizing:f,alsoTryWithoutScanRegion:h});throw`Scanner error: ${g}`;}})()]);return n?r:r.data}catch(p){if(!m||!h)throw p;let k=await e.scanImage(a,{qrEngine:c,canvas:d,disallowCanvasResizing:f});return n?k:k.data}finally{b||e._postWorkerMessage(c,"close")}}setGrayscaleWeights(a,b,c,d=!0){e._postWorkerMessage(this._qrEnginePromise,"grayscaleWeights",{red:a,green:b,
[d,k]=e._drawToCanvas(p,m,d,f);let q;if(c instanceof Worker){let g=c;b||e._postWorkerMessageSync(g,"inversionMode","both");q=await new Promise((l,v)=>{let w,u,r,y=-1;u=t=>{t.data.id===y&&(g.removeEventListener("message",u),g.removeEventListener("error",r),clearTimeout(w),null!==t.data.data?l({data:t.data.data,cornerPoints:e._convertPoints(t.data.cornerPoints,m)}):v(e.NO_QR_CODE_FOUND))};r=t=>{g.removeEventListener("message",u);g.removeEventListener("error",r);clearTimeout(w);v("Scanner error: "+(t?
t.message||t:"Unknown Error"))};g.addEventListener("message",u);g.addEventListener("error",r);w=setTimeout(()=>r("timeout"),1E4);let x=k.getImageData(0,0,d.width,d.height);y=e._postWorkerMessageSync(g,"decode",x,[x.data.buffer])})}else q=await Promise.race([new Promise((g,l)=>window.setTimeout(()=>l("Scanner error: timeout"),1E4)),(async()=>{try{var [g]=await c.detect(d);if(!g)throw e.NO_QR_CODE_FOUND;return{data:g.rawValue,cornerPoints:e._convertPoints(g.cornerPoints,m)}}catch(l){g=l.message||l;
if(/not implemented|service unavailable/.test(g))return e._disableBarcodeDetector=!0,e.scanImage(a,{scanRegion:m,canvas:d,disallowCanvasResizing:f,alsoTryWithoutScanRegion:h});throw`Scanner error: ${g}`;}})()]);return n?q:q.data}catch(p){if(!m||!h)throw p;let k=await e.scanImage(a,{qrEngine:c,canvas:d,disallowCanvasResizing:f});return n?k:k.data}finally{b||e._postWorkerMessage(c,"close")}}setGrayscaleWeights(a,b,c,d=!0){e._postWorkerMessage(this._qrEnginePromise,"grayscaleWeights",{red:a,green:b,
blue:c,useIntegerApproximation:d})}setInversionMode(a){e._postWorkerMessage(this._qrEnginePromise,"inversionMode",a)}static async createQrEngine(a){a&&console.warn("Specifying a worker path is not required and not supported anymore.");return!e._disableBarcodeDetector&&"BarcodeDetector"in window&&BarcodeDetector.getSupportedFormats&&(await BarcodeDetector.getSupportedFormats()).includes("qr_code")?new BarcodeDetector({formats:["qr_code"]}):import("./qr-scanner-worker.min.js").then(b=>b.createWorker())}_onPlay(){this._scanRegion=
this._calculateScanRegion(this.$video);this._updateOverlay();this.$overlay&&(this.$overlay.style.display="");this._scanFrame()}_onLoadedMetaData(){this._scanRegion=this._calculateScanRegion(this.$video);this._updateOverlay()}_onVisibilityChange(){document.hidden?this.pause():this._active&&this.start()}_calculateScanRegion(a){let b=Math.round(2/3*Math.min(a.videoWidth,a.videoHeight));return{x:Math.round((a.videoWidth-b)/2),y:Math.round((a.videoHeight-b)/2),width:b,height:b,downScaledWidth:this._legacyCanvasSize,
downScaledHeight:this._legacyCanvasSize}}_updateOverlay(){requestAnimationFrame(()=>{if(this.$overlay){var a=this.$video,b=a.videoWidth,c=a.videoHeight,d=a.offsetWidth,f=a.offsetHeight,h=a.offsetLeft,m=a.offsetTop,n=window.getComputedStyle(a),p=n.objectFit,k=b/c,r=d/f;switch(p){case "none":var g=b;var l=c;break;case "fill":g=d;l=f;break;default:("cover"===p?k>r:k<r)?(l=f,g=l*k):(g=d,l=g/k),"scale-down"===p&&(g=Math.min(g,b),l=Math.min(l,c))}var [v,w]=n.objectPosition.split(" ").map((t,x)=>{const q=
parseFloat(t);return t.endsWith("%")?(x?f-l:d-g)*q/100:q});n=this._scanRegion.width||b;r=this._scanRegion.height||c;p=this._scanRegion.x||0;var u=this._scanRegion.y||0;k=this.$overlay.style;k.width=`${n/b*g}px`;k.height=`${r/c*l}px`;k.top=`${m+w+u/c*l}px`;c=/scaleX\(-1\)/.test(a.style.transform);k.left=`${h+(c?d-v-g:v)+(c?b-p-n:p)/b*g}px`;k.transform=a.style.transform}})}static _convertPoints(a,b){if(!b)return a;let c=b.x||0,d=b.y||0,f=b.width&&b.downScaledWidth?b.width/b.downScaledWidth:1;b=b.height&&
downScaledHeight:this._legacyCanvasSize}}_updateOverlay(){requestAnimationFrame(()=>{if(this.$overlay){var a=this.$video,b=a.videoWidth,c=a.videoHeight,d=a.offsetWidth,f=a.offsetHeight,h=a.offsetLeft,m=a.offsetTop,n=window.getComputedStyle(a),p=n.objectFit,k=b/c,q=d/f;switch(p){case "none":var g=b;var l=c;break;case "fill":g=d;l=f;break;default:("cover"===p?k>q:k<q)?(l=f,g=l*k):(g=d,l=g/k),"scale-down"===p&&(g=Math.min(g,b),l=Math.min(l,c))}var [v,w]=n.objectPosition.split(" ").map((r,y)=>{const x=
parseFloat(r);return r.endsWith("%")?(y?f-l:d-g)*x/100:x});n=this._scanRegion.width||b;q=this._scanRegion.height||c;p=this._scanRegion.x||0;var u=this._scanRegion.y||0;k=this.$overlay.style;k.width=`${n/b*g}px`;k.height=`${q/c*l}px`;k.top=`${m+w+u/c*l}px`;c=/scaleX\(-1\)/.test(a.style.transform);k.left=`${h+(c?d-v-g:v)+(c?b-p-n:p)/b*g}px`;k.transform=a.style.transform}})}static _convertPoints(a,b){if(!b)return a;let c=b.x||0,d=b.y||0,f=b.width&&b.downScaledWidth?b.width/b.downScaledWidth:1;b=b.height&&
b.downScaledHeight?b.height/b.downScaledHeight:1;for(let h of a)h.x=h.x*f+c,h.y=h.y*b+d;return a}_scanFrame(){!this._active||this.$video.paused||this.$video.ended||("requestVideoFrameCallback"in this.$video?this.$video.requestVideoFrameCallback.bind(this.$video):requestAnimationFrame)(async()=>{if(!(1>=this.$video.readyState)){var a=Date.now()-this._lastScanTimestamp,b=1E3/this._maxScansPerSecond;a<b&&await new Promise(d=>setTimeout(d,b-a));this._lastScanTimestamp=Date.now();try{var c=await e.scanImage(this.$video,
{scanRegion:this._scanRegion,qrEngine:this._qrEnginePromise,canvas:this.$canvas})}catch(d){if(!this._active)return;this._onDecodeError(d)}!e._disableBarcodeDetector||await this._qrEnginePromise instanceof Worker||(this._qrEnginePromise=e.createQrEngine());c?(this._onDecode?this._onDecode(c):this._legacyOnDecode&&this._legacyOnDecode(c.data),this.$codeOutlineHighlight&&(clearTimeout(this._codeOutlineHighlightRemovalTimeout),this._codeOutlineHighlightRemovalTimeout=void 0,this.$codeOutlineHighlight.setAttribute("viewBox",
`${this._scanRegion.x||0} `+`${this._scanRegion.y||0} `+`${this._scanRegion.width||this.$video.videoWidth} `+`${this._scanRegion.height||this.$video.videoHeight}`),this.$codeOutlineHighlight.firstElementChild.setAttribute("points",c.cornerPoints.map(({x:d,y:f})=>`${d},${f}`).join(" ")),this.$codeOutlineHighlight.style.display="")):this.$codeOutlineHighlight&&!this._codeOutlineHighlightRemovalTimeout&&(this._codeOutlineHighlightRemovalTimeout=setTimeout(()=>this.$codeOutlineHighlight.style.display=
@@ -26,6 +26,6 @@ b.downScaledHeight?b.height/b.downScaledHeight:1;for(let h of a)h.x=h.x*f+c,h.y=
"environment"===this._preferredCamera?"user":"environment");return{stream:f,facingMode:h}}catch(f){}throw"Camera not found.";}async _restartVideoStream(){let a=this._paused;await this.pause(!0)&&!a&&this._active&&await this.start()}static _stopVideoStream(a){for(let b of a.getTracks())b.stop(),a.removeTrack(b)}_setVideoMirror(a){this.$video.style.transform="scaleX("+("user"===a?-1:1)+")"}_getFacingMode(a){return(a=a.getVideoTracks()[0])?/rear|back|environment/i.test(a.label)?"environment":/front|user|face/i.test(a.label)?
"user":null:null}static _drawToCanvas(a,b,c,d=!1){c=c||document.createElement("canvas");let f=b&&b.x?b.x:0,h=b&&b.y?b.y:0,m=b&&b.width?b.width:a.videoWidth||a.width,n=b&&b.height?b.height:a.videoHeight||a.height;d||(d=b&&b.downScaledWidth?b.downScaledWidth:m,b=b&&b.downScaledHeight?b.downScaledHeight:n,c.width!==d&&(c.width=d),c.height!==b&&(c.height=b));b=c.getContext("2d",{alpha:!1});b.imageSmoothingEnabled=!1;b.drawImage(a,f,h,m,n,0,0,c.width,c.height);return[c,b]}static async _loadImage(a){if(a instanceof
Image)return await e._awaitImageLoad(a),a;if(a instanceof HTMLVideoElement||a instanceof HTMLCanvasElement||a instanceof SVGImageElement||"OffscreenCanvas"in window&&a instanceof OffscreenCanvas||"ImageBitmap"in window&&a instanceof ImageBitmap)return a;if(a instanceof File||a instanceof Blob||a instanceof URL||"string"===typeof a){let b=new Image;b.src=a instanceof File||a instanceof Blob?URL.createObjectURL(a):a.toString();try{return await e._awaitImageLoad(b),b}finally{(a instanceof File||a instanceof
Blob)&&URL.revokeObjectURL(b.src)}}else throw"Unsupported image type.";}static async _awaitImageLoad(a){a.complete&&0!==a.naturalWidth||await new Promise((b,c)=>{let d=f=>{a.removeEventListener("load",d);a.removeEventListener("error",d);f instanceof ErrorEvent?c("Image load error"):b()};a.addEventListener("load",d);a.addEventListener("error",d)})}static async _postWorkerMessage(a,b,c){a=await a;a instanceof Worker&&a.postMessage({type:b,data:c})}}e.DEFAULT_CANVAS_SIZE=400;e.NO_QR_CODE_FOUND="No QR code found";
e._disableBarcodeDetector=!1;export default e
Blob)&&URL.revokeObjectURL(b.src)}}else throw"Unsupported image type.";}static async _awaitImageLoad(a){a.complete&&0!==a.naturalWidth||await new Promise((b,c)=>{let d=f=>{a.removeEventListener("load",d);a.removeEventListener("error",d);f instanceof ErrorEvent?c("Image load error"):b()};a.addEventListener("load",d);a.addEventListener("error",d)})}static async _postWorkerMessage(a,b,c,d){return e._postWorkerMessageSync(await a,b,c,d)}static _postWorkerMessageSync(a,b,c,d){if(!(a instanceof Worker))return-1;
let f=e._workerMessageId++;a.postMessage({id:f,type:b,data:c},d);return f}}e.DEFAULT_CANVAS_SIZE=400;e.NO_QR_CODE_FOUND="No QR code found";e._disableBarcodeDetector=!1;e._workerMessageId=0;export default e
//# sourceMappingURL=qr-scanner.min.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"qr-scanner.min.js","sources":["src/qr-scanner.ts"],"sourcesContent":["class QrScanner {\n static readonly DEFAULT_CANVAS_SIZE = 400;\n static readonly NO_QR_CODE_FOUND = 'No QR code found';\n private static _disableBarcodeDetector = false;\n\n /** @deprecated */\n static set WORKER_PATH(workerPath: string) {\n console.warn('Setting QrScanner.WORKER_PATH is not required and not supported anymore. '\n + 'Have a look at the README for new setup instructions.');\n }\n\n static async hasCamera(): Promise<boolean> {\n try {\n return !!(await QrScanner.listCameras(false)).length;\n } catch (e) {\n return false;\n }\n }\n\n static async listCameras(requestLabels = false): Promise<Array<QrScanner.Camera>> {\n if (!navigator.mediaDevices) return [];\n\n const enumerateCameras = async (): Promise<Array<MediaDeviceInfo>> =>\n (await navigator.mediaDevices.enumerateDevices()).filter((device) => device.kind === 'videoinput');\n\n // Note that enumerateDevices can always be called and does not prompt the user for permission.\n // However, enumerateDevices only includes device labels if served via https and an active media stream exists\n // or permission to access the camera was given. Therefore, if we're not getting labels but labels are requested\n // ask for camera permission by opening a stream.\n let openedStream: MediaStream | undefined;\n try {\n if (requestLabels && (await enumerateCameras()).every((camera) => !camera.label)) {\n openedStream = await navigator.mediaDevices.getUserMedia({ audio: false, video: true });\n }\n } catch (e) {\n // Fail gracefully, especially if the device has no camera or on mobile when the camera is already in use\n // and some browsers disallow a second stream.\n }\n\n try {\n return (await enumerateCameras()).map((camera, i) => ({\n id: camera.deviceId,\n label: camera.label || (i === 0 ? 'Default Camera' : `Camera ${i + 1}`),\n }));\n } finally {\n // close the stream we just opened for getting camera access for listing the device labels\n if (openedStream) {\n console.warn('Call listCameras after successfully starting a QR scanner to avoid creating '\n + 'a temporary video stream');\n QrScanner._stopVideoStream(openedStream);\n }\n }\n }\n\n readonly $video: HTMLVideoElement;\n readonly $canvas: HTMLCanvasElement;\n readonly $overlay?: HTMLDivElement;\n private readonly $codeOutlineHighlight?: SVGSVGElement;\n private readonly _onDecode?: (result: QrScanner.ScanResult) => void;\n private readonly _legacyOnDecode?: (result: string) => void;\n private readonly _legacyCanvasSize: number = QrScanner.DEFAULT_CANVAS_SIZE;\n private _preferredCamera: QrScanner.FacingMode | QrScanner.DeviceId = 'environment';\n private readonly _maxScansPerSecond: number = 25;\n private _lastScanTimestamp: number = -1;\n private _scanRegion: QrScanner.ScanRegion;\n private _codeOutlineHighlightRemovalTimeout?: number;\n private _qrEnginePromise: Promise<Worker | BarcodeDetector>\n private _active: boolean = false;\n private _paused: boolean = false;\n private _flashOn: boolean = false;\n private _destroyed: boolean = false;\n\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: QrScanner.ScanResult) => void,\n options: {\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n maxScansPerSecond?: number;\n highlightScanRegion?: boolean,\n highlightCodeOutline?: boolean,\n overlay?: HTMLDivElement,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n canvasSize?: number,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(video: HTMLVideoElement, onDecode: (result: string) => void, canvasSize?: number);\n constructor(\n video: HTMLLine truncated
{"version":3,"file":"qr-scanner.min.js","sources":["src/qr-scanner.ts"],"sourcesContent":["class QrScanner {\n static readonly DEFAULT_CANVAS_SIZE = 400;\n static readonly NO_QR_CODE_FOUND = 'No QR code found';\n private static _disableBarcodeDetector = false;\n private static _workerMessageId = 0;\n\n /** @deprecated */\n static set WORKER_PATH(workerPath: string) {\n console.warn('Setting QrScanner.WORKER_PATH is not required and not supported anymore. '\n + 'Have a look at the README for new setup instructions.');\n }\n\n static async hasCamera(): Promise<boolean> {\n try {\n return !!(await QrScanner.listCameras(false)).length;\n } catch (e) {\n return false;\n }\n }\n\n static async listCameras(requestLabels = false): Promise<Array<QrScanner.Camera>> {\n if (!navigator.mediaDevices) return [];\n\n const enumerateCameras = async (): Promise<Array<MediaDeviceInfo>> =>\n (await navigator.mediaDevices.enumerateDevices()).filter((device) => device.kind === 'videoinput');\n\n // Note that enumerateDevices can always be called and does not prompt the user for permission.\n // However, enumerateDevices only includes device labels if served via https and an active media stream exists\n // or permission to access the camera was given. Therefore, if we're not getting labels but labels are requested\n // ask for camera permission by opening a stream.\n let openedStream: MediaStream | undefined;\n try {\n if (requestLabels && (await enumerateCameras()).every((camera) => !camera.label)) {\n openedStream = await navigator.mediaDevices.getUserMedia({ audio: false, video: true });\n }\n } catch (e) {\n // Fail gracefully, especially if the device has no camera or on mobile when the camera is already in use\n // and some browsers disallow a second stream.\n }\n\n try {\n return (await enumerateCameras()).map((camera, i) => ({\n id: camera.deviceId,\n label: camera.label || (i === 0 ? 'Default Camera' : `Camera ${i + 1}`),\n }));\n } finally {\n // close the stream we just opened for getting camera access for listing the device labels\n if (openedStream) {\n console.warn('Call listCameras after successfully starting a QR scanner to avoid creating '\n + 'a temporary video stream');\n QrScanner._stopVideoStream(openedStream);\n }\n }\n }\n\n readonly $video: HTMLVideoElement;\n readonly $canvas: HTMLCanvasElement;\n readonly $overlay?: HTMLDivElement;\n private readonly $codeOutlineHighlight?: SVGSVGElement;\n private readonly _onDecode?: (result: QrScanner.ScanResult) => void;\n private readonly _legacyOnDecode?: (result: string) => void;\n private readonly _legacyCanvasSize: number = QrScanner.DEFAULT_CANVAS_SIZE;\n private _preferredCamera: QrScanner.FacingMode | QrScanner.DeviceId = 'environment';\n private readonly _maxScansPerSecond: number = 25;\n private _lastScanTimestamp: number = -1;\n private _scanRegion: QrScanner.ScanRegion;\n private _codeOutlineHighlightRemovalTimeout?: number;\n private _qrEnginePromise: Promise<Worker | BarcodeDetector>\n private _active: boolean = false;\n private _paused: boolean = false;\n private _flashOn: boolean = false;\n private _destroyed: boolean = false;\n\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: QrScanner.ScanResult) => void,\n options: {\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n maxScansPerSecond?: number;\n highlightScanRegion?: boolean,\n highlightCodeOutline?: boolean,\n overlay?: HTMLDivElement,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n canvasSize?: number,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(video: HTMLVideoElement, onDecode: (result: string) => void, canvasSize?: numbeLine truncated
+7 -7
View File
@@ -12,13 +12,13 @@ this._onVisibilityChange);window.removeEventListener("resize",this._updateOverla
!1,this.$video.srcObject)await this.$video.play();else try{let {stream:a,facingMode:b}=await this._getCameraStream();!this._active||this._paused?e._stopVideoStream(a):(this._setVideoMirror(b),this.$video.srcObject=a,await this.$video.play(),this._flashOn&&(this._flashOn=!1,this.turnFlashOn().catch(()=>{})))}catch(a){if(!this._paused)throw this._active=!1,a;}}stop(){this.pause();this._active=!1}async pause(a=!1){this._paused=!0;if(!this._active)return!0;this.$video.pause();this.$overlay&&(this.$overlay.style.display=
"none");let b=()=>{this.$video.srcObject instanceof MediaStream&&(e._stopVideoStream(this.$video.srcObject),this.$video.srcObject=null)};if(a)return b(),!0;await new Promise(c=>setTimeout(c,300));if(!this._paused)return!1;b();return!0}async setCamera(a){a!==this._preferredCamera&&(this._preferredCamera=a,await this._restartVideoStream())}static async scanImage(a,b,c,d,f=!1,h=!1){let m,n=!1;b&&("scanRegion"in b||"qrEngine"in b||"canvas"in b||"disallowCanvasResizing"in b||"alsoTryWithoutScanRegion"in
b||"returnDetailedScanResult"in b)?(m=b.scanRegion,c=b.qrEngine,d=b.canvas,f=b.disallowCanvasResizing||!1,h=b.alsoTryWithoutScanRegion||!1,n=!0):b||c||d||f||h?console.warn("You're using a deprecated api for scanImage which will be removed in the future."):console.warn("Note that the return type of scanImage will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true.");b=!!c;try{let p,k;[c,p]=await Promise.all([c||e.createQrEngine(),e._loadImage(a)]);
[d,k]=e._drawToCanvas(p,m,d,f);let r;if(c instanceof Worker){let g=c;b||g.postMessage({type:"inversionMode",data:"both"});r=await new Promise((l,v)=>{let w,u,t;u=q=>{"qrResult"===q.data.type&&(g.removeEventListener("message",u),g.removeEventListener("error",t),clearTimeout(w),null!==q.data.data?l({data:q.data.data,cornerPoints:e._convertPoints(q.data.cornerPoints,m)}):v(e.NO_QR_CODE_FOUND))};t=q=>{g.removeEventListener("message",u);g.removeEventListener("error",t);clearTimeout(w);v("Scanner error: "+
(q?q.message||q:"Unknown Error"))};g.addEventListener("message",u);g.addEventListener("error",t);w=setTimeout(()=>t("timeout"),1E4);let x=k.getImageData(0,0,d.width,d.height);g.postMessage({type:"decode",data:x},[x.data.buffer])})}else r=await Promise.race([new Promise((g,l)=>window.setTimeout(()=>l("Scanner error: timeout"),1E4)),(async()=>{try{var [g]=await c.detect(d);if(!g)throw e.NO_QR_CODE_FOUND;return{data:g.rawValue,cornerPoints:e._convertPoints(g.cornerPoints,m)}}catch(l){g=l.message||l;
if(/not implemented|service unavailable/.test(g))return e._disableBarcodeDetector=!0,e.scanImage(a,{scanRegion:m,canvas:d,disallowCanvasResizing:f,alsoTryWithoutScanRegion:h});throw`Scanner error: ${g}`;}})()]);return n?r:r.data}catch(p){if(!m||!h)throw p;let k=await e.scanImage(a,{qrEngine:c,canvas:d,disallowCanvasResizing:f});return n?k:k.data}finally{b||e._postWorkerMessage(c,"close")}}setGrayscaleWeights(a,b,c,d=!0){e._postWorkerMessage(this._qrEnginePromise,"grayscaleWeights",{red:a,green:b,
[d,k]=e._drawToCanvas(p,m,d,f);let q;if(c instanceof Worker){let g=c;b||e._postWorkerMessageSync(g,"inversionMode","both");q=await new Promise((l,v)=>{let w,u,r,y=-1;u=t=>{t.data.id===y&&(g.removeEventListener("message",u),g.removeEventListener("error",r),clearTimeout(w),null!==t.data.data?l({data:t.data.data,cornerPoints:e._convertPoints(t.data.cornerPoints,m)}):v(e.NO_QR_CODE_FOUND))};r=t=>{g.removeEventListener("message",u);g.removeEventListener("error",r);clearTimeout(w);v("Scanner error: "+(t?
t.message||t:"Unknown Error"))};g.addEventListener("message",u);g.addEventListener("error",r);w=setTimeout(()=>r("timeout"),1E4);let x=k.getImageData(0,0,d.width,d.height);y=e._postWorkerMessageSync(g,"decode",x,[x.data.buffer])})}else q=await Promise.race([new Promise((g,l)=>window.setTimeout(()=>l("Scanner error: timeout"),1E4)),(async()=>{try{var [g]=await c.detect(d);if(!g)throw e.NO_QR_CODE_FOUND;return{data:g.rawValue,cornerPoints:e._convertPoints(g.cornerPoints,m)}}catch(l){g=l.message||l;
if(/not implemented|service unavailable/.test(g))return e._disableBarcodeDetector=!0,e.scanImage(a,{scanRegion:m,canvas:d,disallowCanvasResizing:f,alsoTryWithoutScanRegion:h});throw`Scanner error: ${g}`;}})()]);return n?q:q.data}catch(p){if(!m||!h)throw p;let k=await e.scanImage(a,{qrEngine:c,canvas:d,disallowCanvasResizing:f});return n?k:k.data}finally{b||e._postWorkerMessage(c,"close")}}setGrayscaleWeights(a,b,c,d=!0){e._postWorkerMessage(this._qrEnginePromise,"grayscaleWeights",{red:a,green:b,
blue:c,useIntegerApproximation:d})}setInversionMode(a){e._postWorkerMessage(this._qrEnginePromise,"inversionMode",a)}static async createQrEngine(a){a&&console.warn("Specifying a worker path is not required and not supported anymore.");return!e._disableBarcodeDetector&&"BarcodeDetector"in window&&BarcodeDetector.getSupportedFormats&&(await BarcodeDetector.getSupportedFormats()).includes("qr_code")?new BarcodeDetector({formats:["qr_code"]}):import("./qr-scanner-worker.min.js").then(b=>b.createWorker())}_onPlay(){this._scanRegion=
this._calculateScanRegion(this.$video);this._updateOverlay();this.$overlay&&(this.$overlay.style.display="");this._scanFrame()}_onLoadedMetaData(){this._scanRegion=this._calculateScanRegion(this.$video);this._updateOverlay()}_onVisibilityChange(){document.hidden?this.pause():this._active&&this.start()}_calculateScanRegion(a){let b=Math.round(2/3*Math.min(a.videoWidth,a.videoHeight));return{x:Math.round((a.videoWidth-b)/2),y:Math.round((a.videoHeight-b)/2),width:b,height:b,downScaledWidth:this._legacyCanvasSize,
downScaledHeight:this._legacyCanvasSize}}_updateOverlay(){requestAnimationFrame(()=>{if(this.$overlay){var a=this.$video,b=a.videoWidth,c=a.videoHeight,d=a.offsetWidth,f=a.offsetHeight,h=a.offsetLeft,m=a.offsetTop,n=window.getComputedStyle(a),p=n.objectFit,k=b/c,r=d/f;switch(p){case "none":var g=b;var l=c;break;case "fill":g=d;l=f;break;default:("cover"===p?k>r:k<r)?(l=f,g=l*k):(g=d,l=g/k),"scale-down"===p&&(g=Math.min(g,b),l=Math.min(l,c))}var [v,w]=n.objectPosition.split(" ").map((t,x)=>{const q=
parseFloat(t);return t.endsWith("%")?(x?f-l:d-g)*q/100:q});n=this._scanRegion.width||b;r=this._scanRegion.height||c;p=this._scanRegion.x||0;var u=this._scanRegion.y||0;k=this.$overlay.style;k.width=`${n/b*g}px`;k.height=`${r/c*l}px`;k.top=`${m+w+u/c*l}px`;c=/scaleX\(-1\)/.test(a.style.transform);k.left=`${h+(c?d-v-g:v)+(c?b-p-n:p)/b*g}px`;k.transform=a.style.transform}})}static _convertPoints(a,b){if(!b)return a;let c=b.x||0,d=b.y||0,f=b.width&&b.downScaledWidth?b.width/b.downScaledWidth:1;b=b.height&&
downScaledHeight:this._legacyCanvasSize}}_updateOverlay(){requestAnimationFrame(()=>{if(this.$overlay){var a=this.$video,b=a.videoWidth,c=a.videoHeight,d=a.offsetWidth,f=a.offsetHeight,h=a.offsetLeft,m=a.offsetTop,n=window.getComputedStyle(a),p=n.objectFit,k=b/c,q=d/f;switch(p){case "none":var g=b;var l=c;break;case "fill":g=d;l=f;break;default:("cover"===p?k>q:k<q)?(l=f,g=l*k):(g=d,l=g/k),"scale-down"===p&&(g=Math.min(g,b),l=Math.min(l,c))}var [v,w]=n.objectPosition.split(" ").map((r,y)=>{const x=
parseFloat(r);return r.endsWith("%")?(y?f-l:d-g)*x/100:x});n=this._scanRegion.width||b;q=this._scanRegion.height||c;p=this._scanRegion.x||0;var u=this._scanRegion.y||0;k=this.$overlay.style;k.width=`${n/b*g}px`;k.height=`${q/c*l}px`;k.top=`${m+w+u/c*l}px`;c=/scaleX\(-1\)/.test(a.style.transform);k.left=`${h+(c?d-v-g:v)+(c?b-p-n:p)/b*g}px`;k.transform=a.style.transform}})}static _convertPoints(a,b){if(!b)return a;let c=b.x||0,d=b.y||0,f=b.width&&b.downScaledWidth?b.width/b.downScaledWidth:1;b=b.height&&
b.downScaledHeight?b.height/b.downScaledHeight:1;for(let h of a)h.x=h.x*f+c,h.y=h.y*b+d;return a}_scanFrame(){!this._active||this.$video.paused||this.$video.ended||("requestVideoFrameCallback"in this.$video?this.$video.requestVideoFrameCallback.bind(this.$video):requestAnimationFrame)(async()=>{if(!(1>=this.$video.readyState)){var a=Date.now()-this._lastScanTimestamp,b=1E3/this._maxScansPerSecond;a<b&&await new Promise(d=>setTimeout(d,b-a));this._lastScanTimestamp=Date.now();try{var c=await e.scanImage(this.$video,
{scanRegion:this._scanRegion,qrEngine:this._qrEnginePromise,canvas:this.$canvas})}catch(d){if(!this._active)return;this._onDecodeError(d)}!e._disableBarcodeDetector||await this._qrEnginePromise instanceof Worker||(this._qrEnginePromise=e.createQrEngine());c?(this._onDecode?this._onDecode(c):this._legacyOnDecode&&this._legacyOnDecode(c.data),this.$codeOutlineHighlight&&(clearTimeout(this._codeOutlineHighlightRemovalTimeout),this._codeOutlineHighlightRemovalTimeout=void 0,this.$codeOutlineHighlight.setAttribute("viewBox",
`${this._scanRegion.x||0} `+`${this._scanRegion.y||0} `+`${this._scanRegion.width||this.$video.videoWidth} `+`${this._scanRegion.height||this.$video.videoHeight}`),this.$codeOutlineHighlight.firstElementChild.setAttribute("points",c.cornerPoints.map(({x:d,y:f})=>`${d},${f}`).join(" ")),this.$codeOutlineHighlight.style.display="")):this.$codeOutlineHighlight&&!this._codeOutlineHighlightRemovalTimeout&&(this._codeOutlineHighlightRemovalTimeout=setTimeout(()=>this.$codeOutlineHighlight.style.display=
@@ -26,6 +26,6 @@ b.downScaledHeight?b.height/b.downScaledHeight:1;for(let h of a)h.x=h.x*f+c,h.y=
"environment"===this._preferredCamera?"user":"environment");return{stream:f,facingMode:h}}catch(f){}throw"Camera not found.";}async _restartVideoStream(){let a=this._paused;await this.pause(!0)&&!a&&this._active&&await this.start()}static _stopVideoStream(a){for(let b of a.getTracks())b.stop(),a.removeTrack(b)}_setVideoMirror(a){this.$video.style.transform="scaleX("+("user"===a?-1:1)+")"}_getFacingMode(a){return(a=a.getVideoTracks()[0])?/rear|back|environment/i.test(a.label)?"environment":/front|user|face/i.test(a.label)?
"user":null:null}static _drawToCanvas(a,b,c,d=!1){c=c||document.createElement("canvas");let f=b&&b.x?b.x:0,h=b&&b.y?b.y:0,m=b&&b.width?b.width:a.videoWidth||a.width,n=b&&b.height?b.height:a.videoHeight||a.height;d||(d=b&&b.downScaledWidth?b.downScaledWidth:m,b=b&&b.downScaledHeight?b.downScaledHeight:n,c.width!==d&&(c.width=d),c.height!==b&&(c.height=b));b=c.getContext("2d",{alpha:!1});b.imageSmoothingEnabled=!1;b.drawImage(a,f,h,m,n,0,0,c.width,c.height);return[c,b]}static async _loadImage(a){if(a instanceof
Image)return await e._awaitImageLoad(a),a;if(a instanceof HTMLVideoElement||a instanceof HTMLCanvasElement||a instanceof SVGImageElement||"OffscreenCanvas"in window&&a instanceof OffscreenCanvas||"ImageBitmap"in window&&a instanceof ImageBitmap)return a;if(a instanceof File||a instanceof Blob||a instanceof URL||"string"===typeof a){let b=new Image;b.src=a instanceof File||a instanceof Blob?URL.createObjectURL(a):a.toString();try{return await e._awaitImageLoad(b),b}finally{(a instanceof File||a instanceof
Blob)&&URL.revokeObjectURL(b.src)}}else throw"Unsupported image type.";}static async _awaitImageLoad(a){a.complete&&0!==a.naturalWidth||await new Promise((b,c)=>{let d=f=>{a.removeEventListener("load",d);a.removeEventListener("error",d);f instanceof ErrorEvent?c("Image load error"):b()};a.addEventListener("load",d);a.addEventListener("error",d)})}static async _postWorkerMessage(a,b,c){a=await a;a instanceof Worker&&a.postMessage({type:b,data:c})}}e.DEFAULT_CANVAS_SIZE=400;e.NO_QR_CODE_FOUND="No QR code found";
e._disableBarcodeDetector=!1;return e})
Blob)&&URL.revokeObjectURL(b.src)}}else throw"Unsupported image type.";}static async _awaitImageLoad(a){a.complete&&0!==a.naturalWidth||await new Promise((b,c)=>{let d=f=>{a.removeEventListener("load",d);a.removeEventListener("error",d);f instanceof ErrorEvent?c("Image load error"):b()};a.addEventListener("load",d);a.addEventListener("error",d)})}static async _postWorkerMessage(a,b,c,d){return e._postWorkerMessageSync(await a,b,c,d)}static _postWorkerMessageSync(a,b,c,d){if(!(a instanceof Worker))return-1;
let f=e._workerMessageId++;a.postMessage({id:f,type:b,data:c},d);return f}}e.DEFAULT_CANVAS_SIZE=400;e.NO_QR_CODE_FOUND="No QR code found";e._disableBarcodeDetector=!1;e._workerMessageId=0;return e})
//# sourceMappingURL=qr-scanner.umd.min.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"qr-scanner.umd.min.js","sources":["src/qr-scanner.ts"],"sourcesContent":["class QrScanner {\n static readonly DEFAULT_CANVAS_SIZE = 400;\n static readonly NO_QR_CODE_FOUND = 'No QR code found';\n private static _disableBarcodeDetector = false;\n\n /** @deprecated */\n static set WORKER_PATH(workerPath: string) {\n console.warn('Setting QrScanner.WORKER_PATH is not required and not supported anymore. '\n + 'Have a look at the README for new setup instructions.');\n }\n\n static async hasCamera(): Promise<boolean> {\n try {\n return !!(await QrScanner.listCameras(false)).length;\n } catch (e) {\n return false;\n }\n }\n\n static async listCameras(requestLabels = false): Promise<Array<QrScanner.Camera>> {\n if (!navigator.mediaDevices) return [];\n\n const enumerateCameras = async (): Promise<Array<MediaDeviceInfo>> =>\n (await navigator.mediaDevices.enumerateDevices()).filter((device) => device.kind === 'videoinput');\n\n // Note that enumerateDevices can always be called and does not prompt the user for permission.\n // However, enumerateDevices only includes device labels if served via https and an active media stream exists\n // or permission to access the camera was given. Therefore, if we're not getting labels but labels are requested\n // ask for camera permission by opening a stream.\n let openedStream: MediaStream | undefined;\n try {\n if (requestLabels && (await enumerateCameras()).every((camera) => !camera.label)) {\n openedStream = await navigator.mediaDevices.getUserMedia({ audio: false, video: true });\n }\n } catch (e) {\n // Fail gracefully, especially if the device has no camera or on mobile when the camera is already in use\n // and some browsers disallow a second stream.\n }\n\n try {\n return (await enumerateCameras()).map((camera, i) => ({\n id: camera.deviceId,\n label: camera.label || (i === 0 ? 'Default Camera' : `Camera ${i + 1}`),\n }));\n } finally {\n // close the stream we just opened for getting camera access for listing the device labels\n if (openedStream) {\n console.warn('Call listCameras after successfully starting a QR scanner to avoid creating '\n + 'a temporary video stream');\n QrScanner._stopVideoStream(openedStream);\n }\n }\n }\n\n readonly $video: HTMLVideoElement;\n readonly $canvas: HTMLCanvasElement;\n readonly $overlay?: HTMLDivElement;\n private readonly $codeOutlineHighlight?: SVGSVGElement;\n private readonly _onDecode?: (result: QrScanner.ScanResult) => void;\n private readonly _legacyOnDecode?: (result: string) => void;\n private readonly _legacyCanvasSize: number = QrScanner.DEFAULT_CANVAS_SIZE;\n private _preferredCamera: QrScanner.FacingMode | QrScanner.DeviceId = 'environment';\n private readonly _maxScansPerSecond: number = 25;\n private _lastScanTimestamp: number = -1;\n private _scanRegion: QrScanner.ScanRegion;\n private _codeOutlineHighlightRemovalTimeout?: number;\n private _qrEnginePromise: Promise<Worker | BarcodeDetector>\n private _active: boolean = false;\n private _paused: boolean = false;\n private _flashOn: boolean = false;\n private _destroyed: boolean = false;\n\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: QrScanner.ScanResult) => void,\n options: {\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n maxScansPerSecond?: number;\n highlightScanRegion?: boolean,\n highlightCodeOutline?: boolean,\n overlay?: HTMLDivElement,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n canvasSize?: number,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(video: HTMLVideoElement, onDecode: (result: string) => void, canvasSize?: number);\n constructor(\n video: Line truncated
{"version":3,"file":"qr-scanner.umd.min.js","sources":["src/qr-scanner.ts"],"sourcesContent":["class QrScanner {\n static readonly DEFAULT_CANVAS_SIZE = 400;\n static readonly NO_QR_CODE_FOUND = 'No QR code found';\n private static _disableBarcodeDetector = false;\n private static _workerMessageId = 0;\n\n /** @deprecated */\n static set WORKER_PATH(workerPath: string) {\n console.warn('Setting QrScanner.WORKER_PATH is not required and not supported anymore. '\n + 'Have a look at the README for new setup instructions.');\n }\n\n static async hasCamera(): Promise<boolean> {\n try {\n return !!(await QrScanner.listCameras(false)).length;\n } catch (e) {\n return false;\n }\n }\n\n static async listCameras(requestLabels = false): Promise<Array<QrScanner.Camera>> {\n if (!navigator.mediaDevices) return [];\n\n const enumerateCameras = async (): Promise<Array<MediaDeviceInfo>> =>\n (await navigator.mediaDevices.enumerateDevices()).filter((device) => device.kind === 'videoinput');\n\n // Note that enumerateDevices can always be called and does not prompt the user for permission.\n // However, enumerateDevices only includes device labels if served via https and an active media stream exists\n // or permission to access the camera was given. Therefore, if we're not getting labels but labels are requested\n // ask for camera permission by opening a stream.\n let openedStream: MediaStream | undefined;\n try {\n if (requestLabels && (await enumerateCameras()).every((camera) => !camera.label)) {\n openedStream = await navigator.mediaDevices.getUserMedia({ audio: false, video: true });\n }\n } catch (e) {\n // Fail gracefully, especially if the device has no camera or on mobile when the camera is already in use\n // and some browsers disallow a second stream.\n }\n\n try {\n return (await enumerateCameras()).map((camera, i) => ({\n id: camera.deviceId,\n label: camera.label || (i === 0 ? 'Default Camera' : `Camera ${i + 1}`),\n }));\n } finally {\n // close the stream we just opened for getting camera access for listing the device labels\n if (openedStream) {\n console.warn('Call listCameras after successfully starting a QR scanner to avoid creating '\n + 'a temporary video stream');\n QrScanner._stopVideoStream(openedStream);\n }\n }\n }\n\n readonly $video: HTMLVideoElement;\n readonly $canvas: HTMLCanvasElement;\n readonly $overlay?: HTMLDivElement;\n private readonly $codeOutlineHighlight?: SVGSVGElement;\n private readonly _onDecode?: (result: QrScanner.ScanResult) => void;\n private readonly _legacyOnDecode?: (result: string) => void;\n private readonly _legacyCanvasSize: number = QrScanner.DEFAULT_CANVAS_SIZE;\n private _preferredCamera: QrScanner.FacingMode | QrScanner.DeviceId = 'environment';\n private readonly _maxScansPerSecond: number = 25;\n private _lastScanTimestamp: number = -1;\n private _scanRegion: QrScanner.ScanRegion;\n private _codeOutlineHighlightRemovalTimeout?: number;\n private _qrEnginePromise: Promise<Worker | BarcodeDetector>\n private _active: boolean = false;\n private _paused: boolean = false;\n private _flashOn: boolean = false;\n private _destroyed: boolean = false;\n\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: QrScanner.ScanResult) => void,\n options: {\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n maxScansPerSecond?: number;\n highlightScanRegion?: boolean,\n highlightCodeOutline?: boolean,\n overlay?: HTMLDivElement,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n canvasSize?: number,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(video: HTMLVideoElement, onDecode: (result: string) => void, canvasSize?: nLine truncated
+31 -11
View File
@@ -2,6 +2,7 @@ class QrScanner {
static readonly DEFAULT_CANVAS_SIZE = 400;
static readonly NO_QR_CODE_FOUND = 'No QR code found';
private static _disableBarcodeDetector = false;
private static _workerMessageId = 0;
/** @deprecated */
static set WORKER_PATH(workerPath: string) {
@@ -503,15 +504,16 @@ class QrScanner {
if (qrEngine instanceof Worker) {
const qrEngineWorker = qrEngine; // for ts to know that it's still a worker later in the event listeners
if (!gotExternalEngine) {
// Enable scanning of inverted color qr codes. Not using _postWorkerMessage as it's async
qrEngineWorker.postMessage({ type: 'inversionMode', data: 'both' });
// Enable scanning of inverted color qr codes.
QrScanner._postWorkerMessageSync(qrEngineWorker, 'inversionMode', 'both');
}
detailedScanResult = await new Promise((resolve, reject) => {
let timeout: number;
let onMessage: (event: MessageEvent) => void;
let onError: (error: ErrorEvent | string) => void;
let expectedResponseId = -1;
onMessage = (event: MessageEvent) => {
if (event.data.type !== 'qrResult') {
if (event.data.id !== expectedResponseId) {
return;
}
qrEngineWorker.removeEventListener('message', onMessage);
@@ -537,10 +539,12 @@ class QrScanner {
qrEngineWorker.addEventListener('error', onError);
timeout = setTimeout(() => onError('timeout'), 10000);
const imageData = canvasContext.getImageData(0, 0, canvas!.width, canvas!.height);
qrEngineWorker.postMessage({
type: 'decode',
data: imageData
}, [imageData.data.buffer]);
expectedResponseId = QrScanner._postWorkerMessageSync(
qrEngineWorker,
'decode',
imageData,
[imageData.data.buffer],
);
});
} else {
detailedScanResult = await Promise.race([
@@ -1017,10 +1021,26 @@ class QrScanner {
qrEngineOrQrEnginePromise: Worker | BarcodeDetector | Promise<Worker | BarcodeDetector>,
type: string,
data?: any,
): Promise<void> {
const qrEngine = await qrEngineOrQrEnginePromise;
if (!(qrEngine instanceof Worker)) return;
qrEngine.postMessage({ type, data });
transfer?: Transferable[],
): Promise<number> {
return QrScanner._postWorkerMessageSync(await qrEngineOrQrEnginePromise, type, data, transfer);
}
// sync version of _postWorkerMessage without performance overhead of async functions
private static _postWorkerMessageSync(
qrEngine: Worker | BarcodeDetector,
type: string,
data?: any,
transfer?: Transferable[],
): number {
if (!(qrEngine instanceof Worker)) return -1;
const id = QrScanner._workerMessageId++;
qrEngine.postMessage({
id,
type,
data,
}, transfer);
return id;
}
}
+5 -2
View File
@@ -18,12 +18,13 @@ let grayscaleWeights: GrayscaleWeights = {
};
self.onmessage = event => {
const id = event['data']['id'];
const type = event['data']['type'];
const data = event['data']['data'];
switch (type) {
case 'decode':
decode(data);
decode(data, id);
break;
case 'grayscaleWeights':
setGrayscaleWeights(data);
@@ -38,7 +39,7 @@ self.onmessage = event => {
}
};
function decode(data: { data: Uint8ClampedArray, width: number, height: number }): void {
function decode(data: { data: Uint8ClampedArray, width: number, height: number }, requestId: number): void {
const rgbaData = data['data'];
const width = data['width'];
const height = data['height'];
@@ -48,6 +49,7 @@ function decode(data: { data: Uint8ClampedArray, width: number, height: number }
});
if (!result) {
(self as unknown as Worker).postMessage({
id: requestId,
type: 'qrResult',
data: null,
});
@@ -55,6 +57,7 @@ function decode(data: { data: Uint8ClampedArray, width: number, height: number }
}
(self as unknown as Worker).postMessage({
id: requestId,
type: 'qrResult',
data: result.data,
// equivalent to cornerPoints of native BarcodeDetector
+2
View File
@@ -3,6 +3,7 @@ declare class QrScanner {
static readonly DEFAULT_CANVAS_SIZE = 400;
static readonly NO_QR_CODE_FOUND = "No QR code found";
private static _disableBarcodeDetector;
private static _workerMessageId;
/** @deprecated */
static set WORKER_PATH(workerPath: string);
static hasCamera(): Promise<boolean>;
@@ -84,6 +85,7 @@ declare class QrScanner {
private static _loadImage;
private static _awaitImageLoad;
private static _postWorkerMessage;
private static _postWorkerMessageSync;
}
declare namespace QrScanner {
interface ScanRegion {