angular-weblineindia-qrcode-scanner
Version:
An AngularJS based Barcode / QRCode scanner component.
668 lines • 67.6 kB
JavaScript
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