truly-ui
Version:
Web Components for Desktop Applications.
360 lines (358 loc) • 51.8 kB
JavaScript
/*
MIT License
Copyright (c) 2019 Temainfo Software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import { Component, Input, Output, Inject, Optional, ViewChild, EventEmitter, Self, } from '@angular/core';
import * as objectPath from 'object-path';
import { OverlayAnimation } from '../core/directives/overlay-animation';
import { KeyEvent } from '../core/enums/key-events';
import { DROPDOWN_CONFIG } from './interfaces/dropdown.config';
import { ValueAccessorBase } from '../input/core/value-accessor';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@angular/common";
import * as i3 from "../overlaylist/overlay-list";
import * as i4 from "../icons/icons";
import * as i5 from "../loader/loader";
import * as i6 from "@angular/cdk/overlay";
import * as i7 from "../internals/components/label/label";
export class TlDropDownList extends ValueAccessorBase {
set data(data) {
if (data) {
this._data = data;
this.initializeComponent();
}
}
get data() {
return this._data;
}
constructor(dropdownConfig, changes, ngControl) {
super();
this.changes = changes;
this.ngControl = ngControl;
this.keyText = null;
this.icon = null;
this.debounceTime = 200;
this.disabled = false;
this.labelPlacement = 'left';
this.labelSize = '100px';
this.itemHeight = '23px';
this.keyValue = null;
this.maxHeight = '150px';
this.identifier = null;
this.defaultOption = false;
this.groupBy = null;
this.width = '100%';
this.placeholder = 'Select Item';
this.modelMode = 'object';
this.searchOnList = false;
this.selectItem = new EventEmitter();
this.typeOfData = 'complex';
this.selectedDescription = '';
this.isOpen = false;
this.datasource = [];
this.isLoading = true;
this.setControl();
this.setOptions(dropdownConfig);
}
get control() {
return this.ngControl?.control;
}
ngOnInit() {
this.listenModelChange();
this.getModelValue();
}
setControl() {
if (this.ngControl) {
this.ngControl.valueAccessor = this;
}
}
onSearch(searchTextValue) {
const filter = [];
this.datasource = this.data.slice();
this.datasource.filter((item) => {
if (this.getItemText(item).toLowerCase().includes(searchTextValue.toLowerCase())) {
filter.push(item);
}
});
this.datasource = filter;
}
getItemText(item) {
if (this.typeOfData === 'simple') {
return item;
}
return objectPath.get(item, this.keyText);
}
onKeyDown($event) {
this.handleSelectInLetter($event.key);
const keyEvent = {
[KeyEvent.SPACE]: () => this.handleOpenList($event),
[KeyEvent.ARROWDOWN]: () => this.stopEvent($event),
[KeyEvent.ARROWUP]: () => this.stopEvent($event),
[KeyEvent.ESCAPE]: () => this.handleEscape($event)
};
if (keyEvent[$event.code]) {
keyEvent[$event.code]();
}
}
handleEscape($event) {
if (this.isOpen) {
this.isOpen = false;
this.stopEvent($event);
}
}
getNativeInput() {
return this.input.nativeElement;
}
onFindByLetter(value) {
this.handleSelectInLetter(value);
}
onSelectOption($event) {
this.isOpen = false;
this.optionSelected = $event;
this.selectedDescription = this.isSimpleData() ? $event.option.item : objectPath.get($event.option.item, this.keyText);
this.selectItem.emit($event.option.item);
this.handleKeyModelValue($event.option.item);
this.setInputFocus();
}
onDefaultOption() {
this.value = '';
this.selectedDescription = this.placeholder;
this.optionSelected = null;
this.isOpen = false;
}
isModelModeString() {
return this.modelMode === 'string';
}
handleOpenList($event) {
this.stopEvent($event);
if (!this.isOpen && !this.disabled && !this.isLoading) {
this.isOpen = true;
this.setUpComponent();
}
}
onBackdropClick() {
this.isOpen = false;
this.changes.detectChanges();
}
initializeComponent() {
this.setUpComponent();
this.validateData();
this.getModelValue();
}
setUpComponent() {
this.datasource = this.data;
if (this.data.length > 0) {
this.isLoading = false;
}
}
validateData() {
const key = Object.keys(this.data)[0];
if (typeof this.data[key] === 'string') {
this.typeOfData = 'simple';
}
}
handleCloseDropdown() {
this.isOpen = false;
this.setInputFocus();
}
setInputFocus() {
this.input.nativeElement.focus();
}
isSimpleData() {
return this.typeOfData === 'simple';
}
listenModelChange() {
if (this.control) {
this.control.valueChanges.subscribe(() => {
this.getModelValue();
});
}
}
handleKeyModelValue(itemValue) {
if (this.isSimpleData()) {
return this.value = itemValue;
}
if (!this.keyValue) {
return this.value = itemValue;
}
return this.value = objectPath.get(itemValue, this.keyValue);
}
getModelValue() {
if (!this.control) {
return;
}
this.datasource.forEach((value, index) => {
if (this.control.value) {
if (this.getCompare(value) === this.getCompareModel()) {
this.selectedDescription = this.getDescription(value);
this.indexOptionSelectedModel = index;
this.changes.detectChanges();
this.handleKeyModelValue(value);
return;
}
}
});
}
setOptions(options) {
if (options) {
const self = this;
Object.keys(options).forEach(function (key) {
self[key] = options[key];
});
}
}
getCompareModel() {
if (this.isSimpleData()) {
return this.control.value;
}
if (!this.keyValue) {
return objectPath.get(this.control.value, this.identifier);
}
if (this.isModelModeString()) {
return this.control.value;
}
return objectPath.get(this.control.value, this.keyValue);
}
getCompare(value) {
if (this.isSimpleData()) {
return value;
}
if (!this.keyValue) {
return objectPath.get(value, this.identifier);
}
return objectPath.get(value, this.keyValue);
}
getDescription(value) {
if (this.isSimpleData()) {
return value;
}
return objectPath.get(value, this.keyText);
}
handleSelectInLetter(keyInput) {
const selected = this.selectByFirst(keyInput);
if (selected) {
this.selectedDescription = this.getDescription(selected.option);
this.optionSelected = { option: selected.option, index: selected.index };
this.handleKeyModelValue(selected.option);
}
}
stopEvent($event) {
$event.stopPropagation();
$event.preventDefault();
}
selectByFirst(keyInput) {
let selected = null;
this.datasource.forEach((option, index) => {
if (this.getFirstLetterOfItem(option) === this.getKeyInputLowerCase(keyInput)) {
selected = { option, index };
return;
}
});
return selected;
}
getKeyInputLowerCase(keyInput) {
return String(keyInput).toLowerCase();
}
getFirstLetterOfItem(item) {
return String(objectPath.get(item, this.keyText)).substring(0, 1).toLowerCase();
}
ngOnChanges({ data }) {
if (data) {
if (!data.firstChange && data.currentValue.length === 0) {
this.isLoading = false;
}
}
}
}
/** @nocollapse */ TlDropDownList.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlDropDownList, deps: [{ token: DROPDOWN_CONFIG, optional: true }, { token: i0.ChangeDetectorRef }, { token: i1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TlDropDownList.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TlDropDownList, selector: "tl-dropdown-list", inputs: { data: "data", keyText: "keyText", icon: "icon", label: "label", debounceTime: "debounceTime", disabled: "disabled", labelPlacement: "labelPlacement", labelSize: "labelSize", itemHeight: "itemHeight", keyValue: "keyValue", maxHeight: "maxHeight", identifier: "identifier", defaultOption: "defaultOption", groupBy: "groupBy", width: "width", placeholder: "placeholder", modelMode: "modelMode", searchOnList: "searchOnList" }, outputs: { selectItem: "selectItem" }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"ui-dropdown-box\" [ngStyle]=\"{'line-height' : itemHeight, 'width': width}\">\n\n <div class=\"ui-loading-icon\" [style.height]=\"itemHeight\" *ngIf=\"isLoading\">\n <tl-loader></tl-loader>\n </div>\n\n <tl-label *ngIf=\"label\"\n [labelPlacement]=\"labelPlacement\"\n [labelSize]=\"labelSize\"\n [labelTitle]=\"label\">\n </tl-label>\n\n <div class=\"ui-dropdown-wrapper\">\n <input cdkOverlayOrigin\n #input\n readonly\n #trigger=\"cdkOverlayOrigin\"\n [attr.disabled]=\"disabled ? true : null\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"handleOpenList($event)\"\n value=\"{{ selectedDescription ? selectedDescription : placeholder }}\"\n [ngClass]=\"{ 'ng-invalid' : control?.invalid, 'disabled': disabled }\"\n [ngStyle]=\"{'height' : itemHeight, 'line-height' : itemHeight}\"\n class=\"ui-dropdown\">\n <div class=\"ui-dropdown-icon\"\n [style.height]=\"itemHeight\"\n [style.transform]=\"isOpen ? 'rotate(180deg)' : 'rotate(0)'\"\n [ngClass]=\"{ 'disabled': disabled, 'ng-invalid' : control?.invalid }\">\n <tl-icon [lib]=\"'ion'\" [style]=\"'ios'\">arrow-down</tl-icon>\n </div>\n </div>\n <input readonly notform class=\"ui-hidden-input\" [(ngModel)]=\"value\">\n <ng-template cdkConnectedOverlay\n (backdropClick)=\"onBackdropClick()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n [cdkConnectedOverlayOpen]=\"isOpen\">\n <tl-overlay-list\n @overlay\n (selectOption)=\"onSelectOption($event)\"\n (search)=\"onSearch($event)\"\n (close)=\"handleCloseDropdown()\"\n (defaultOption)=\"onDefaultOption()\"\n (findByLetter)=\"onFindByLetter($event)\"\n [customInput]=\"input\"\n [typeOfData]=\"typeOfData\"\n [hasDefaultOption]=\"defaultOption\"\n [defaultOptionText]=\"placeholder\"\n [groupBy]=\"groupBy\"\n [optionSelected]=\"optionSelected\"\n [inputModelIndex]=\"indexOptionSelectedModel\"\n [datasource]=\"datasource\"\n [maxHeight]=\"maxHeight\"\n [itemHeight]=\"itemHeight\"\n [width]=\"input.offsetWidth + 'px'\"\n [icon]=\"icon\"\n [keyText]=\"keyText\"\n [searchOnList]=\"searchOnList\">\n </tl-overlay-list>\n </ng-template>\n</div>\n", styles: ["*{box-sizing:border-box}.ui-dropdown-box{width:100%;position:relative;display:table}.ui-dropdown-box>.ui-dropdown-wrapper{position:relative}.ui-dropdown-box>.ui-dropdown-wrapper>.ui-dropdown{border-radius:3px;width:100%;padding-left:5px;cursor:pointer;font-size:1em;font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-weight:400;user-select:none;-webkit-user-select:none}.ui-dropdown-box>.ui-dropdown-wrapper>.ui-dropdown-icon{position:absolute;top:0;width:20px;right:10px;text-align:center;font-size:1em;font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-weight:400;transition:transform linear .2s;pointer-events:none}.ui-dropdown-box>.ui-dropdown-wrapper>.ui-dropdown-icon i{padding:0}.ui-dropdown-box>.ui-hidden-input{position:absolute;left:0;opacity:0;width:0;bottom:0}.ui-dropdown-box .ui-loading-icon{position:absolute;width:18px;height:18px;z-index:1;margin:0;right:35px}.ui-dropdown-box tl-icon{position:absolute;right:5px;opacity:.5}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3.TlOverlayList, selector: "tl-overlay-list", inputs: ["datasource", "searchOnList", "itemHeight", "inputModelIndex", "optionSelected", "typeOfData", "keyText", "groupBy", "keyIcon", "icon", "defaultIcon", "defaultOptionText", "width", "maxHeight", "customInput", "customFocus", "hasDefaultOption"], outputs: ["selectOption", "defaultOption", "search", "findByLetter", "close"] }, { kind: "component", type: i4.TlIcons, selector: "tl-icon", inputs: ["icon", "lib", "style", "size", "animation", "color", "align"] }, { kind: "component", type: i5.TlLoader, selector: "tl-loader", inputs: ["color", "strokeWidth"] }, { kind: "directive", type: i6.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i6.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: i7.TlLabel, selector: "tl-label", inputs: ["labelPlacement", "required", "labelSize", "labelTitle"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], animations: [OverlayAnimation] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlDropDownList, decorators: [{
type: Component,
args: [{ selector: 'tl-dropdown-list', animations: [OverlayAnimation], template: "<div class=\"ui-dropdown-box\" [ngStyle]=\"{'line-height' : itemHeight, 'width': width}\">\n\n <div class=\"ui-loading-icon\" [style.height]=\"itemHeight\" *ngIf=\"isLoading\">\n <tl-loader></tl-loader>\n </div>\n\n <tl-label *ngIf=\"label\"\n [labelPlacement]=\"labelPlacement\"\n [labelSize]=\"labelSize\"\n [labelTitle]=\"label\">\n </tl-label>\n\n <div class=\"ui-dropdown-wrapper\">\n <input cdkOverlayOrigin\n #input\n readonly\n #trigger=\"cdkOverlayOrigin\"\n [attr.disabled]=\"disabled ? true : null\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"handleOpenList($event)\"\n value=\"{{ selectedDescription ? selectedDescription : placeholder }}\"\n [ngClass]=\"{ 'ng-invalid' : control?.invalid, 'disabled': disabled }\"\n [ngStyle]=\"{'height' : itemHeight, 'line-height' : itemHeight}\"\n class=\"ui-dropdown\">\n <div class=\"ui-dropdown-icon\"\n [style.height]=\"itemHeight\"\n [style.transform]=\"isOpen ? 'rotate(180deg)' : 'rotate(0)'\"\n [ngClass]=\"{ 'disabled': disabled, 'ng-invalid' : control?.invalid }\">\n <tl-icon [lib]=\"'ion'\" [style]=\"'ios'\">arrow-down</tl-icon>\n </div>\n </div>\n <input readonly notform class=\"ui-hidden-input\" [(ngModel)]=\"value\">\n <ng-template cdkConnectedOverlay\n (backdropClick)=\"onBackdropClick()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n [cdkConnectedOverlayOpen]=\"isOpen\">\n <tl-overlay-list\n @overlay\n (selectOption)=\"onSelectOption($event)\"\n (search)=\"onSearch($event)\"\n (close)=\"handleCloseDropdown()\"\n (defaultOption)=\"onDefaultOption()\"\n (findByLetter)=\"onFindByLetter($event)\"\n [customInput]=\"input\"\n [typeOfData]=\"typeOfData\"\n [hasDefaultOption]=\"defaultOption\"\n [defaultOptionText]=\"placeholder\"\n [groupBy]=\"groupBy\"\n [optionSelected]=\"optionSelected\"\n [inputModelIndex]=\"indexOptionSelectedModel\"\n [datasource]=\"datasource\"\n [maxHeight]=\"maxHeight\"\n [itemHeight]=\"itemHeight\"\n [width]=\"input.offsetWidth + 'px'\"\n [icon]=\"icon\"\n [keyText]=\"keyText\"\n [searchOnList]=\"searchOnList\">\n </tl-overlay-list>\n </ng-template>\n</div>\n", styles: ["*{box-sizing:border-box}.ui-dropdown-box{width:100%;position:relative;display:table}.ui-dropdown-box>.ui-dropdown-wrapper{position:relative}.ui-dropdown-box>.ui-dropdown-wrapper>.ui-dropdown{border-radius:3px;width:100%;padding-left:5px;cursor:pointer;font-size:1em;font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-weight:400;user-select:none;-webkit-user-select:none}.ui-dropdown-box>.ui-dropdown-wrapper>.ui-dropdown-icon{position:absolute;top:0;width:20px;right:10px;text-align:center;font-size:1em;font-family:Segoe UI,Lato,\"sans-serif\",Arial;font-weight:400;transition:transform linear .2s;pointer-events:none}.ui-dropdown-box>.ui-dropdown-wrapper>.ui-dropdown-icon i{padding:0}.ui-dropdown-box>.ui-hidden-input{position:absolute;left:0;opacity:0;width:0;bottom:0}.ui-dropdown-box .ui-loading-icon{position:absolute;width:18px;height:18px;z-index:1;margin:0;right:35px}.ui-dropdown-box tl-icon{position:absolute;right:5px;opacity:.5}\n"] }]
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [DROPDOWN_CONFIG]
}] }, { type: i0.ChangeDetectorRef }, { type: i1.NgControl, decorators: [{
type: Optional
}, {
type: Self
}] }]; }, propDecorators: { data: [{
type: Input,
args: ['data']
}], keyText: [{
type: Input,
args: ['keyText']
}], icon: [{
type: Input,
args: ['icon']
}], label: [{
type: Input,
args: ['label']
}], debounceTime: [{
type: Input,
args: ['debounceTime']
}], disabled: [{
type: Input,
args: ['disabled']
}], labelPlacement: [{
type: Input,
args: ['labelPlacement']
}], labelSize: [{
type: Input,
args: ['labelSize']
}], itemHeight: [{
type: Input,
args: ['itemHeight']
}], keyValue: [{
type: Input,
args: ['keyValue']
}], maxHeight: [{
type: Input,
args: ['maxHeight']
}], identifier: [{
type: Input,
args: ['identifier']
}], defaultOption: [{
type: Input,
args: ['defaultOption']
}], groupBy: [{
type: Input,
args: ['groupBy']
}], width: [{
type: Input,
args: ['width']
}], placeholder: [{
type: Input,
args: ['placeholder']
}], modelMode: [{
type: Input,
args: ['modelMode']
}], searchOnList: [{
type: Input,
args: ['searchOnList']
}], selectItem: [{
type: Output,
args: ['selectItem']
}], input: [{
type: ViewChild,
args: ['input', { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcGRvd25saXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdHJ1bHktdWkvc3JjL2NvbXBvbmVudHMvZHJvcGRvd25saXN0L2Ryb3Bkb3dubGlzdC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL2Ryb3Bkb3dubGlzdC9kcm9wZG93bmxpc3QuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sTUFBTSxFQUNOLFFBQVEsRUFDUixTQUFTLEVBQ2MsWUFBWSxFQUFvQyxJQUFJLEdBQzVFLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sS0FBSyxVQUFVLE1BQU0sYUFBYSxDQUFDO0FBRzFDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsZUFBZSxFQUFrQixNQUFNLDhCQUE4QixDQUFDO0FBRy9FLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDOzs7Ozs7Ozs7QUFRakUsTUFBTSxPQUFPLGNBQWUsU0FBUSxpQkFBc0I7SUFFeEQsSUFDSSxJQUFJLENBQUUsSUFBVztRQUNuQixJQUFLLElBQUksRUFBRztZQUNWLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1NBQzVCO0lBQ0gsQ0FBQztJQUVELElBQUksSUFBSTtRQUNOLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0lBd0RELFlBQW9ELGNBQThCLEVBQ3hFLE9BQTBCLEVBQTZCLFNBQW9CO1FBQ25GLEtBQUssRUFBRSxDQUFDO1FBREEsWUFBTyxH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QU0sRUFBRSxJQUFJLEVBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuIE1JVCBMaWNlbnNlXG5cbiBDb3B5cmlnaHQgKGMpIDIwMTkgVGVtYWluZm8gU29mdHdhcmVcblxuIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gU09GVFdBUkUuXG4gKi9cbmltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgSW5qZWN0LFxuICBPcHRpb25hbCxcbiAgVmlld0NoaWxkLFxuICBFbGVtZW50UmVmLCBPbkNoYW5nZXMsIEV2ZW50RW1pdHRlciwgQ2hhbmdlRGV0ZWN0b3JSZWYsIFNpbXBsZUNoYW5nZXMsIFNlbGYsIE9uSW5pdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCAqIGFzIG9iamVjdFBhdGggZnJvbSAnb2JqZWN0LXBhdGgnO1xuXG5pbXBvcnQgeyBOZ0NvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBPdmVybGF5QW5pbWF0aW9uIH0gZnJvbSAnLi4vY29yZS9kaXJlY3RpdmVzL292ZXJsYXktYW5pbWF0aW9uJztcbmltcG9ydCB7IEtleUV2ZW50IH0gZnJvbSAnLi4vY29yZS9lbnVtcy9rZXktZXZlbnRzJztcbmltcG9ydCB7IERST1BET1dOX0NPTkZJRywgRHJvcGRvd25Db25maWcgfSBmcm9tICcuL2ludGVyZmFjZXMvZHJvcGRvd24uY29uZmlnJztcbmltcG9ydCB7IExpc3RJdGVtSW50ZXJmYWNlIH0gZnJvbSAnLi9pbnRlcmZhY2VzL2xpc3QtaXRlbSc7XG5pbXBvcnQgeyBUbExpc3RJdGVtIH0gZnJvbSAnLi4vb3ZlcmxheWxpc3QvbGlzdC1pdGVtL2xpc3QtaXRlbSc7XG5pbXBvcnQgeyBWYWx1ZUFjY2Vzc29yQmFzZSB9IGZyb20gJy4uL2lucHV0L2NvcmUvdmFsdWUtYWNjZXNzb3InO1xuXG5AQ29tcG9uZW50KCB7XG4gIHNlbGVjdG9yOiAndGwtZHJvcGRvd24tbGlzdCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9kcm9wZG93bmxpc3QuaHRtbCcsXG4gIHN0eWxlVXJsczogWyAnLi9kcm9wZG93bmxpc3Quc2NzcycgXSxcbiAgYW5pbWF0aW9uczogWyBPdmVybGF5QW5pbWF0aW9uIF1cbn0gKVxuZXhwb3J0IGNsYXNzIFRsRHJvcERvd25MaXN0IGV4dGVuZHMgVmFsdWVBY2Nlc3NvckJhc2U8YW55PiBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcblxuICBASW5wdXQoICdkYXRhJyApXG4gIHNldCBkYXRhKCBkYXRhOiBhbnlbXSApIHtcbiAgICBpZiAoIGRhdGEgKSB7XG4gICAgICB0aGlzLl9kYXRhID0gZGF0YTtcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZUNvbXBvbmVudCgpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBkYXRhKCkge1xuICAgIHJldHVybiB0aGlzLl9kYXRhO1xuICB9XG5cbiAgQElucHV0KCAna2V5VGV4dCcgKSBrZXlUZXh0ID0gbnVsbDtcblxuICBASW5wdXQoICdpY29uJyApIGljb24gPSBudWxsO1xuXG4gIEBJbnB1dCggJ2xhYmVsJyApIGxhYmVsOiBzdHJpbmc7XG5cbiAgQElucHV0KCAnZGVib3VuY2VUaW1lJyApIGRlYm91bmNlVGltZSA9IDIwMDtcblxuICBASW5wdXQoICdkaXNhYmxlZCcgKSBkaXNhYmxlZCA9IGZhbHNlO1xuXG4gIEBJbnB1dCggJ2xhYmVsUGxhY2VtZW50JyApIGxhYmVsUGxhY2VtZW50ID0gJ2xlZnQnO1xuXG4gIEBJbnB1dCggJ2xhYmVsU2l6ZScgKSBsYWJlbFNpemUgPSAnMTAwcHgnO1xuXG4gIEBJbnB1dCggJ2l0ZW1IZWlnaHQnICkgaXRlbUhlaWdodCA9ICcyM3B4JztcblxuICBASW5wdXQoICdrZXlWYWx1ZScgKSBrZXlWYWx1ZSA9IG51bGw7XG5cbiAgQElucHV0KCAnbWF4SGVpZ2h0JyApIG1heEhlaWdodCA9ICcxNTBweCc7XG5cbiAgQElucHV0KCAnaWRlbnRpZmllcicgKSBpZGVudGlmaWVyID0gbnVsbDtcblxuICBASW5wdXQoICdkZWZhdWx0T3B0aW9uJyApIGRlZmF1bHRPcHRpb24gPSBmYWxzZTtcblxuICBASW5wdXQoICdncm91cEJ5JyApIGdyb3VwQnkgPSBudWxsO1xuXG4gIEBJbnB1dCggJ3dpZHRoJyApIHdpZHRoID0gJzEwMCUnO1xuXG4gIEBJbnB1dCggJ3BsYWNlaG9sZGVyJyApIHBsYWNlaG9sZGVyID0gJ1NlbGVjdCBJdGVtJztcblxuICBASW5wdXQoICdtb2RlbE1vZGUnICkgbW9kZWxNb2RlOiAnc3RyaW5nJyB8ICdvYmplY3QnID0gJ29iamVjdCc7XG5cbiAgQElucHV0KCAnc2VhcmNoT25MaXN0JyApIHNlYXJjaE9uTGlzdCA9IGZhbHNlO1xuXG4gIEBPdXRwdXQoICdzZWxlY3RJdGVtJyApIHNlbGVjdEl0ZW06IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBWaWV3Q2hpbGQoICdpbnB1dCcsIHtzdGF0aWM6IHRydWV9ICApIGlucHV0OiBFbGVtZW50UmVmO1xuXG4gIHB1YmxpYyB0eXBlT2ZEYXRhID0gJ2NvbXBsZXgnO1xuXG4gIHB1YmxpYyBzZWxlY3RlZERlc2NyaXB0aW9uID0gJyc7XG5cbiAgcHVibGljIF9kYXRhO1xuXG4gIHB1YmxpYyBpbmRleE9wdGlvblNlbGVjdGVkTW9kZWw7XG5cbiAgcHVibGljIG9wdGlvblNlbGVjdGVkO1xuXG4gIHB1YmxpYyBpc09wZW4gPSBmYWxzZTtcblxuICBwdWJsaWMgZGF0YXNvdXJjZSA9IFtdO1xuXG4gIHB1YmxpYyBpc0xvYWRpbmcgPSB0cnVlO1xuXG4gIGNvbnN0cnVjdG9yKCBAT3B0aW9uYWwoKSBASW5qZWN0KCBEUk9QRE9XTl9DT05GSUcgKSBkcm9wZG93bkNvbmZpZzogRHJvcGRvd25Db25maWcsXG4gICAgcHJpdmF0ZSBjaGFuZ2VzOiBDaGFuZ2VEZXRlY3RvclJlZiwgQE9wdGlvbmFsKCkgQFNlbGYoKSBwdWJsaWMgbmdDb250cm9sOiBOZ0NvbnRyb2wgKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLnNldENvbnRyb2woKTtcbiAgICB0aGlzLnNldE9wdGlvbnMoIGRyb3Bkb3duQ29uZmlnICk7XG4gIH1cblxuICBnZXQgY29udHJvbCgpIHtcbiAgICByZXR1cm4gdGhpcy5uZ0NvbnRyb2w/LmNvbnRyb2w7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmxpc3Rlbk1vZGVsQ2hhbmdlKCk7XG4gICAgdGhpcy5nZXRNb2RlbFZhbHVlKCk7XG4gIH1cblxuICBzZXRDb250cm9sKCkge1xuICAgIGlmICggdGhpcy5uZ0NvbnRyb2wgKSB7XG4gICAgICB0aGlzLm5nQ29udHJvbC52YWx1ZUFjY2Vzc29yID0gdGhpcztcbiAgICB9XG4gIH1cblxuICBvblNlYXJjaCggc2VhcmNoVGV4dFZhbHVlICkge1xuICAgIGNvbnN0IGZpbHRlciA9IFtdO1xuICAgIHRoaXMuZGF0YXNvdXJjZSA9IHRoaXMuZGF0YS5zbGljZSgpO1xuICAgIHRoaXMuZGF0YXNvdXJjZS5maWx0ZXIoICggaXRlbSApID0+IHtcbiAgICAgIGlmICggdGhpcy5nZXRJdGVtVGV4dCggaXRlbSApLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoc2VhcmNoVGV4dFZhbHVlLnRvTG93ZXJDYXNlKCkpICkge1xuICAgICAgICBmaWx0ZXIucHVzaCggaXRlbSApO1xuICAgICAgfVxuICAgIH0gKTtcbiAgICB0aGlzLmRhdGFzb3VyY2UgPSBmaWx0ZXI7XG4gIH1cblxuICBnZXRJdGVtVGV4dCggaXRlbSApIHtcbiAgICBpZiAoIHRoaXMudHlwZU9mRGF0YSA9PT0gJ3NpbXBsZScgKSB7XG4gICAgICByZXR1cm4gaXRlbTtcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdFBhdGguZ2V0KCBpdGVtLCB0aGlzLmtleVRleHQgKTtcbiAgfVxuXG4gIG9uS2V5RG93biggJGV2ZW50ICkge1xuICAgIHRoaXMuaGFuZGxlU2VsZWN0SW5MZXR0ZXIoICRldmVudC5rZXkgKTtcbiAgICBjb25zdCBrZXlFdmVudCA9IHtcbiAgICAgIFtLZXlFdmVudC5TUEFDRV06ICgpID0+IHRoaXMuaGFuZGxlT3Blbkxpc3QoICRldmVudCApLFxuICAgICAgW0tleUV2ZW50LkFSUk9XRE9XTl06ICgpID0+IHRoaXMuc3RvcEV2ZW50KCAkZXZlbnQgKSxcbiAgICAgIFtLZXlFdmVudC5BUlJPV1VQXTogKCkgPT4gdGhpcy5zdG9wRXZlbnQoICRldmVudCApLFxuICAgICAgW0tleUV2ZW50LkVTQ0FQRV06ICgpID0+IHRoaXMuaGFuZGxlRXNjYXBlKCAkZXZlbnQgKVxuICAgIH07XG4gICAgaWYgKCBrZXlFdmVudFsgJGV2ZW50LmNvZGUgXSApIHtcbiAgICAgIGtleUV2ZW50WyAkZXZlbnQuY29kZSBdKCk7XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlRXNjYXBlKCAkZXZlbnQgKSB7XG4gICAgaWYgKCB0aGlzLmlzT3BlbiApIHtcbiAgICAgIHRoaXMuaXNPcGVuID0gZmFsc2U7XG4gICAgICB0aGlzLnN0b3BFdmVudCggJGV2ZW50ICk7XG4gICAgfVxuICB9XG5cbiAgZ2V0TmF0aXZlSW5wdXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW5wdXQubmF0aXZlRWxlbWVudDtcbiAgfVxuXG5cbiAgb25GaW5kQnlMZXR0ZXIoIHZhbHVlOiBzdHJpbmcgKSB7XG4gICAgdGhpcy5oYW5kbGVTZWxlY3RJbkxldHRlciggdmFsdWUgKTtcbiAgfVxuXG4gIG9uU2VsZWN0T3B0aW9uKCAkZXZlbnQ6IExpc3RJdGVtSW50ZXJmYWNlICkge1xuICAgIHRoaXMuaXNPcGVuID0gZmFsc2U7XG4gICAgdGhpcy5vcHRpb25TZWxlY3RlZCA9ICRldmVudDtcbiAgICB0aGlzLnNlbGVjdGVkRGVzY3JpcHRpb24gPSB0aGlzLmlzU2ltcGxlRGF0YSgpID8gJGV2ZW50Lm9wdGlvbi5pdGVtIDogb2JqZWN0UGF0aC5nZXQoICRldmVudC5vcHRpb24uaXRlbSwgdGhpcy5rZXlUZXh0ICk7XG4gICAgdGhpcy5zZWxlY3RJdGVtLmVtaXQoICRldmVudC5vcHRpb24uaXRlbSApO1xuICAgIHRoaXMuaGFuZGxlS2V5TW9kZWxWYWx1ZSggJGV2ZW50Lm9wdGlvbi5pdGVtICk7XG4gICAgdGhpcy5zZXRJbnB1dEZvY3VzKCk7XG4gIH1cblxuICBvbkRlZmF1bHRPcHRpb24oKSB7XG4gICAgdGhpcy52YWx1ZSA9ICcnO1xuICAgIHRoaXMuc2VsZWN0ZWREZXNjcmlwdGlvbiA9IHRoaXMucGxhY2Vob2xkZXI7XG4gICAgdGhpcy5vcHRpb25TZWxlY3RlZCA9IG51bGw7XG4gICAgdGhpcy5pc09wZW4gPSBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgaXNNb2RlbE1vZGVTdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMubW9kZWxNb2RlID09PSAnc3RyaW5nJztcbiAgfVxuXG4gIHB1YmxpYyBoYW5kbGVPcGVuTGlzdCggJGV2ZW50ICkge1xuICAgIHRoaXMuc3RvcEV2ZW50KCAkZXZlbnQgKTtcbiAgICBpZiAoICF0aGlzLmlzT3BlbiAmJiAhdGhpcy5kaXNhYmxlZCAmJiAhdGhpcy5pc0xvYWRpbmcgKSB7XG4gICAgICB0aGlzLmlzT3BlbiA9IHRydWU7XG4gICAgICB0aGlzLnNldFVwQ29tcG9uZW50KCk7XG4gICAgfVxuICB9XG5cbiAgb25CYWNrZHJvcENsaWNrKCkge1xuICAgIHRoaXMuaXNPcGVuID0gZmFsc2U7XG4gICAgdGhpcy5jaGFuZ2VzLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIHByaXZhdGUgaW5pdGlhbGl6ZUNvbXBvbmVudCgpIHtcbiAgICB0aGlzLnNldFVwQ29tcG9uZW50KCk7XG4gICAgdGhpcy52YWxpZGF0ZURhdGEoKTtcbiAgICB0aGlzLmdldE1vZGVsVmFsdWUoKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0VXBDb21wb25lbnQoKSB7XG4gICAgdGhpcy5kYXRhc291cmNlID0gdGhpcy5kYXRhO1xuICAgIGlmICggdGhpcy5kYXRhLmxlbmd0aCA+IDAgKSB7XG4gICAgICB0aGlzLmlzTG9hZGluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVEYXRhKCkge1xuICAgIGNvbnN0IGtleSA9IE9iamVjdC5rZXlzKCB0aGlzLmRhdGEgKVsgMCBdO1xuICAgIGlmICggdHlwZW9mIHRoaXMuZGF0YVsga2V5IF0gPT09ICdzdHJpbmcnICkge1xuICAgICAgdGhpcy50eXBlT2ZEYXRhID0gJ3NpbXBsZSc7XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlQ2xvc2VEcm9wZG93bigpIHtcbiAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xuICAgIHRoaXMuc2V0SW5wdXRGb2N1cygpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRJbnB1dEZvY3VzKCkge1xuICAgIHRoaXMuaW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1NpbXBsZURhdGEoKSB7XG4gICAgcmV0dXJuIHRoaXMudHlwZU9mRGF0YSA9PT0gJ3NpbXBsZSc7XG4gIH1cblxuICBwcml2YXRlIGxpc3Rlbk1vZGVsQ2hhbmdlKCkge1xuICAgIGlmICggdGhpcy5jb250cm9sICkge1xuICAgICAgdGhpcy5jb250cm9sLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoICgpID0+IHtcbiAgICAgICAgdGhpcy5nZXRNb2RlbFZhbHVlKCk7XG4gICAgICB9ICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVLZXlNb2RlbFZhbHVlKCBpdGVtVmFsdWUgKSB7XG4gICAgaWYgKCB0aGlzLmlzU2ltcGxlRGF0YSgpICkge1xuICAgICAgcmV0dXJuIHRoaXMudmFsdWUgPSBpdGVtVmFsdWU7XG4gICAgfVxuICAgIGlmICggIXRoaXMua2V5VmFsdWUgKSB7XG4gICAgICByZXR1cm4gdGhpcy52YWx1ZSA9IGl0ZW1WYWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmFsdWUgPSBvYmplY3RQYXRoLmdldCggaXRlbVZhbHVlLCB0aGlzLmtleVZhbHVlICk7XG4gIH1cblxuICBwcml2YXRlIGdldE1vZGVsVmFsdWUoKSB7XG4gICAgaWYgKCAhdGhpcy5jb250cm9sICkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmRhdGFzb3VyY2UuZm9yRWFjaCggKCB2YWx1ZSwgaW5kZXggKSA9PiB7XG4gICAgICBpZiAoIHRoaXMuY29udHJvbC52YWx1ZSApIHtcbiAgICAgICAgaWYgKCB0aGlzLmdldENvbXBhcmUoIHZhbHVlICkgPT09IHRoaXMuZ2V0Q29tcGFyZU1vZGVsKCkgKSB7XG4gICAgICAgICAgdGhpcy5zZWxlY3RlZERlc2NyaXB0aW9uID0gdGhpcy5nZXREZXNjcmlwdGlvbiggdmFsdWUgKTtcbiAgICAgICAgICB0aGlzLmluZGV4T3B0aW9uU2VsZWN0ZWRNb2RlbCA9IGluZGV4O1xuICAgICAgICAgIHRoaXMuY2hhbmdlcy5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgICAgdGhpcy5oYW5kbGVLZXlNb2RlbFZhbHVlKCB2YWx1ZSApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0T3B0aW9ucyggb3B0aW9uczogRHJvcGRvd25Db25maWcgKSB7XG4gICAgaWYgKCBvcHRpb25zICkge1xuICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICBPYmplY3Qua2V5cyggb3B0aW9ucyApLmZvckVhY2goIGZ1bmN0aW9uICgga2V5ICkge1xuICAgICAgICBzZWxmWyBrZXkgXSA9IG9wdGlvbnNbIGtleSBdO1xuICAgICAgfSApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q29tcGFyZU1vZGVsKCkge1xuICAgIGlmICggdGhpcy5pc1NpbXBsZURhdGEoKSApIHtcbiAgICAgIHJldHVybiB0aGlzLmNvbnRyb2wudmFsdWU7XG4gICAgfVxuICAgIGlmICggIXRoaXMua2V5VmFsdWUgKSB7XG4gICAgICByZXR1cm4gb2JqZWN0UGF0aC5nZXQoIHRoaXMuY29udHJvbC52YWx1ZSwgdGhpcy5pZGVudGlmaWVyICk7XG4gICAgfVxuICAgIGlmICggdGhpcy5pc01vZGVsTW9kZVN0cmluZygpICkge1xuICAgICAgcmV0dXJuIHRoaXMuY29udHJvbC52YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdFBhdGguZ2V0KCB0aGlzLmNvbnRyb2wudmFsdWUsIHRoaXMua2V5VmFsdWUgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q29tcGFyZSggdmFsdWUgKSB7XG4gICAgaWYgKCB0aGlzLmlzU2ltcGxlRGF0YSgpICkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICBpZiAoICF0aGlzLmtleVZhbHVlICkge1xuICAgICAgcmV0dXJuIG9iamVjdFBhdGguZ2V0KCB2YWx1ZSwgdGhpcy5pZGVudGlmaWVyICk7XG4gICAgfVxuICAgIHJldHVybiBvYmplY3RQYXRoLmdldCggdmFsdWUsIHRoaXMua2V5VmFsdWUgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RGVzY3JpcHRpb24oIHZhbHVlICkge1xuICAgIGlmICggdGhpcy5pc1NpbXBsZURhdGEoKSApIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdFBhdGguZ2V0KCB2YWx1ZSwgdGhpcy5rZXlUZXh0ICk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVNlbGVjdEluTGV0dGVyKCBrZXlJbnB1dDogc3RyaW5nICkge1xuICAgIGNvbnN0IHNlbGVjdGVkID0gdGhpcy5zZWxlY3RCeUZpcnN0KCBrZXlJbnB1dCApO1xuICAgIGlmICggc2VsZWN0ZWQgKSB7XG4gICAgICB0aGlzLnNlbGVjdGVkRGVzY3JpcHRpb24gPSB0aGlzLmdldERlc2NyaXB0aW9uKCBzZWxlY3RlZC5vcHRpb24gKTtcbiAgICAgIHRoaXMub3B0aW9uU2VsZWN0ZWQgPSB7IG9wdGlvbjogc2VsZWN0ZWQub3B0aW9uLCBpbmRleDogc2VsZWN0ZWQuaW5kZXggfTtcbiAgICAgIHRoaXMuaGFuZGxlS2V5TW9kZWxWYWx1ZSggc2VsZWN0ZWQub3B0aW9uICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdG9wRXZlbnQoICRldmVudCApIHtcbiAgICAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gIH1cblxuICBwcml2YXRlIHNlbGVjdEJ5Rmlyc3QoIGtleUlucHV0OiBzdHJpbmcgKTogTGlzdEl0ZW1JbnRlcmZhY2Uge1xuICAgIGxldCBzZWxlY3RlZDogTGlzdEl0ZW1JbnRlcmZhY2UgPSBudWxsO1xuICAgIHRoaXMuZGF0YXNvdXJjZS5mb3JFYWNoKCAoIG9wdGlvbjogVGxMaXN0SXRlbSwgaW5kZXg6IG51bWJlciApID0+IHtcbiAgICAgIGlmICggdGhpcy5nZXRGaXJzdExldHRlck9mSXRlbSggb3B0aW9uICkgPT09IHRoaXMuZ2V0S2V5SW5wdXRMb3dlckNhc2UoIGtleUlucHV0ICkgKSB7XG4gICAgICAgIHNlbGVjdGVkID0gPExpc3RJdGVtSW50ZXJmYWNlPnsgb3B0aW9uLCBpbmRleCB9O1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSApO1xuICAgIHJldHVybiBzZWxlY3RlZDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0S2V5SW5wdXRMb3dlckNhc2UoIGtleUlucHV0OiBzdHJpbmcgKTogc3RyaW5nIHtcbiAgICByZXR1cm4gU3RyaW5nKCBrZXlJbnB1dCApLnRvTG93ZXJDYXNlKCk7XG4gIH1cblxuICBwcml2YXRlIGdldEZpcnN0TGV0dGVyT2ZJdGVtKCBpdGVtICk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFN0cmluZyggb2JqZWN0UGF0aC5nZXQoIGl0ZW0sIHRoaXMua2V5VGV4dCApICkuc3Vic3RyaW5nKCAwLCAxICkudG9Mb3dlckNhc2UoKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKCB7IGRhdGEgfTogU2ltcGxlQ2hhbmdlcyApIHtcbiAgICBpZiAoIGRhdGEgKSB7XG4gICAgICBpZiAoIWRhdGEuZmlyc3RDaGFuZ2UgJiYgZGF0YS5jdXJyZW50VmFsdWUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRoaXMuaXNMb2FkaW5nID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwidWktZHJvcGRvd24tYm94XCIgIFtuZ1N0eWxlXT1cInsnbGluZS1oZWlnaHQnIDogaXRlbUhlaWdodCwgJ3dpZHRoJzogd2lkdGh9XCI+XG5cbiAgPGRpdiBjbGFzcz1cInVpLWxvYWRpbmctaWNvblwiIFtzdHlsZS5oZWlnaHRdPVwiaXRlbUhlaWdodFwiICpuZ0lmPVwiaXNMb2FkaW5nXCI+XG4gICAgPHRsLWxvYWRlcj48L3RsLWxvYWRlcj5cbiAgPC9kaXY+XG5cbiAgPHRsLWxhYmVsICpuZ0lmPVwibGFiZWxcIlxuICAgICAgICAgICAgW2xhYmVsUGxhY2VtZW50XT1cImxhYmVsUGxhY2VtZW50XCJcbiAgICAgICAgICAgIFtsYWJlbFNpemVdPVwibGFiZWxTaXplXCJcbiAgICAgICAgICAgIFtsYWJlbFRpdGxlXT1cImxhYmVsXCI+XG4gIDwvdGwtbGFiZWw+XG5cbiAgPGRpdiBjbGFzcz1cInVpLWRyb3Bkb3duLXdyYXBwZXJcIj5cbiAgPGlucHV0IGNka092ZXJsYXlPcmlnaW5cbiAgICAgICAgICNpbnB1dFxuICAgICAgICAgcmVhZG9ubHlcbiAgICAgICAgICN0cmlnZ2VyPVwiY2RrT3ZlcmxheU9yaWdpblwiXG4gICAgICAgICBbYXR0ci5kaXNhYmxlZF09XCJkaXNhYmxlZCA/IHRydWUgOiBudWxsXCJcbiAgICAgICAgIChrZXlkb3duKT1cIm9uS2V5RG93bigkZXZlbnQpXCJcbiAgICAgICAgIChjbGljayk9XCJoYW5kbGVPcGVuTGlzdCgkZXZlbnQpXCJcbiAgICAgICAgIHZhbHVlPVwie3sgc2VsZWN0ZWREZXNjcmlwdGlvbiA/IHNlbGVjdGVkRGVzY3JpcHRpb24gOiBwbGFjZWhvbGRlciB9fVwiXG4gICAgICAgICBbbmdDbGFzc109XCJ7ICduZy1pbnZhbGlkJyA6IGNvbnRyb2w/LmludmFsaWQsICdkaXNhYmxlZCc6IGRpc2FibGVkIH1cIlxuICAgICAgICAgW25nU3R5bGVdPVwieydoZWlnaHQnIDogaXRlbUhlaWdodCwgJ2xpbmUtaGVpZ2h0JyA6IGl0ZW1IZWlnaHR9XCJcbiAgICAgICAgIGNsYXNzPVwidWktZHJvcGRvd25cIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInVpLWRyb3Bkb3duLWljb25cIlxuICAgICAgICAgICAgIFtzdHlsZS5oZWlnaHRdPVwiaXRlbUhlaWdodFwiXG4gICAgICAgICAgICAgW3N0eWxlLnRyYW5zZm9ybV09XCJpc09wZW4gPyAncm90YXRlKDE4MGRlZyknIDogJ3JvdGF0ZSgwKSdcIlxuICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsgJ2Rpc2FibGVkJzogZGlzYWJsZWQsICduZy1pbnZhbGlkJyA6IGNvbnRyb2w/LmludmFsaWQgfVwiPlxuICAgICAgICAgIDx0bC1pY29uIF