// Vendored from qrcode-decoder on npm (was giving me Webpack issues) import { Options } from 'jsqr'; import jsQR from 'jsqr'; const videoSize = { width: { min: 360, ideal: 720, max: 1080 }, height: { min: 360, ideal: 720, max: 1080 }, }; class QrcodeDecoder { timerCapture: null | NodeJS.Timeout; canvasElem: null | HTMLCanvasElement; gCtx: null | CanvasRenderingContext2D; stream: null | MediaStream; videoElem: null | HTMLVideoElement; getUserMediaHandler: null; videoConstraints: MediaStreamConstraints; defaultOption: Options; constructor() { this.timerCapture = null; this.canvasElem = null; this.gCtx = null; this.stream = null; this.videoElem = null; this.getUserMediaHandler = null; this.videoConstraints = { // default use rear camera video: { ...videoSize, facingMode: { exact: 'environment' } }, audio: false, }; this.defaultOption = { inversionAttempts: 'attemptBoth' }; } /** * Verifies if canvas element is supported. */ isCanvasSupported() { const elem = document.createElement('canvas'); return !!(elem.getContext && elem.getContext('2d')); } _createImageData(target: CanvasImageSource, width: number, height: number) { if (!this.canvasElem) { this._prepareCanvas(width, height); } this.gCtx!.clearRect(0, 0, width, height); this.gCtx!.drawImage(target, 0, 0, width, height); const imageData = this.gCtx!.getImageData( 0, 0, this.canvasElem!.width, this.canvasElem!.height, ); return imageData; } /** * Prepares the canvas element (which will * receive the image from the camera and provide * what the algorithm needs for checking for a * QRCode and then decoding it.) * * * @param {DOMElement} canvasElem the canvas * element * @param {number} width The width that * the canvas element * should have * @param {number} height The height that * the canvas element * should have * @return {DOMElement} the canvas * after the resize if width and height * provided. */ _prepareCanvas(width: number, height: number) { if (!this.canvasElem) { this.canvasElem = document.createElement('canvas'); this.canvasElem.style.width = `${width}px`; this.canvasElem.style.height = `${height}px`; this.canvasElem.width = width; this.canvasElem.height = height; } this.gCtx = this.canvasElem.getContext('2d'); } /** * Based on the video dimensions and the canvas * that was previously generated captures the * video/image source and then paints into the * canvas so that the decoder is able to work as * it expects. * @param {DOMElement} videoElem