UNPKG

scandit-sdk

Version:

Scandit Barcode Scanner SDK for the Web

893 lines 46.7 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.GUI = void 0; var tslib_1 = require("tslib"); var resize_observer_1 = require("@juggle/resize-observer"); /** * @hidden */ // tslint:disable-next-line: variable-name no-any var ResizeObserver = (_a = window.ResizeObserver) !== null && _a !== void 0 ? _a : resize_observer_1.ResizeObserver; var base64assets_1 = require("../assets/base64assets"); var browserHelper_1 = require("../browserHelper"); var camera_1 = require("../camera"); var cameraAccess_1 = require("../cameraAccess"); var imageSettings_1 = require("../imageSettings"); var logger_1 = require("../logger"); var singleImageModeSettings_1 = require("../singleImageModeSettings"); var barcodePicker_1 = require("./barcodePicker"); var GUI = /** @class */ (function () { function GUI(options) { var _this = this; // This property was introduced because testing videoElement.offsetParent in Safari // proved to be unreliable. this.isVideoElementDetached = false; this.scanner = options.scanner; this.originElement = options.originElement; this.singleImageModeEnabled = options.singleImageModeEnabled; this.singleImageModeSettings = options.singleImageModeSettings; this.scanningPaused = options.scanningPaused; this.cameraUploadCallback = options.cameraUploadCallback; this.mirrorImageOverrides = new Map(); this.cameraUploadInProgress = false; this.cameraSwitchInProgress = false; this.dataCaptureContextCreated = false; this.grandParentElement = document.createElement("div"); this.grandParentElement.className = GUI.grandParentElementClassName; this.originElement.appendChild(this.grandParentElement); this.parentElement = document.createElement("div"); this.parentElement.className = GUI.parentElementClassName; this.grandParentElement.appendChild(this.parentElement); this.videoElement = document.createElement("video"); this.cameraSwitcherElement = document.createElement("img"); this.torchTogglerElement = document.createElement("img"); this.laserContainerElement = document.createElement("div"); this.laserActiveImageElement = document.createElement("img"); this.laserPausedImageElement = document.createElement("img"); this.cameraRecoveryElement = document.createElement("div"); this.viewfinderElement = document.createElement("div"); var canvas = document.createElement("canvas"); this.webGLContextLostListener = this.handleWebGLContextLost.bind(this); if (options.singleImageModeEnabled) { this.context2d = canvas.getContext("2d"); this.cameraUploadElement = document.createElement("div"); this.cameraUploadLabelElement = document.createElement("label"); this.cameraUploadInputElement = document.createElement("input"); this.cameraUploadProgressElement = document.createElement("div"); this.setupCameraUploadGuiAssets(); this.guiStyle = barcodePicker_1.BarcodePicker.GuiStyle.NONE; } else { this.setupContext(canvas); this.setupVideoElement(); this.setupCameraSwitcher(); this.setupTorchToggler(); this.setupCameraRecovery(options.cameraRecoveryText); this.setupFullGuiAssets(); this.setGuiStyle(options.guiStyle); this.setVideoFit(options.videoFit); this.setLaserArea(options.laserArea); this.setViewfinderArea(options.viewfinderArea); // Ensure the camera is accessed and the video plays again correctly when visibility changes this.visibilityListener = this.checkAndRecoverPlayback.bind(this); document.addEventListener("visibilitychange", this.visibilityListener); this.newScanSettingsListener = this.handleNewScanSettings.bind(this); this.scanner.on("newScanSettings", this.newScanSettingsListener); this.handleNewScanSettings(); this.videoPauseListener = this.handleVideoPause.bind(this); this.videoElement.addEventListener("pause", this.videoPauseListener); this.videoResizeListener = this.handleVideoResize.bind(this); this.videoElement.addEventListener("resize", this.videoResizeListener); } if (options.hideLogo) { this.contextCreatedShowLogoListener = this.showScanditLogo.bind(this, options.hideLogo); this.scanner.on("contextCreated", this.contextCreatedShowLogoListener); } else { this.showScanditLogo(options.hideLogo); } this.contextCreatedActivateGUIListener = this.activateGUI.bind(this); this.scanner.on("contextCreated", this.contextCreatedActivateGUIListener); this.resize(); this.resizeObserver = new ResizeObserver( /* istanbul ignore next */ function () { _this.resize(); }); this.resizeObserver.observe(this.originElement); this.setVisible(options.visible); } GUI.prototype.destroy = function () { var _a, _b, _c, _d; if (this.visibilityListener != null) { document.removeEventListener("visibilitychange", this.visibilityListener); } if (this.newScanSettingsListener != null) { this.scanner.removeListener("newScanSettings", this.newScanSettingsListener); } if (this.videoPauseListener != null) { this.videoElement.removeEventListener("pause", this.videoPauseListener); } if (this.videoResizeListener != null) { this.videoElement.removeEventListener("resize", this.videoResizeListener); } if (this.contextCreatedShowLogoListener != null) { this.scanner.removeListener("contextCreated", this.contextCreatedShowLogoListener); } if (this.contextCreatedActivateGUIListener != null) { this.scanner.removeListener("contextCreated", this.contextCreatedActivateGUIListener); } this.resizeObserver.disconnect(); this.grandParentElement.remove(); this.videoElement.remove(); (_b = (_a = this.contextWebGL) === null || _a === void 0 ? void 0 : _a.canvas) === null || _b === void 0 ? void 0 : _b.removeEventListener("webglcontextlost", this.webGLContextLostListener); (_d = (_c = this.contextWebGL) === null || _c === void 0 ? void 0 : _c.getExtension("WEBGL_lose_context")) === null || _d === void 0 ? void 0 : _d.loseContext(); this.contextWebGL = undefined; this.context2d = undefined; this.originElement.classList.remove(GUI.hiddenClassName); }; GUI.prototype.setCameraManager = function (cameraManager) { this.cameraManager = cameraManager; }; GUI.prototype.pauseScanning = function () { this.scanningPaused = true; this.laserActiveImageElement.classList.add(GUI.hiddenOpacityClassName); this.laserPausedImageElement.classList.remove(GUI.hiddenOpacityClassName); this.viewfinderElement.classList.add(GUI.pausedClassName); }; GUI.prototype.resumeScanning = function () { this.scanningPaused = false; if (this.dataCaptureContextCreated) { this.laserPausedImageElement.classList.add(GUI.hiddenOpacityClassName); this.laserActiveImageElement.classList.remove(GUI.hiddenOpacityClassName); this.viewfinderElement.classList.remove(GUI.pausedClassName); } }; GUI.prototype.isVisible = function () { return this.visible; }; GUI.prototype.setVisible = function (visible) { this.visible = visible; if (visible) { this.originElement.classList.remove(GUI.hiddenClassName); if (this.guiStyle === barcodePicker_1.BarcodePicker.GuiStyle.LASER) { this.laserActiveImageElement.classList.remove(GUI.flashColorClassName); } else if (this.guiStyle === barcodePicker_1.BarcodePicker.GuiStyle.VIEWFINDER) { this.viewfinderElement.classList.remove(GUI.flashWhiteClassName); } } else { this.originElement.classList.add(GUI.hiddenClassName); } }; GUI.prototype.isMirrorImageEnabled = function () { var _a, _b; if (((_a = this.cameraManager) === null || _a === void 0 ? void 0 : _a.selectedCamera) != null && ((_b = this.cameraManager) === null || _b === void 0 ? void 0 : _b.activeCamera) != null) { var mirrorImageOverride = this.mirrorImageOverrides.get(this.cameraManager.activeCamera); return mirrorImageOverride !== null && mirrorImageOverride !== void 0 ? mirrorImageOverride : this.cameraManager.activeCamera.cameraType === camera_1.Camera.Type.FRONT; } else { return false; } }; GUI.prototype.setMirrorImageEnabled = function (enabled, override) { var _a; if (((_a = this.cameraManager) === null || _a === void 0 ? void 0 : _a.selectedCamera) != null) { if (enabled) { this.videoElement.classList.add(GUI.mirroredClassName); } else { this.videoElement.classList.remove(GUI.mirroredClassName); } if (override) { this.mirrorImageOverrides.set(this.cameraManager.selectedCamera, enabled); } } }; GUI.prototype.setGuiStyle = function (guiStyle) { if (this.singleImageModeEnabled) { return; } switch (guiStyle) { case barcodePicker_1.BarcodePicker.GuiStyle.LASER: this.guiStyle = guiStyle; this.laserContainerElement.classList.remove(GUI.hiddenClassName); this.viewfinderElement.classList.add(GUI.hiddenClassName); break; case barcodePicker_1.BarcodePicker.GuiStyle.VIEWFINDER: this.guiStyle = guiStyle; this.laserContainerElement.classList.add(GUI.hiddenClassName); this.viewfinderElement.classList.remove(GUI.hiddenClassName); break; case barcodePicker_1.BarcodePicker.GuiStyle.NONE: default: this.guiStyle = barcodePicker_1.BarcodePicker.GuiStyle.NONE; this.laserContainerElement.classList.add(GUI.hiddenClassName); this.viewfinderElement.classList.add(GUI.hiddenClassName); break; } }; GUI.prototype.setLaserArea = function (area) { this.customLaserArea = area; if (area == null) { area = this.scanner.getScanSettings().getSearchArea(); } var borderPercentage = 0.025; var usablePercentage = 1 - borderPercentage * 2; this.laserContainerElement.style.left = "".concat((borderPercentage + area.x * usablePercentage) * 100, "%"); this.laserContainerElement.style.width = "".concat(area.width * usablePercentage * 100, "%"); this.laserContainerElement.style.top = "".concat((borderPercentage + area.y * usablePercentage) * 100, "%"); this.laserContainerElement.style.height = "".concat(area.height * usablePercentage * 100, "%"); }; GUI.prototype.setViewfinderArea = function (area) { this.customViewfinderArea = area; if (area == null) { area = this.scanner.getScanSettings().getSearchArea(); } var borderPercentage = 0.025; var usablePercentage = 1 - borderPercentage * 2; this.viewfinderElement.style.left = "".concat((borderPercentage + area.x * usablePercentage) * 100, "%"); this.viewfinderElement.style.width = "".concat(area.width * usablePercentage * 100, "%"); this.viewfinderElement.style.top = "".concat((borderPercentage + area.y * usablePercentage) * 100, "%"); this.viewfinderElement.style.height = "".concat(area.height * usablePercentage * 100, "%"); }; GUI.prototype.setVideoFit = function (objectFit) { if (this.singleImageModeEnabled) { return; } this.videoFit = objectFit; if (objectFit === barcodePicker_1.BarcodePicker.ObjectFit.COVER) { this.videoElement.style.objectFit = "cover"; this.videoElement.dataset.objectFit = "cover"; // used by "objectFitPolyfill" library } else { this.videoElement.style.objectFit = "contain"; this.videoElement.dataset.objectFit = "contain"; // used by "objectFitPolyfill" library this.scanner.applyScanSettings(this.scanner.getScanSettings().setBaseSearchArea({ x: 0, y: 0, width: 1.0, height: 1.0 })); } this.resize(); }; GUI.prototype.reassignOriginElement = function (originElement) { if (!this.visible) { this.originElement.classList.remove(GUI.hiddenClassName); originElement.classList.add(GUI.hiddenClassName); } originElement.appendChild(this.grandParentElement); this.checkAndRecoverPlayback().catch( /* istanbul ignore next */ function () { // Ignored }); this.resize(); this.resizeObserver.disconnect(); this.resizeObserver.observe(originElement); this.originElement = originElement; }; GUI.prototype.flashGUI = function () { if (this.guiStyle === barcodePicker_1.BarcodePicker.GuiStyle.LASER) { this.flashLaser(); } else if (this.guiStyle === barcodePicker_1.BarcodePicker.GuiStyle.VIEWFINDER) { this.flashViewfinder(); } }; GUI.prototype.getImageData = function (imageData) { function isVideoAndContextStateValid(videoElement, context) { // This could happen in unexpected situations and should be temporary return (videoElement.readyState === 4 && videoElement.videoWidth > 2 && videoElement.videoHeight > 2 && context.canvas.width > 2 && context.canvas.height > 2); } if (this.singleImageModeEnabled && this.context2d != null) { return new Uint8Array(this.context2d.getImageData(0, 0, this.context2d.canvas.width, this.context2d.canvas.height).data.buffer); } // istanbul ignore else if (!this.singleImageModeEnabled) { if (this.contextWebGL != null) { if (!isVideoAndContextStateValid(this.videoElement, this.contextWebGL) || this.contextWebGL.drawingBufferWidth <= 2 || this.contextWebGL.drawingBufferHeight <= 2) { return; } var imageDataLength = this.contextWebGL.drawingBufferWidth * this.contextWebGL.drawingBufferHeight * 4; if (imageData == null || imageData.byteLength === 0 || imageData.byteLength !== imageDataLength) { imageData = new Uint8Array(imageDataLength); } this.contextWebGL.texImage2D(this.contextWebGL.TEXTURE_2D, 0, this.contextWebGL.RGBA, this.contextWebGL.RGBA, this.contextWebGL.UNSIGNED_BYTE, this.videoElement); this.contextWebGL.readPixels(0, 0, this.contextWebGL.drawingBufferWidth, this.contextWebGL.drawingBufferHeight, this.contextWebGL.RGBA, this.contextWebGL.UNSIGNED_BYTE, imageData); // Detect incorrect GPU accelerated WebGL image processing by checking for incorrect alpha channel data if (imageData[3] !== 255) { logger_1.Logger.log(logger_1.Logger.Level.WARN, "Detected incorrect GPU accelerated WebGL image processing, switching to canvas mode"); this.contextWebGL = undefined; this.setupContext(document.createElement("canvas"), true); this.handleVideoResize(); return this.getImageData(imageData); } return imageData; } // istanbul ignore else if (this.context2d != null) { if (!isVideoAndContextStateValid(this.videoElement, this.context2d)) { return; } this.context2d.drawImage(this.videoElement, 0, 0); return new Uint8Array(this.context2d.getImageData(0, 0, this.context2d.canvas.width, this.context2d.canvas.height).data.buffer); } } // istanbul ignore next return; }; GUI.prototype.getVideoCurrentTime = function () { return this.videoElement.currentTime; }; GUI.prototype.setCameraSwitcherVisible = function (visible) { if (visible) { this.cameraSwitcherElement.classList.remove(GUI.hiddenClassName); } else { this.cameraSwitcherElement.classList.add(GUI.hiddenClassName); } }; GUI.prototype.isCameraRecoveryVisible = function () { return !this.cameraRecoveryElement.classList.contains(GUI.hiddenClassName); }; GUI.prototype.setCameraRecoveryVisible = function (visible) { if (visible) { this.cameraRecoveryElement.classList.remove(GUI.hiddenClassName); } else { this.cameraRecoveryElement.classList.add(GUI.hiddenClassName); } }; GUI.prototype.setTorchTogglerVisible = function (visible) { if (visible) { this.torchTogglerElement.classList.remove(GUI.hiddenClassName); } else { this.torchTogglerElement.classList.add(GUI.hiddenClassName); } }; GUI.prototype.playVideo = function () { var playPromise = this.videoElement.play(); playPromise === null || playPromise === void 0 ? void 0 : playPromise.catch( /* istanbul ignore next */ function () { // Can sometimes cause an incorrect rejection (all is good, ignore). }); }; GUI.prototype.setVideoVisible = function (visible) { this.videoElement.style.visibility = visible ? "visible" : "hidden"; }; GUI.prototype.setCameraType = function (cameraType) { var _a; (_a = this.cameraUploadInputElement) === null || _a === void 0 ? void 0 : _a.setAttribute("capture", cameraType === camera_1.Camera.Type.FRONT ? "user" : "environment"); }; GUI.prototype.setCameraUploadGuiBusyScanning = function (busyScanning) { if (busyScanning) { this.cameraUploadProgressElement.classList.remove(GUI.flashInsetClassName); this.cameraUploadElement.classList.add(GUI.opacityPulseClassName); } else { this.cameraUploadProgressElement.classList.add(GUI.flashInsetClassName); this.cameraUploadElement.classList.remove(GUI.opacityPulseClassName); } }; GUI.prototype.setupContext = function (canvas, force2d) { if (force2d === void 0) { force2d = false; } if (force2d) { this.context2d = canvas.getContext("2d"); return; } var context = canvas.getContext("webgl", { alpha: false, antialias: false }); // istanbul ignore if if (context == null) { context = canvas.getContext("experimental-webgl", { alpha: false, antialias: false }); } if (context != null) { this.setupWebGL(context); canvas.addEventListener("webglcontextlost", this.webGLContextLostListener); } else { this.context2d = canvas.getContext("2d"); } }; GUI.prototype.setupWebGL = function (contextWebGL) { var texture = contextWebGL.createTexture(); contextWebGL.bindTexture(contextWebGL.TEXTURE_2D, texture); var frameBuffer = contextWebGL.createFramebuffer(); contextWebGL.bindFramebuffer(contextWebGL.FRAMEBUFFER, frameBuffer); contextWebGL.framebufferTexture2D(contextWebGL.FRAMEBUFFER, contextWebGL.COLOR_ATTACHMENT0, contextWebGL.TEXTURE_2D, texture, 0); contextWebGL.texParameteri(contextWebGL.TEXTURE_2D, contextWebGL.TEXTURE_WRAP_S, contextWebGL.CLAMP_TO_EDGE); contextWebGL.texParameteri(contextWebGL.TEXTURE_2D, contextWebGL.TEXTURE_WRAP_T, contextWebGL.CLAMP_TO_EDGE); contextWebGL.texParameteri(contextWebGL.TEXTURE_2D, contextWebGL.TEXTURE_MIN_FILTER, contextWebGL.NEAREST); contextWebGL.texParameteri(contextWebGL.TEXTURE_2D, contextWebGL.TEXTURE_MAG_FILTER, contextWebGL.NEAREST); this.contextWebGL = contextWebGL; }; GUI.prototype.setupVideoElement = function () { this.videoElement.setAttribute("autoplay", "autoplay"); this.videoElement.setAttribute("playsinline", "true"); this.videoElement.setAttribute("muted", "muted"); this.videoElement.className = GUI.videoElementClassName; this.parentElement.appendChild(this.videoElement); }; GUI.prototype.setupCameraUploadGuiAssets = function () { var _this = this; var _a, _b; var deviceType = browserHelper_1.BrowserHelper.userAgentInfo.getDevice().type; var defaultSettings = deviceType === "mobile" || deviceType === "tablet" ? singleImageModeSettings_1.SingleImageModeSettings.defaultMobile : singleImageModeSettings_1.SingleImageModeSettings.defaultDesktop; this.cameraUploadElement.className = GUI.cameraUploadElementClassName; Object.assign(this.cameraUploadElement.style, defaultSettings.containerStyle, this.singleImageModeSettings.containerStyle); this.parentElement.appendChild(this.cameraUploadElement); var informationElement = (_a = this.singleImageModeSettings.informationElement) !== null && _a !== void 0 ? _a : defaultSettings.informationElement; Object.assign(informationElement.style, defaultSettings.informationStyle, this.singleImageModeSettings.informationStyle); this.cameraUploadElement.appendChild(informationElement); this.cameraUploadInputElement.type = "file"; this.cameraUploadInputElement.accept = "image/*"; this.cameraUploadInputElement.addEventListener("change", this.cameraUploadFile.bind(this)); var cameraUploadInputCheckFunction = function (event) { // istanbul ignore next if (_this.scanningPaused || _this.cameraUploadInProgress) { event.preventDefault(); } }; this.cameraUploadInputElement.addEventListener("click", cameraUploadInputCheckFunction); this.cameraUploadInputElement.addEventListener("keydown", cameraUploadInputCheckFunction); this.cameraUploadLabelElement.appendChild(this.cameraUploadInputElement); var cameraUploadButtonIconElement = (_b = this.singleImageModeSettings.buttonElement) !== null && _b !== void 0 ? _b : defaultSettings.buttonElement; [this.cameraUploadProgressElement.style, cameraUploadButtonIconElement.style].forEach(function (style) { Object.assign(style, defaultSettings.buttonStyle, _this.singleImageModeSettings.buttonStyle); }); cameraUploadButtonIconElement.style.maxWidth = "100px"; cameraUploadButtonIconElement.style.maxHeight = "100px"; this.cameraUploadLabelElement.appendChild(cameraUploadButtonIconElement); this.cameraUploadProgressElement.classList.add("radial-progress"); this.cameraUploadLabelElement.appendChild(this.cameraUploadProgressElement); this.cameraUploadElement.appendChild(this.cameraUploadLabelElement); }; GUI.prototype.setupFullGuiAssets = function () { this.laserActiveImageElement.src = base64assets_1.laserActiveImage; this.laserContainerElement.appendChild(this.laserActiveImageElement); this.laserPausedImageElement.src = base64assets_1.laserPausedImage; this.laserContainerElement.appendChild(this.laserPausedImageElement); this.laserContainerElement.className = GUI.laserContainerElementClassName; this.parentElement.appendChild(this.laserContainerElement); this.viewfinderElement.className = GUI.viewfinderElementClassName; this.parentElement.appendChild(this.viewfinderElement); // Show inactive GUI, as for now the scanner isn't ready yet this.laserActiveImageElement.classList.add(GUI.hiddenOpacityClassName); this.laserPausedImageElement.classList.remove(GUI.hiddenOpacityClassName); this.viewfinderElement.classList.add(GUI.pausedClassName); }; GUI.prototype.flashLaser = function () { this.laserActiveImageElement.classList.remove(GUI.flashColorClassName); // tslint:disable-next-line:no-unused-expression this.laserActiveImageElement.offsetHeight; // NOSONAR // Trigger reflow to restart animation this.laserActiveImageElement.classList.add(GUI.flashColorClassName); }; GUI.prototype.flashViewfinder = function () { this.viewfinderElement.classList.remove(GUI.flashWhiteClassName); // tslint:disable-next-line:no-unused-expression this.viewfinderElement.offsetHeight; // NOSONAR // Trigger reflow to restart animation this.viewfinderElement.classList.add(GUI.flashWhiteClassName); }; GUI.prototype.resize = function () { this.parentElement.style.maxWidth = ""; this.parentElement.style.maxHeight = ""; var width = this.originElement.clientWidth; var height = this.originElement.clientHeight; if (width === 0 || height === 0) { if (!this.singleImageModeEnabled) { this.handleVideoDisplay(true); } return; } if (this.singleImageModeEnabled) { this.resizeCameraUpload(width, height); } else { this.resizeVideo(width, height); this.handleVideoDisplay(false); } }; GUI.prototype.resizeCameraUpload = function (width, height) { this.cameraUploadLabelElement.style.transform = "scale(".concat(Math.min(1, width / 300, height / 300), ")"); }; GUI.prototype.resizeVideo = function (width, height) { if (this.videoElement.videoWidth <= 2 || this.videoElement.videoHeight <= 2) { return; } var videoRatio = this.videoElement.videoWidth / this.videoElement.videoHeight; if (this.videoFit === barcodePicker_1.BarcodePicker.ObjectFit.COVER) { var widthPercentage = 1; var heightPercentage = 1; if (videoRatio < width / height) { heightPercentage = Math.min(1, height / (width / videoRatio)); } else { widthPercentage = Math.min(1, width / (height * videoRatio)); } this.scanner.applyScanSettings(this.scanner.getScanSettings().setBaseSearchArea({ x: (1 - widthPercentage) / 2, y: (1 - heightPercentage) / 2, width: widthPercentage, height: heightPercentage, })); return; } if (videoRatio > width / height) { height = width / videoRatio; } else { width = height * videoRatio; } this.parentElement.style.maxWidth = "".concat(Math.ceil(width), "px"); this.parentElement.style.maxHeight = "".concat(Math.ceil(height), "px"); window.objectFitPolyfill(this.videoElement); }; GUI.prototype.checkAndRecoverPlayback = function () { var _a, _b, _c; return tslib_1.__awaiter(this, void 0, void 0, function () { var srcObject, _d; return tslib_1.__generator(this, function (_e) { switch (_e.label) { case 0: srcObject = this.videoElement.srcObject; if (!(document.visibilityState === "visible" && ((_a = this.cameraManager) === null || _a === void 0 ? void 0 : _a.activeCamera) != null && ((_b = this.videoElement) === null || _b === void 0 ? void 0 : _b.srcObject) != null)) return [3 /*break*/, 6]; if (!(!srcObject.active || ((_c = srcObject.getVideoTracks()[0]) === null || _c === void 0 ? void 0 : _c.muted) !== false)) return [3 /*break*/, 5]; _e.label = 1; case 1: _e.trys.push([1, 3, , 4]); logger_1.Logger.log(logger_1.Logger.Level.DEBUG, 'Detected visibility change ("visible") event with inactive video source, try to reinitialize camera'); return [4 /*yield*/, this.cameraManager.reinitializeCamera()]; case 2: _e.sent(); return [3 /*break*/, 4]; case 3: _d = _e.sent(); return [3 /*break*/, 4]; case 4: return [3 /*break*/, 6]; case 5: logger_1.Logger.log(logger_1.Logger.Level.DEBUG, 'Detected visibility change ("visible") event with active video source, replay video'); this.playVideo(); _e.label = 6; case 6: return [2 /*return*/]; } }); }); }; GUI.prototype.updateCameraUploadProgress = function (progressPercentageValue) { this.cameraUploadProgressElement.setAttribute("data-progress", progressPercentageValue); }; GUI.prototype.cameraUploadImageLoad = function (image) { return tslib_1.__awaiter(this, void 0, void 0, function () { var resizedImageWidth, resizedImageHeight, resizedImageSizeLimit; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: this.updateCameraUploadProgress("100"); resizedImageSizeLimit = 1440; if (image.naturalWidth <= resizedImageSizeLimit && image.naturalHeight <= resizedImageSizeLimit) { resizedImageWidth = image.naturalWidth; resizedImageHeight = image.naturalHeight; } else { if (image.naturalWidth > image.naturalHeight) { resizedImageWidth = resizedImageSizeLimit; resizedImageHeight = Math.round((image.naturalHeight / image.naturalWidth) * resizedImageSizeLimit); } else { resizedImageWidth = Math.round((image.naturalWidth / image.naturalHeight) * resizedImageSizeLimit); resizedImageHeight = resizedImageSizeLimit; } } return [4 /*yield*/, this.cameraUploadFileProcess(image, resizedImageWidth, resizedImageHeight)]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; GUI.prototype.cameraUploadFileProcess = function (image, width, height) { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: // istanbul ignore else if (this.context2d != null) { this.context2d.canvas.width = width; this.context2d.canvas.height = height; this.context2d.drawImage(image, 0, 0, width, height); this.scanner.applyImageSettings({ width: width, height: height, format: imageSettings_1.ImageSettings.Format.RGBA_8U, }); } this.setCameraUploadGuiBusyScanning(true); return [4 /*yield*/, this.cameraUploadCallback()]; case 1: _a.sent(); this.setCameraUploadGuiBusyScanning(false); this.cameraUploadInProgress = false; return [2 /*return*/]; } }); }); }; GUI.prototype.cameraUploadFile = function () { var _this = this; var files = this.cameraUploadInputElement.files; if (files != null && files.length !== 0) { this.cameraUploadInProgress = true; var image_1 = new Image(); var fileReader_1 = new FileReader(); fileReader_1.onload = function () { _this.cameraUploadInputElement.value = ""; // istanbul ignore else if (fileReader_1.result != null) { image_1.onload = _this.cameraUploadImageLoad.bind(_this, image_1); // istanbul ignore next image_1.onprogress = function (event2) { if (event2.lengthComputable) { var progress = Math.round((event2.loaded / event2.total) * 20) * 5; if (progress <= 100) { _this.updateCameraUploadProgress(progress.toString()); } } }; // istanbul ignore next image_1.onerror = function () { _this.cameraUploadInProgress = false; logger_1.Logger.log(logger_1.Logger.Level.WARN, "Could not load image from selected file"); }; image_1.src = fileReader_1.result; } }; // istanbul ignore next fileReader_1.onerror = function () { var _a; _this.cameraUploadInProgress = false; logger_1.Logger.log(logger_1.Logger.Level.WARN, "Error while reading the file: ".concat((_a = fileReader_1.error) === null || _a === void 0 ? void 0 : _a.toString())); }; this.updateCameraUploadProgress("0"); fileReader_1.readAsDataURL(files[0]); } }; GUI.prototype.cameraSwitcherListener = function (event) { return tslib_1.__awaiter(this, void 0, void 0, function () { var cameraManager, cameras, currentCameraIndex, newCameraIndex, error_1, error_2; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!(!this.cameraSwitchInProgress && this.cameraManager != null)) return [3 /*break*/, 12]; cameraManager = this.cameraManager; event.preventDefault(); _a.label = 1; case 1: _a.trys.push([1, 11, , 12]); return [4 /*yield*/, cameraAccess_1.CameraAccess.getCameras()]; case 2: cameras = _a.sent(); if (cameraManager.activeCamera == null) { return [2 /*return*/]; } if (cameras.length <= 1) { this.setCameraSwitcherVisible(false); return [2 /*return*/]; } this.cameraSwitchInProgress = true; currentCameraIndex = cameras.indexOf(cameraManager.activeCamera); newCameraIndex = (currentCameraIndex + 1) % cameras.length; _a.label = 3; case 3: if (!(newCameraIndex !== currentCameraIndex)) return [3 /*break*/, 10]; _a.label = 4; case 4: _a.trys.push([4, 6, , 9]); return [4 /*yield*/, cameraManager.initializeCameraWithSettings(cameras[newCameraIndex], cameraManager.activeCameraSettings)]; case 5: _a.sent(); return [3 /*break*/, 9]; case 6: error_1 = _a.sent(); logger_1.Logger.log(logger_1.Logger.Level.WARN, "Couldn't access camera:", cameras[newCameraIndex], error_1); newCameraIndex = (newCameraIndex + 1) % cameras.length; if (!(newCameraIndex === currentCameraIndex)) return [3 /*break*/, 8]; this.setCameraSwitcherVisible(false); return [4 /*yield*/, cameraManager.initializeCameraWithSettings(cameras[newCameraIndex], cameraManager.activeCameraSettings)]; case 7: _a.sent(); _a.label = 8; case 8: return [3 /*break*/, 3]; case 9: return [3 /*break*/, 10]; case 10: this.cameraSwitchInProgress = false; return [3 /*break*/, 12]; case 11: error_2 = _a.sent(); logger_1.Logger.log(logger_1.Logger.Level.ERROR, error_2); this.cameraSwitchInProgress = false; return [3 /*break*/, 12]; case 12: return [2 /*return*/]; } }); }); }; GUI.prototype.cameraRecoveryListener = function (event) { var _a; return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: event.preventDefault(); if (!(this.cameraManager != null)) return [3 /*break*/, 2]; this.cameraManager.activeCamera = this.cameraManager.selectedCamera; return [4 /*yield*/, ((_a = this.cameraManager) === null || _a === void 0 ? void 0 : _a.reinitializeCamera())]; case 1: _b.sent(); _b.label = 2; case 2: return [2 /*return*/]; } }); }); }; GUI.prototype.setupCameraSwitcher = function () { var _this = this; this.cameraSwitcherElement.src = base64assets_1.switchCameraImage; this.cameraSwitcherElement.className = GUI.cameraSwitcherElementClassName; this.cameraSwitcherElement.classList.add(GUI.hiddenClassName); this.parentElement.appendChild(this.cameraSwitcherElement); ["touchstart", "mousedown"].forEach(function (eventName) { _this.cameraSwitcherElement.addEventListener(eventName, _this.cameraSwitcherListener.bind(_this)); }); }; GUI.prototype.setupCameraRecovery = function (cameraRecoveryText) { var _this = this; this.cameraRecoveryElement.textContent = cameraRecoveryText; this.cameraRecoveryElement.className = GUI.cameraRecoveryElementClassName; this.cameraRecoveryElement.classList.add(GUI.hiddenClassName); this.parentElement.appendChild(this.cameraRecoveryElement); ["touchstart", "mousedown"].forEach(function (eventName) { _this.cameraRecoveryElement.addEventListener(eventName, _this.cameraRecoveryListener.bind(_this)); }); }; GUI.prototype.setupTorchToggler = function () { var _this = this; this.torchTogglerElement.src = base64assets_1.toggleTorchImage; this.torchTogglerElement.className = GUI.torchTogglerElementClassName; this.torchTogglerElement.classList.add(GUI.hiddenClassName); this.parentElement.appendChild(this.torchTogglerElement); ["touchstart", "mousedown"].forEach(function (eventName) { _this.torchTogglerElement.addEventListener(eventName, function (event) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!(this.cameraManager != null)) return [3 /*break*/, 2]; event.preventDefault(); return [4 /*yield*/, this.cameraManager.toggleTorch()]; case 1: _a.sent(); _a.label = 2; case 2: return [2 /*return*/]; } }); }); }); }); }; GUI.prototype.showScanditLogo = function (hideLogo, licenseKeyFeatures) { if (hideLogo && (licenseKeyFeatures === null || licenseKeyFeatures === void 0 ? void 0 : licenseKeyFeatures.hiddenScanditLogoAllowed) === true) { return; } var scanditLogoImageElement = document.createElement("img"); scanditLogoImageElement.src = base64assets_1.scanditLogoImage; scanditLogoImageElement.className = GUI.scanditLogoImageElementClassName; this.parentElement.appendChild(scanditLogoImageElement); }; GUI.prototype.activateGUI = function () { this.dataCaptureContextCreated = true; if (!this.scanningPaused) { this.resumeScanning(); } }; GUI.prototype.handleNewScanSettings = function () { if (this.customLaserArea == null) { this.setLaserArea(); } if (this.customViewfinderArea == null) { this.setViewfinderArea(); } }; GUI.prototype.handleVideoDisplay = function (hidden) { // Safari on iOS 14 behaves weirdly when hiding the video element: // it stops camera access after a few seconds if the related video element is not "visible". // We do the following to maintain the video element "visible" but actually hidden. if (hidden && !this.isVideoElementDetached) { this.videoElement.width = this.videoElement.height = 0; this.videoElement.style.opacity = "0"; document.body.appendChild(this.videoElement); this.isVideoElementDetached = true; } else if (!hidden && this.isVideoElementDetached) { this.parentElement.insertAdjacentElement("afterbegin", this.videoElement); this.isVideoElementDetached = false; this.videoElement.removeAttribute("width"); this.videoElement.removeAttribute("height"); this.videoElement.style.removeProperty("opacity"); this.resize(); } }; GUI.prototype.handleVideoPause = function () { // Safari behaves weirdly when displaying the video element again after hiding it: // it pauses the video on hide and resumes it on show, then reusing video frames "buffered" from the video just // before it was hidden. We do the following to avoid processing old data. this.playVideo(); }; GUI.prototype.handleVideoResize = function () { this.resize(); if (this.videoElement.videoWidth <= 2 || this.videoElement.videoHeight <= 2) { return; } if (this.contextWebGL != null) { if (this.contextWebGL.canvas.width === this.videoElement.videoWidth && this.contextWebGL.canvas.height === this.videoElement.videoHeight) { return; } this.contextWebGL.canvas.width = this.videoElement.videoWidth; this.contextWebGL.canvas.height = this.videoElement.videoHeight; this.contextWebGL.viewport(0, 0, this.contextWebGL.drawingBufferWidth, this.contextWebGL.drawingBufferHeight); this.scanner.applyImageSettings({ width: this.contextWebGL.drawingBufferWidth, height: this.contextWebGL.drawingBufferHeight, format: imageSettings_1.ImageSettings.Format.RGBA_8U, }); } else if (this.context2d != null) { if (this.context2d.canvas.width === this.videoElement.videoWidth && this.context2d.canvas.height === this.videoElement.videoHeight) { return; } this.context2d.canvas.width = this.videoElement.videoWidth; this.context2d.canvas.height = this.videoElement.videoHeight; this.scanner.applyImageSettings({ width: this.videoElement.videoWidth, height: this.videoElement.videoHeight, format: imageSettings_1.ImageSettings.Format.RGBA_8U, }); } }; GUI.prototype.handleWebGLContextLost = function () { // We recreate instead of waiting for restore via the webglcontextrestored event as restore might never happen logger_1.Logger.log(logger_1.Logger.Level.WARN, "WebGL context has been lost, restoring..."); this.contextWebGL = undefined; this.setupContext(document.createElement("canvas")); this.handleVideoResize(); logger_1.Logger.log(logger_1.Logger.Level.WARN, "WebGL context restored"); }; GUI.grandParentElementClassName = "scandit scandit-container"; GUI.parentElementClassName = "scandit scandit-barcode-picker"; GUI.hiddenClassName = "scandit-hidden"; GUI.hiddenOpacityClassName = "scandit-hidden-opacity"; GUI.videoElementClassName = "scandit-video"; GUI.scanditLogoImageElementClassName = "scandit-logo"; GUI.laserContainerElementClassName = "scandit-laser"; GUI.viewfinderElementClassName = "scandit-viewfinder"; GUI.cameraSwitcherElementClassName = "scandit-camera-switcher"; GUI.cameraRecoveryElementClassName = "scandit-camera-recovery"; GUI.torchTogglerElementClassName = "scandit-torch-toggle"; GUI.cameraUploadElementClassName = "scandit-camera-upload"; GUI.flashColorClassName = "scandit-flash-color"; GUI.flashWhiteClassName = "scandit-flash-white"; GUI.flashInsetClassName = "scandit-flash-inset"; GUI.opacityPulseClassName = "scandit-opacity-pulse"; GUI.mirroredClassName = "mirrored"; GUI.pausedClassName = "paused"; return GUI; }()); exports.GUI = GUI; //# sourceMappingURL=gui.js.map