UNPKG

angular-weblineindia-qrcode-scanner

Version:
668 lines 67.6 kB
import * as tslib_1 from "tslib"; import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild, } from '@angular/core'; import { ArgumentException, BarcodeFormat, DecodeHintType } from '@zxing/library'; import { BrowserMultiFormatContinuousReader } from './browser-multi-format-continuous-reader'; var ZXingScannerComponent = /** @class */ (function () { /** * Constructor to build the object and do some DI. */ function ZXingScannerComponent() { /** * How the preview element shoud be fit inside the :host container. */ this.previewFitMode = 'cover'; // instance based emitters this.autostarted = new EventEmitter(); this.autostarting = new EventEmitter(); this.torchCompatible = new EventEmitter(); this.scanSuccess = new EventEmitter(); this.scanFailure = new EventEmitter(); this.scanError = new EventEmitter(); this.scanComplete = new EventEmitter(); this.camerasFound = new EventEmitter(); this.camerasNotFound = new EventEmitter(); this.permissionResponse = new EventEmitter(true); this.hasDevices = new EventEmitter(); this.deviceChange = new EventEmitter(); this._device = null; this._enabled = true; this._hints = new Map(); this.autofocusEnabled = true; this.autostart = true; this.formats = [BarcodeFormat.QR_CODE]; // computed data this.hasNavigator = typeof navigator !== 'undefined'; this.isMediaDevicesSuported = this.hasNavigator && !!navigator.mediaDevices; } Object.defineProperty(ZXingScannerComponent.prototype, "codeReader", { /** * Exposes the current code reader, so the user can use it's APIs. */ get: function () { return this._codeReader; }, enumerable: true, configurable: true }); Object.defineProperty(ZXingScannerComponent.prototype, "device", { /** * User device acessor. */ get: function () { return this._device; }, /** * User device input */ set: function (device) { if (!device && device !== null) { throw new ArgumentException('The `device` must be a valid MediaDeviceInfo or null.'); } if (this.isCurrentDevice(device)) { console.warn('Setting the same device is not allowed.'); return; } if (this.isAutostarting) { // do not allow setting devices during auto-start, since it will set one and emit it. console.warn('Avoid setting a device during auto-start.'); return; } if (!this.hasPermission) { console.warn('Permissions not set yet, waiting for them to be set to apply device change.'); // this.permissionResponse // .pipe( // take(1), // tap(() => console.log(`Permissions set, applying device change${device ? ` (${device.deviceId})` : ''}.`)) // ) // .subscribe(() => this.device = device); // return; } // in order to change the device the codeReader gotta be reseted this._reset(); this._device = device; // if enabled, starts scanning if (this._enabled && device !== null) { this.scanFromDevice(device.deviceId); } }, enumerable: true, configurable: true }); Object.defineProperty(ZXingScannerComponent.prototype, "formats", { /** * Returns all the registered formats. */ get: function () { return this.hints.get(DecodeHintType.POSSIBLE_FORMATS); }, /** * Registers formats the scanner should support. * * @param input BarcodeFormat or case-insensitive string array. */ set: function (input) { var _this = this; if (typeof input === 'string') { throw new Error('Invalid formats, make sure the [formats] input is a binding.'); } // formats may be set from html template as BarcodeFormat or string array var formats = input.map(function (f) { return _this.getBarcodeFormatOrFail(f); }); var hints = this.hints; // updates the hints hints.set(DecodeHintType.POSSIBLE_FORMATS, formats); this.hints = hints; }, enumerable: true, configurable: true }); Object.defineProperty(ZXingScannerComponent.prototype, "hints", { /** * Returns all the registered hints. */ get: function () { return this._hints; }, /** * Does what it takes to set the hints. */ set: function (hints) { this._hints = hints; // @note avoid restarting the code reader when possible // new instance with new hints. this.restart(); }, enumerable: true, configurable: true }); Object.defineProperty(ZXingScannerComponent.prototype, "isAutostarting", { /** * */ set: function (state) { this._isAutostarting = state; this.autostarting.next(state); }, enumerable: true, configurable: true }); Object.defineProperty(ZXingScannerComponent.prototype, "isAutstarting", { /** * */ get: function () { return this._isAutostarting; }, enumerable: true, configurable: true }); Object.defineProperty(ZXingScannerComponent.prototype, "torch", { /** * Allow start scan or not. */ set: function (on) { this.getCodeReader().setTorch(on); }, enumerable: true, configurable: true }); Object.defineProperty(ZXingScannerComponent.prototype, "enable", { /** * Allow start scan or not. */ set: function (enabled) { this._enabled = Boolean(enabled); if (!this._enabled) { this.reset(); } else if (this.device) { this.scanFromDevice(this.device.deviceId); } }, enumerable: true, configurable: true }); Object.defineProperty(ZXingScannerComponent.prototype, "enabled", { /** * Tells if the scanner is enabled or not. */ get: function () { return this._enabled; }, enumerable: true, configurable: true }); Object.defineProperty(ZXingScannerComponent.prototype, "tryHarder", { /** * If is `tryHarder` enabled. */ get: function () { return this.hints.get(DecodeHintType.TRY_HARDER); }, /** * Enable/disable tryHarder hint. */ set: function (enable) { var hints = this.hints; if (enable) { hints.set(DecodeHintType.TRY_HARDER, true); } else { hints.delete(DecodeHintType.TRY_HARDER); } this.hints = hints; }, enumerable: true, configurable: true }); /** * Gets and registers all cammeras. */ ZXingScannerComponent.prototype.askForPermission = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var stream, permission, err_1; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!this.hasNavigator) { console.error('@zxing/ngx-scanner', 'Can\'t ask permission, navigator is not present.'); this.setPermission(null); return [2 /*return*/, this.hasPermission]; } if (!this.isMediaDevicesSuported) { console.error('@zxing/ngx-scanner', 'Can\'t get user media, this is not supported.'); this.setPermission(null); return [2 /*return*/, this.hasPermission]; } _a.label = 1; case 1: _a.trys.push([1, 3, 4, 5]); return [4 /*yield*/, this.getAnyVideoDevice()]; case 2: // Will try to ask for permission stream = _a.sent(); permission = !!stream; return [3 /*break*/, 5]; case 3: err_1 = _a.sent(); return [2 /*return*/, this.handlePermissionException(err_1)]; case 4: this.terminateStream(stream); return [7 /*endfinally*/]; case 5: this.setPermission(permission); // Returns the permission return [2 /*return*/, permission]; } }); }); }; /** * */ ZXingScannerComponent.prototype.getAnyVideoDevice = function () { return navigator.mediaDevices.getUserMedia({ video: true }); }; /** * Terminates a stream and it's tracks. */ ZXingScannerComponent.prototype.terminateStream = function (stream) { if (stream) { stream.getTracks().forEach(function (t) { return t.stop(); }); } stream = undefined; }; /** * Initializes the component without starting the scanner. */ ZXingScannerComponent.prototype.initAutostartOff = function () { // do not ask for permission when autostart is off this.isAutostarting = null; // just update devices information this.updateVideoInputDevices(); }; /** * Initializes the component and starts the scanner. * Permissions are asked to accomplish that. */ ZXingScannerComponent.prototype.initAutostartOn = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var hasPermission, e_1, devices; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: this.isAutostarting = true; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.askForPermission()]; case 2: // Asks for permission before enumerating devices so it can get all the device's info hasPermission = _a.sent(); return [3 /*break*/, 4]; case 3: e_1 = _a.sent(); console.error('Exception occurred while asking for permission:', e_1); return [2 /*return*/]; case 4: if (!hasPermission) return [3 /*break*/, 6]; return [4 /*yield*/, this.updateVideoInputDevices()]; case 5: devices = _a.sent(); this.autostartScanner(tslib_1.__spread(devices)); _a.label = 6; case 6: return [2 /*return*/]; } }); }); }; /** * Checks if the given device is the current defined one. */ ZXingScannerComponent.prototype.isCurrentDevice = function (device) { return this.device && device && device.deviceId === this.device.deviceId; }; /** * Executed after the view initialization. */ ZXingScannerComponent.prototype.ngAfterViewInit = function () { var _this = this; // makes torch availability information available to user this.getCodeReader().isTorchAvailable.subscribe(function (x) { return _this.torchCompatible.emit(x); }); if (!this.autostart) { console.warn('New feature \'autostart\' disabled, be careful. Permissions and devices recovery has to be run manually.'); // does the necessary configuration without autostarting this.initAutostartOff(); return; } // configurates the component and starts the scanner this.initAutostartOn(); }; /** * Executes some actions before destroy the component. */ ZXingScannerComponent.prototype.ngOnDestroy = function () { this.reset(); }; /** * Stops old `codeReader` and starts scanning in a new one. */ ZXingScannerComponent.prototype.restart = function () { var prevDevice = this._reset(); if (!prevDevice) { return; } // @note apenas necessario por enquanto causa da Torch this._codeReader = undefined; this.device = prevDevice; }; /** * Discovers and updates known video input devices. */ ZXingScannerComponent.prototype.updateVideoInputDevices = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var devices, hasDevices; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.getCodeReader().listVideoInputDevices()]; case 1: devices = (_a.sent()) || []; hasDevices = devices && devices.length > 0; // stores discovered devices and updates information this.hasDevices.next(hasDevices); this.camerasFound.next(tslib_1.__spread(devices)); if (!hasDevices) { this.camerasNotFound.next(); } return [2 /*return*/, devices]; } }); }); }; /** * Starts the scanner with the back camera otherwise take the last * available device. */ ZXingScannerComponent.prototype.autostartScanner = function (devices) { var matcher = function (_a) { var label = _a.label; return /back|trás|rear|traseira|environment|ambiente/gi.test(label); }; // select the rear camera by default, otherwise take the last camera. var device = devices.find(matcher) || devices.pop(); if (!device) { throw new Error('Impossible to autostart, no input devices available.'); } this.device = device; // @note when listening to this change, callback code will sometimes run before the previous line. this.deviceChange.emit(device); this.isAutostarting = false; this.autostarted.next(); }; /** * Dispatches the scan success event. * * @param result the scan result. */ ZXingScannerComponent.prototype.dispatchScanSuccess = function (result) { this.scanSuccess.next(result.getText()); }; /** * Dispatches the scan failure event. */ ZXingScannerComponent.prototype.dispatchScanFailure = function (reason) { this.scanFailure.next(reason); }; /** * Dispatches the scan error event. * * @param error the error thing. */ ZXingScannerComponent.prototype.dispatchScanError = function (error) { this.scanError.next(error); }; /** * Dispatches the scan event. * * @param result the scan result. */ ZXingScannerComponent.prototype.dispatchScanComplete = function (result) { this.scanComplete.next(result); }; /** * Returns the filtered permission. */ ZXingScannerComponent.prototype.handlePermissionException = function (err) { // failed to grant permission to video input console.error('@zxing/ngx-scanner', 'Error when asking for permission.', err); var permission; switch (err.name) { // usually caused by not secure origins case 'NotSupportedError': console.warn('@zxing/ngx-scanner', err.message); // could not claim permission = null; // can't check devices this.hasDevices.next(null); break; // user denied permission case 'NotAllowedError': console.warn('@zxing/ngx-scanner', err.message); // claimed and denied permission permission = false; // this means that input devices exists this.hasDevices.next(true); break; // the device has no attached input devices case 'NotFoundError': console.warn('@zxing/ngx-scanner', err.message); // no permissions claimed permission = null; // because there was no devices this.hasDevices.next(false); // tells the listener about the error this.camerasNotFound.next(err); break; case 'NotReadableError': console.warn('@zxing/ngx-scanner', 'Couldn\'t read the device(s)\'s stream, it\'s probably in use by another app.'); // no permissions claimed permission = null; // there are devices, which I couldn't use this.hasDevices.next(false); // tells the listener about the error this.camerasNotFound.next(err); break; default: console.warn('@zxing/ngx-scanner', 'I was not able to define if I have permissions for camera or not.', err); // unknown permission = null; // this.hasDevices.next(undefined; break; } this.setPermission(permission); // tells the listener about the error this.permissionResponse.error(err); return permission; }; /** * Returns a valid BarcodeFormat or fails. */ ZXingScannerComponent.prototype.getBarcodeFormatOrFail = function (format) { return typeof format === 'string' ? BarcodeFormat[format.trim().toUpperCase()] : format; }; /** * Retorna um code reader, cria um se nenhume existe. */ ZXingScannerComponent.prototype.getCodeReader = function () { if (!this._codeReader) { this._codeReader = new BrowserMultiFormatContinuousReader(this.hints); } return this._codeReader; }; /** * Starts the continuous scanning for the given device. * * @param deviceId The deviceId from the device. */ ZXingScannerComponent.prototype.scanFromDevice = function (deviceId) { var _this = this; var videoElement = this.previewElemRef.nativeElement; var codeReader = this.getCodeReader(); var decodingStream = codeReader.continuousDecodeFromInputVideoDevice(deviceId, videoElement); if (!decodingStream) { throw new Error('Undefined decoding stream, aborting.'); } var next = function (x) { return _this._onDecodeResult(x.result, x.error); }; var error = function (err) { return _this._onDecodeError(err); }; var complete = function () { _this.reset(); console.log('completed'); }; decodingStream.subscribe(next, error, complete); }; /** * Handles decode errors. */ ZXingScannerComponent.prototype._onDecodeError = function (err) { this.dispatchScanError(err); this.reset(); }; /** * Handles decode results. */ ZXingScannerComponent.prototype._onDecodeResult = function (result, error) { if (result) { this.dispatchScanSuccess(result); } else { this.dispatchScanFailure(error); } this.dispatchScanComplete(result); }; /** * Stops the code reader and returns the previous selected device. */ ZXingScannerComponent.prototype._reset = function () { if (!this._codeReader) { return; } var device = this.device; // do not set this.device inside this method, it would create a recursive loop this._device = null; this._codeReader.reset(); return device; }; /** * Resets the scanner and emits device change. */ ZXingScannerComponent.prototype.reset = function () { this._reset(); this.deviceChange.emit(null); }; /** * Sets the permission value and emmits the event. */ ZXingScannerComponent.prototype.setPermission = function (hasPermission) { this.hasPermission = hasPermission; this.permissionResponse.next(hasPermission); }; tslib_1.__decorate([ ViewChild('preview', { static: true }), tslib_1.__metadata("design:type", ElementRef) ], ZXingScannerComponent.prototype, "previewElemRef", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean) ], ZXingScannerComponent.prototype, "autofocusEnabled", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "autostarted", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "autostarting", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean) ], ZXingScannerComponent.prototype, "autostart", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", String) ], ZXingScannerComponent.prototype, "previewFitMode", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "torchCompatible", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "scanSuccess", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "scanFailure", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "scanError", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "scanComplete", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "camerasFound", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "camerasNotFound", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "permissionResponse", void 0); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "hasDevices", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", MediaDeviceInfo), tslib_1.__metadata("design:paramtypes", [MediaDeviceInfo]) ], ZXingScannerComponent.prototype, "device", null); tslib_1.__decorate([ Output(), tslib_1.__metadata("design:type", EventEmitter) ], ZXingScannerComponent.prototype, "deviceChange", void 0); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Array), tslib_1.__metadata("design:paramtypes", [Array]) ], ZXingScannerComponent.prototype, "formats", null); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean), tslib_1.__metadata("design:paramtypes", [Boolean]) ], ZXingScannerComponent.prototype, "torch", null); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean), tslib_1.__metadata("design:paramtypes", [Boolean]) ], ZXingScannerComponent.prototype, "enable", null); tslib_1.__decorate([ Input(), tslib_1.__metadata("design:type", Boolean), tslib_1.__metadata("design:paramtypes", [Boolean]) ], ZXingScannerComponent.prototype, "tryHarder", null); ZXingScannerComponent = tslib_1.__decorate([ Component({ selector: 'zxing-scanner', template: "<video #preview [style.object-fit]=\"previewFitMode\">\n <p>\n Your browser does not support this feature, please try to upgrade it.\n </p>\n <p>\n Seu navegador n\u00E3o suporta este recurso, por favor tente atualiz\u00E1-lo.\n </p>\n</video>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}video{width:100%;height:auto;-o-object-fit:contain;object-fit:contain}"] }), tslib_1.__metadata("design:paramtypes", []) ], ZXingScannerComponent); return ZXingScannerComponent; }()); export { ZXingScannerComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoienhpbmctc2Nhbm5lci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9Aenhpbmcvbmd4LXNjYW5uZXIvIiwic291cmNlcyI6WyJsaWIvenhpbmctc2Nhbm5lci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFFTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixhQUFhLEVBQ2IsY0FBYyxFQUdmLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFFLGtDQUFrQyxFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFTOUY7SUEwVEU7O09BRUc7SUFDSDtRQXJQQTs7V0FFRztRQUVILG1CQUFjLEdBQXlELE9BQU8sQ0FBQztRQWtQN0UsMEJBQTBCO1FBQzFCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUN0QyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDdkMsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzFDLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUN0QyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDdEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ3BDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUN2QyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDdkMsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzFDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLFlBQVks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QUFmLGVBQWU7dURBcUNqQztJQU1EO1FBREMsTUFBTSxFQUFFOzBDQUNLLFlBQVk7K0RBQWtCO0lBc0I1QztRQURDLEtBQUssRUFBRTs7O3dEQWdCUDtJQXlDRDtRQURDLEtBQUssRUFBRTs7O3NEQUdQO0lBTUQ7UUFEQyxLQUFLLEVBQUU7Ozt1REFVUDtJQW9CRDtRQURDLEtBQUssRUFBRTs7OzBEQVlQO0lBeFRVLHFCQUFxQjtRQU5qQyxTQUFTLENBQUM7WUFDVCxRQUFRLEVBQUUsZUFBZTtZQUN6QiwyUUFBNkM7WUFFN0MsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07O1NBQ2hELENBQUM7O09BQ1cscUJBQXFCLENBNnRCakM7SUFBRCw0QkFBQztDQUFBLEFBN3RCRCxJQTZ0QkM7U0E3dEJZLHFCQUFxQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT3V0cHV0LFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQge1xuICBBcmd1bWVudEV4Y2VwdGlvbixcbiAgQmFyY29kZUZvcm1hdCxcbiAgRGVjb2RlSGludFR5cGUsXG4gIEV4Y2VwdGlvbixcbiAgUmVzdWx0XG59IGZyb20gJ0B6eGluZy9saWJyYXJ5JztcblxuaW1wb3J0IHsgQnJvd3Nlck11bHRpRm9ybWF0Q29udGludW91c1JlYWRlciB9IGZyb20gJy4vYnJvd3Nlci1tdWx0aS1mb3JtYXQtY29udGludW91cy1yZWFkZXInO1xuaW1wb3J0IHsgUmVzdWx0QW5kRXJyb3IgfSBmcm9tICcuL1Jlc3VsdEFuZEVycm9yJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnenhpbmctc2Nhbm5lcicsXG4gIHRlbXBsYXRlVXJsOiAnLi96eGluZy1zY2FubmVyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4venhpbmctc2Nhbm5lci5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBaWGluZ1NjYW5uZXJDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuXG4gIC8qKlxuICAgKiBTdXBwb3J0ZWQgSGludHMgbWFwLlxuICAgKi9cbiAgcHJpdmF0ZSBfaGludHM6IE1hcDxEZWNvZGVIaW50VHlwZSwgYW55PiB8IG51bGw7XG5cbiAgLyoqXG4gICAqIFRoZSBaWGluZyBjb2RlIHJlYWRlci5cbiAgICovXG4gIHByaXZhdGUgX2NvZGVSZWFkZXI6IEJyb3dzZXJNdWx0aUZvcm1hdENvbnRpbnVvdXNSZWFkZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBkZXZpY2UgdGhhdCBzaG91bGQgYmUgdXNlZCB0byBzY2FuIHRoaW5ncy5cbiAgICovXG4gIHByaXZhdGUgX2RldmljZTogTWVkaWFEZXZpY2VJbmZvO1xuXG4gIC8qKlxuICAgKiBUaGUgZGV2aWNlIHRoYXQgc2hvdWxkIGJlIHVzZWQgdG8gc2NhbiB0aGluZ3MuXG4gICAqL1xuICBwcml2YXRlIF9lbmFibGVkOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKlxuICAgKi9cbiAgcHJpdmF0ZSBfaXNBdXRvc3RhcnRpbmc6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEhhcyBgbmF2aWdhdG9yYCBhY2Nlc3MuXG4gICAqL1xuICBwcml2YXRlIGhhc05hdmlnYXRvcjogYm9vbGVhbjtcblxuICAvKipcbiAgICogU2F5cyBpZiBzb21lIG5hdGl2ZSBBUEkgaXMgc3VwcG9ydGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBpc01lZGlhRGV2aWNlc1N1cG9ydGVkOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJZiB0aGUgdXNlci1hZ2VudCBhbGxvd2VkIHRoZSB1c2Ugb2YgdGhlIGNhbWVyYSBvciBub3QuXG4gICAqL1xuICBwcml2YXRlIGhhc1Blcm1pc3Npb246IGJvb2xlYW4gfCBudWxsO1xuXG4gIC8qKlxuICAgKiBSZWZlcmVuY2UgdG8gdGhlIHByZXZpZXcgZWxlbWVudCwgc2hvdWxkIGJlIHRoZSBgdmlkZW9gIHRhZy5cbiAgICovXG4gIEBWaWV3Q2hpbGQoJ3ByZXZpZXcnLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICBwcmV2aWV3RWxlbVJlZjogRWxlbWVudFJlZjxIVE1MVmlkZW9FbGVtZW50PjtcblxuICAvKipcbiAgICogRW5hYmxlIG9yIGRpc2FibGUgYXV0b2ZvY3VzIG9mIHRoZSBjYW1lcmEgKG1pZ2h0IGhhdmUgYW4gaW1wYWN0IG9uIHBlcmZvcm1hbmNlKVxuICAgKi9cbiAgQElucHV0KClcbiAgYXV0b2ZvY3VzRW5hYmxlZDogYm9vbGVhbjtcblxuICAvKipcbiAgICogRW1pdHMgd2hlbiBhbmQgaWYgdGhlIHNjYW5uZXIgaXMgYXV0b3N0YXJ0ZWQuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgYXV0b3N0YXJ0ZWQ6IEV2ZW50RW1pdHRlcjx2b2lkPjtcblxuICAvKipcbiAgICogVHJ1ZSBkdXJpbmcgYXV0b3N0YXJ0IGFuZCBmYWxzZSBhZnRlci4gSXQgd2lsbCBiZSBudWxsIGlmIHdvbid0IGF1dG9zdGFydCBhdCBhbGwuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgYXV0b3N0YXJ0aW5nOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbiB8IG51bGw+O1xuXG4gIC8qKlxuICAgKiBJZiB0aGUgc2Nhbm5lciBzaG91bGQgYXV0b3N0YXJ0IHdpdGggdGhlIGZpcnN0IGF2YWlsYWJsZSBkZXZpY2UuXG4gICAqL1xuICBASW5wdXQoKVxuICBhdXRvc3RhcnQ6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEhvdyB0aGUgcHJldmlldyBlbGVtZW50IHNob3VkIGJlIGZpdCBpbnNpZGUgdGhlIDpob3N0IGNvbnRhaW5lci5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHByZXZpZXdGaXRNb2RlOiAnZmlsbCcgfCAnY29udGFpbicgfCAnY292ZXInIHwgJ3NjYWxlLWRvd24nIHwgJ25vbmUnID0gJ2NvdmVyJztcblxuICAvKipcbiAgICogRW1pdHRzIGV2ZW50cyB3aGVuIHRoZSB0b3JjaCBjb21wYXRpYmlsaXR5IGlzIGNoYW5nZWQuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgdG9yY2hDb21wYXRpYmxlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj47XG5cbiAgLyoqXG4gICAqIEVtaXR0cyBldmVudHMgd2hlbiBhIHNjYW4gaXMgc3VjY2Vzc2Z1bCBwZXJmb3JtZWQsIHdpbGwgaW5qZWN0IHRoZSBzdHJpbmcgdmFsdWUgb2YgdGhlIFFSLWNvZGUgdG8gdGhlIGNhbGxiYWNrLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIHNjYW5TdWNjZXNzOiBFdmVudEVtaXR0ZXI8c3RyaW5nPjtcblxuICAvKipcbiAgICogRW1pdHRzIGV2ZW50cyB3aGVuIGEgc2NhbiBmYWlscyB3aXRob3V0IGVycm9ycywgdXNlZnVsbCB0byBrbm93IGhvdyBtdWNoIHNjYW4gdHJpZXMgd2hlcmUgbWFkZS5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBzY2FuRmFpbHVyZTogRXZlbnRFbWl0dGVyPEV4Y2VwdGlvbiB8IHVuZGVmaW5lZD47XG5cbiAgLyoqXG4gICAqIEVtaXR0cyBldmVudHMgd2hlbiBhIHNjYW4gdGhyb3dzIHNvbWUgZXJyb3IsIHdpbGwgaW5qZWN0IHRoZSBlcnJvciB0byB0aGUgY2FsbGJhY2suXG4gICAqL1xuICBAT3V0cHV0KClcbiAgc2NhbkVycm9yOiBFdmVudEVtaXR0ZXI8RXJyb3I+O1xuXG4gIC8qKlxuICAgKiBFbWl0dHMgZXZlbnRzIHdoZW4gYSBzY2FuIGlzIHBlcmZvcm1lZCwgd2lsbCBpbmplY3QgdGhlIFJlc3VsdCB2YWx1ZSBvZiB0aGUgUVItY29kZSBzY2FuIChpZiBhdmFpbGFibGUpIHRvIHRoZSBjYWxsYmFjay5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBzY2FuQ29tcGxldGU6IEV2ZW50RW1pdHRlcjxSZXN1bHQ+O1xuXG4gIC8qKlxuICAgKiBFbWl0dHMgZXZlbnRzIHdoZW4gbm8gY2FtZXJhcyBhcmUgZm91bmQsIHdpbGwgaW5qZWN0IGFuIGV4Y2VwdGlvbiAoaWYgYXZhaWxhYmxlKSB0byB0aGUgY2FsbGJhY2suXG4gICAqL1xuICBAT3V0cHV0KClcbiAgY2FtZXJhc0ZvdW5kOiBFdmVudEVtaXR0ZXI8TWVkaWFEZXZpY2VJbmZvW10+O1xuXG4gIC8qKlxuICAgKiBFbWl0dHMgZXZlbnRzIHdoZW4gbm8gY2FtZXJhcyBhcmUgZm91bmQsIHdpbGwgaW5qZWN0IGFuIGV4Y2VwdGlvbiAoaWYgYXZhaWxhYmxlKSB0byB0aGUgY2FsbGJhY2suXG4gICAqL1xuICBAT3V0cHV0KClcbiAgY2FtZXJhc05vdEZvdW5kOiBFdmVudEVtaXR0ZXI8YW55PjtcblxuICAvKipcbiAgICogRW1pdHRzIGV2ZW50cyB3aGVuIHRoZSB1c2VycyBhbnN3ZXJzIGZvciBwZXJtaXNzaW9uLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIHBlcm1pc3Npb25SZXNwb25zZTogRXZlbnRFbWl0dGVyPGJvb2xlYW4+O1xuXG4gIC8qKlxuICAgKiBFbWl0dHMgZXZlbnRzIHdoZW4gaGFzIGRldmljZXMgc3RhdHVzIGlzIHVwZGF0ZS5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBoYXNEZXZpY2VzOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj47XG5cbiAgLyoqXG4gICAqIEV4cG9zZXMgdGhlIGN1cnJlbnQgY29kZSByZWFkZXIsIHNvIHRoZSB1c2VyIGNhbiB1c2UgaXQncyBBUElzLlxuICAgKi9cbiAgZ2V0IGNvZGVSZWFkZXIoKTogQnJvd3Nlck11bHRpRm9ybWF0Q29udGludW91c1JlYWRlciB7XG4gICAgcmV0dXJuIHRoaXMuX2NvZGVSZWFkZXI7XG4gIH1cblxuICAvKipcbiAgICogVXNlciBkZXZpY2UgaW5wdXRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHNldCBkZXZpY2UoZGV2aWNlOiBNZWRpYURldmljZUluZm8gfCBudWxsKSB7XG5cbiAgICBpZiAoIWRldmljZSAmJiBkZXZpY2UgIT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbignVGhlIGBkZXZpY2VgIG11c3QgYmUgYSB2YWxpZCBNZWRpYURldmljZUluZm8gb3IgbnVsbC4nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5pc0N1cnJlbnREZXZpY2UoZGV2aWNlKSkge1xuICAgICAgY29uc29sZS53YXJuKCdTZXR0aW5nIHRoZSBzYW1lIGRldmljZSBpcyBub3QgYWxsb3dlZC4nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5pc0F1dG9zdGFydGluZykge1xuICAgICAgLy8gZG8gbm90IGFsbG93IHNldHRpbmcgZGV2aWNlcyBkdXJpbmcgYXV0by1zdGFydCwgc2luY2UgaXQgd2lsbCBzZXQgb25lIGFuZCBlbWl0IGl0LlxuICAgICAgY29uc29sZS53YXJuKCdBdm9pZCBzZXR0aW5nIGEgZGV2aWNlIGR1cmluZyBhdXRvLXN0YXJ0LicpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5oYXNQZXJtaXNzaW9uKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1Blcm1pc3Npb25zIG5vdCBzZXQgeWV0LCB3YWl0aW5nIGZvciB0aGVtIHRvIGJlIHNldCB0byBhcHBseSBkZXZpY2UgY2hhbmdlLicpO1xuICAgICAgLy8gdGhpcy5wZXJtaXNzaW9uUmVzcG9uc2VcbiAgICAgIC8vICAgLnBpcGUoXG4gICAgICAvLyAgICAgdGFrZSgxKSxcbiAgICAgIC8vICAgICB0YXAoKCkgPT4gY29uc29sZS5sb2coYFBlcm1pc3Npb25zIHNldCwgYXBwbHlpbmcgZGV2aWNlIGNoYW5nZSR7ZGV2aWNlID8gYCAoJHtkZXZpY2UuZGV2aWNlSWR9KWAgOiAnJ30uYCkpXG4gICAgICAvLyAgIClcbiAgICAgIC8vICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmRldmljZSA9IGRldmljZSk7XG4gICAgICAvLyByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gaW4gb3JkZXIgdG8gY2hhbmdlIHRoZSBkZXZpY2UgdGhlIGNvZGVSZWFkZXIgZ290dGEgYmUgcmVzZXRlZFxuICAgIHRoaXMuX3Jlc2V0KCk7XG5cbiAgICB0aGlzLl9kZXZpY2UgPSBkZXZpY2U7XG5cbiAgICAvLyBpZiBlbmFibGVkLCBzdGFydHMgc2Nhbm5pbmdcbiAgICBpZiAodGhpcy5fZW5hYmxlZCAmJiBkZXZpY2UgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuc2NhbkZyb21EZXZpY2UoZGV2aWNlLmRldmljZUlkKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRW1pdHMgd2hlbiB0aGUgY3VycmVudCBkZXZpY2UgaXMgY2hhbmdlZC5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBkZXZpY2VDaGFuZ2U6IEV2ZW50RW1pdHRlcjxNZWRpYURldmljZUluZm8+O1xuXG4gIC8qKlxuICAgKiBVc2VyIGRldmljZSBhY2Vzc29yLlxuICAgKi9cbiAgZ2V0IGRldmljZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZGV2aWNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYWxsIHRoZSByZWdpc3RlcmVkIGZvcm1hdHMuXG4gICAqL1xuICBnZXQgZm9ybWF0cygpOiBCYXJjb2RlRm9ybWF0W10ge1xuICAgIHJldHVybiB0aGlzLmhpbnRzLmdldChEZWNvZGVIaW50VHlwZS5QT1NTSUJMRV9GT1JNQVRTKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgZm9ybWF0cyB0aGUgc2Nhbm5lciBzaG91bGQgc3VwcG9ydC5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0IEJhcmNvZGVGb3JtYXQgb3IgY2FzZS1pbnNlbnNpdGl2ZSBzdHJpbmcgYXJyYXkuXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgZm9ybWF0cyhpbnB1dDogQmFyY29kZUZvcm1hdFtdKSB7XG5cbiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGZvcm1hdHMsIG1ha2Ugc3VyZSB0aGUgW2Zvcm1hdHNdIGlucHV0IGlzIGEgYmluZGluZy4nKTtcbiAgICB9XG5cbiAgICAvLyBmb3JtYXRzIG1heSBiZSBzZXQgZnJvbSBod