ng2-tree
Version:
angular2 component for visualizing data that can be naturally represented as a tree
399 lines (383 loc) • 49.8 kB
JavaScript
import { Component, Input, ViewChild } from '@angular/core';
import { Ng2TreeSettings } from './tree.types';
import { Tree } from './tree';
import { TreeController } from './tree-controller';
import { NodeMenuItemAction } from './menu/menu.events';
import { NodeEditableEventAction } from './editable/editable.events';
import * as EventUtils from './utils/event.utils';
import { get, isNil } from './utils/fn.utils';
import { merge } from 'rxjs';
import { filter } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "./menu/node-menu.service";
import * as i2 from "./tree.service";
import * as i3 from "@angular/common";
import * as i4 from "./draggable/node-draggable.directive";
import * as i5 from "./editable/node-editable.directive";
import * as i6 from "./menu/node-menu.component";
import * as i7 from "./utils/safe-html.pipe";
export class TreeInternalComponent {
nodeMenuService;
treeService;
nodeElementRef;
tree;
settings;
template;
isSelected = false;
isRightMenuVisible = false;
isLeftMenuVisible = false;
isReadOnly = false;
controller;
checkboxElementRef;
subscriptions = [];
constructor(nodeMenuService, treeService, nodeElementRef) {
this.nodeMenuService = nodeMenuService;
this.treeService = treeService;
this.nodeElementRef = nodeElementRef;
}
ngAfterViewInit() {
if (this.tree.checked && !this.tree.firstCheckedFired) {
this.tree.firstCheckedFired = true;
this.treeService.fireNodeChecked(this.tree);
}
}
ngOnInit() {
const nodeId = get(this.tree, 'node.id', '');
if (nodeId) {
this.controller = new TreeController(this);
this.treeService.setController(nodeId, this.controller);
}
this.settings = this.settings || new Ng2TreeSettings();
this.isReadOnly = !get(this.settings, 'enableCheckboxes', true);
if (this.tree.isRoot() && this.settings.rootIsVisible === false) {
this.tree.disableCollapseOnInit();
}
this.subscriptions.push(this.nodeMenuService.hideMenuStream(this.nodeElementRef).subscribe(() => {
this.isRightMenuVisible = false;
this.isLeftMenuVisible = false;
}));
this.subscriptions.push(this.treeService.unselectStream(this.tree).subscribe(() => (this.isSelected = false)));
this.subscriptions.push(this.treeService.draggedStream(this.tree, this.nodeElementRef).subscribe((e) => {
if (this.tree.hasSibling(e.captured.tree)) {
this.swapWithSibling(e.captured.tree, this.tree);
}
else if (this.tree.isBranch()) {
this.moveNodeToThisTreeAndRemoveFromPreviousOne(e, this.tree);
}
else {
this.moveNodeToParentTreeAndRemoveFromPreviousOne(e, this.tree);
}
}));
this.subscriptions.push(merge(this.treeService.nodeChecked$, this.treeService.nodeUnchecked$)
.pipe(filter((e) => this.eventContainsId(e) && this.tree.hasChild(e.node)))
.subscribe((e) => this.updateCheckboxState()));
}
ngOnChanges(changes) {
this.controller = new TreeController(this);
}
ngOnDestroy() {
if (get(this.tree, 'node.id', '')) {
this.treeService.deleteController(this.tree.node.id);
}
this.subscriptions.forEach(sub => sub && sub.unsubscribe());
}
swapWithSibling(sibling, tree) {
tree.swapWithSibling(sibling);
this.treeService.fireNodeMoved(sibling, sibling.parent);
}
moveNodeToThisTreeAndRemoveFromPreviousOne(e, tree) {
this.treeService.fireNodeRemoved(e.captured.tree);
const addedChild = tree.addChild(e.captured.tree);
this.treeService.fireNodeMoved(addedChild, e.captured.tree.parent);
}
moveNodeToParentTreeAndRemoveFromPreviousOne(e, tree) {
this.treeService.fireNodeRemoved(e.captured.tree);
const addedSibling = tree.addSibling(e.captured.tree, tree.positionInParent);
this.treeService.fireNodeMoved(addedSibling, e.captured.tree.parent);
}
onNodeSelected(e) {
if (!this.tree.selectionAllowed) {
return;
}
if (EventUtils.isLeftButtonClicked(e)) {
this.isSelected = true;
this.treeService.fireNodeSelected(this.tree);
}
}
onNodeUnselected(e) {
if (!this.tree.selectionAllowed) {
return;
}
if (EventUtils.isLeftButtonClicked(e)) {
this.isSelected = false;
this.treeService.fireNodeUnselected(this.tree);
}
}
showRightMenu(e) {
if (!this.tree.hasRightMenu()) {
return;
}
if (EventUtils.isRightButtonClicked(e)) {
this.isRightMenuVisible = !this.isRightMenuVisible;
this.nodeMenuService.hideMenuForAllNodesExcept(this.nodeElementRef);
}
e.preventDefault();
}
showLeftMenu(e) {
if (!this.tree.hasLeftMenu()) {
return;
}
if (EventUtils.isLeftButtonClicked(e)) {
this.isLeftMenuVisible = !this.isLeftMenuVisible;
this.nodeMenuService.hideMenuForAllNodesExcept(this.nodeElementRef);
if (this.isLeftMenuVisible) {
e.preventDefault();
}
}
}
onMenuItemSelected(e) {
switch (e.nodeMenuItemAction) {
case NodeMenuItemAction.NewTag:
this.onNewSelected(e);
break;
case NodeMenuItemAction.NewFolder:
this.onNewSelected(e);
break;
case NodeMenuItemAction.Rename:
this.onRenameSelected();
break;
case NodeMenuItemAction.Remove:
this.onRemoveSelected();
break;
case NodeMenuItemAction.Custom:
this.onCustomSelected();
this.treeService.fireMenuItemSelected(this.tree, e.nodeMenuItemSelected);
break;
default:
throw new Error(`Chosen menu item doesn't exist`);
}
}
onNewSelected(e) {
this.tree.createNode(e.nodeMenuItemAction === NodeMenuItemAction.NewFolder);
this.isRightMenuVisible = false;
this.isLeftMenuVisible = false;
}
onRenameSelected() {
this.tree.markAsBeingRenamed();
this.isRightMenuVisible = false;
this.isLeftMenuVisible = false;
}
onRemoveSelected() {
this.treeService.deleteController(get(this.tree, 'node.id', ''));
this.treeService.fireNodeRemoved(this.tree);
}
onCustomSelected() {
this.isRightMenuVisible = false;
this.isLeftMenuVisible = false;
}
onSwitchFoldingType() {
this.tree.switchFoldingType();
this.treeService.fireNodeSwitchFoldingType(this.tree);
}
applyNewValue(e) {
if ((e.action === NodeEditableEventAction.Cancel || this.tree.isNew()) && Tree.isValueEmpty(e.value)) {
return this.treeService.fireNodeRemoved(this.tree);
}
if (this.tree.isNew()) {
this.tree.value = e.value;
this.treeService.fireNodeCreated(this.tree);
}
if (this.tree.isBeingRenamed()) {
const oldValue = this.tree.value;
this.tree.value = e.value;
this.treeService.fireNodeRenamed(oldValue, this.tree);
}
this.tree.markAsModified();
}
shouldShowInputForTreeValue() {
return this.tree.isNew() || this.tree.isBeingRenamed();
}
isRootHidden() {
return this.tree.isRoot() && !this.settings.rootIsVisible;
}
hasCustomMenu() {
return this.tree.hasCustomMenu();
}
switchNodeCheckStatus() {
if (!this.tree.checked) {
this.onNodeChecked();
}
else {
this.onNodeUnchecked();
}
}
onNodeChecked() {
if (!this.checkboxElementRef) {
return;
}
this.checkboxElementRef.nativeElement.indeterminate = false;
this.treeService.fireNodeChecked(this.tree);
this.executeOnChildController(controller => controller.check());
this.tree.checked = true;
}
onNodeUnchecked() {
if (!this.checkboxElementRef) {
return;
}
this.checkboxElementRef.nativeElement.indeterminate = false;
this.treeService.fireNodeUnchecked(this.tree);
this.executeOnChildController(controller => controller.uncheck());
this.tree.checked = false;
}
executeOnChildController(executor) {
if (this.tree.hasLoadedChildern()) {
this.tree.children.forEach((child) => {
const controller = this.treeService.getController(child.id);
if (!isNil(controller)) {
executor(controller);
}
});
}
}
updateCheckboxState() {
// Calling setTimeout so the value of isChecked will be updated and after that I'll check the children status.
setTimeout(() => {
const checkedChildrenAmount = this.tree.checkedChildrenAmount();
if (checkedChildrenAmount === 0) {
this.checkboxElementRef.nativeElement.indeterminate = false;
this.tree.checked = false;
this.treeService.fireNodeUnchecked(this.tree);
}
else if (checkedChildrenAmount === this.tree.loadedChildrenAmount()) {
this.checkboxElementRef.nativeElement.indeterminate = false;
this.tree.checked = true;
this.treeService.fireNodeChecked(this.tree);
}
else {
this.tree.checked = false;
this.checkboxElementRef.nativeElement.indeterminate = true;
this.treeService.fireNodeIndetermined(this.tree);
}
});
}
eventContainsId(event) {
if (!event.node.id) {
console.warn('"Node with checkbox" feature requires a unique id assigned to every node, please consider to add it.');
return false;
}
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TreeInternalComponent, deps: [{ token: i1.NodeMenuService }, { token: i2.TreeService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TreeInternalComponent, selector: "tree-internal", inputs: { tree: "tree", settings: "settings", template: "template" }, viewQueries: [{ propertyName: "checkboxElementRef", first: true, predicate: ["checkbox"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
<ul class="tree" *ngIf="tree" [ngClass]="{rootless: isRootHidden()}">
<li>
<div class="value-container"
[ngClass]="{rootless: isRootHidden()}"
[class.selected]="isSelected"
(contextmenu)="showRightMenu($event)"
[nodeDraggable]="nodeElementRef"
[tree]="tree">
<div class="folding" (click)="onSwitchFoldingType()" [ngClass]="tree.foldingCssClass"></div>
<div class="node-checkbox" *ngIf="settings.showCheckboxes">
<input checkbox type="checkbox" [disabled]="isReadOnly" [checked]="this.tree.checked" (change)="switchNodeCheckStatus()" #checkbox />
</div>
<div class="node-value"
*ngIf="!shouldShowInputForTreeValue()"
[class.node-selected]="isSelected"
(click)="onNodeSelected($event)">
<div *ngIf="tree.nodeTemplate" class="node-template" [innerHTML]="tree.nodeTemplate | safeHtml"></div>
<span *ngIf="!template" class="node-name" [innerHTML]="tree.value | safeHtml"></span>
<span class="loading-children" *ngIf="tree.childrenAreBeingLoaded()"></span>
<ng-template [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ $implicit: tree.node }"></ng-template>
</div>
<input type="text" class="node-value"
*ngIf="shouldShowInputForTreeValue()"
[nodeEditable]="tree.value"
(valueChanged)="applyNewValue($event)"/>
<div class="node-left-menu" *ngIf="tree.hasLeftMenu()" (click)="showLeftMenu($event)" [innerHTML]="tree.leftMenuTemplate">
</div>
<node-menu *ngIf="tree.hasLeftMenu() && isLeftMenuVisible && !hasCustomMenu()"
(menuItemSelected)="onMenuItemSelected($event)">
</node-menu>
</div>
<node-menu *ngIf="isRightMenuVisible && !hasCustomMenu()"
(menuItemSelected)="onMenuItemSelected($event)">
</node-menu>
<node-menu *ngIf="hasCustomMenu() && (isRightMenuVisible || isLeftMenuVisible)"
[menuItems]="tree.menuItems"
(menuItemSelected)="onMenuItemSelected($event)">
</node-menu>
<div *ngIf="tree.keepNodesInDOM()" [ngStyle]="{'display': tree.isNodeExpanded() ? 'block' : 'none'}">
<tree-internal *ngFor="let child of tree.childrenAsync | async" [tree]="child" [template]="template" [settings]="settings"></tree-internal>
</div>
<ng-template [ngIf]="tree.isNodeExpanded() && !tree.keepNodesInDOM()">
<tree-internal *ngFor="let child of tree.childrenAsync | async" [tree]="child" [template]="template" [settings]="settings"></tree-internal>
</ng-template>
</li>
</ul>
`, isInline: true, dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i4.NodeDraggableDirective, selector: "[nodeDraggable]", inputs: ["nodeDraggable", "tree"] }, { kind: "directive", type: i5.NodeEditableDirective, selector: "[nodeEditable]", inputs: ["nodeEditable"], outputs: ["valueChanged"] }, { kind: "component", type: i6.NodeMenuComponent, selector: "node-menu", inputs: ["menuItems"], outputs: ["menuItemSelected"] }, { kind: "component", type: TreeInternalComponent, selector: "tree-internal", inputs: ["tree", "settings", "template"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i7.SafeHtmlPipe, name: "safeHtml" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TreeInternalComponent, decorators: [{
type: Component,
args: [{
selector: 'tree-internal',
template: `
<ul class="tree" *ngIf="tree" [ngClass]="{rootless: isRootHidden()}">
<li>
<div class="value-container"
[ngClass]="{rootless: isRootHidden()}"
[class.selected]="isSelected"
(contextmenu)="showRightMenu($event)"
[nodeDraggable]="nodeElementRef"
[tree]="tree">
<div class="folding" (click)="onSwitchFoldingType()" [ngClass]="tree.foldingCssClass"></div>
<div class="node-checkbox" *ngIf="settings.showCheckboxes">
<input checkbox type="checkbox" [disabled]="isReadOnly" [checked]="this.tree.checked" (change)="switchNodeCheckStatus()" #checkbox />
</div>
<div class="node-value"
*ngIf="!shouldShowInputForTreeValue()"
[class.node-selected]="isSelected"
(click)="onNodeSelected($event)">
<div *ngIf="tree.nodeTemplate" class="node-template" [innerHTML]="tree.nodeTemplate | safeHtml"></div>
<span *ngIf="!template" class="node-name" [innerHTML]="tree.value | safeHtml"></span>
<span class="loading-children" *ngIf="tree.childrenAreBeingLoaded()"></span>
<ng-template [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ $implicit: tree.node }"></ng-template>
</div>
<input type="text" class="node-value"
*ngIf="shouldShowInputForTreeValue()"
[nodeEditable]="tree.value"
(valueChanged)="applyNewValue($event)"/>
<div class="node-left-menu" *ngIf="tree.hasLeftMenu()" (click)="showLeftMenu($event)" [innerHTML]="tree.leftMenuTemplate">
</div>
<node-menu *ngIf="tree.hasLeftMenu() && isLeftMenuVisible && !hasCustomMenu()"
(menuItemSelected)="onMenuItemSelected($event)">
</node-menu>
</div>
<node-menu *ngIf="isRightMenuVisible && !hasCustomMenu()"
(menuItemSelected)="onMenuItemSelected($event)">
</node-menu>
<node-menu *ngIf="hasCustomMenu() && (isRightMenuVisible || isLeftMenuVisible)"
[menuItems]="tree.menuItems"
(menuItemSelected)="onMenuItemSelected($event)">
</node-menu>
<div *ngIf="tree.keepNodesInDOM()" [ngStyle]="{'display': tree.isNodeExpanded() ? 'block' : 'none'}">
<tree-internal *ngFor="let child of tree.childrenAsync | async" [tree]="child" [template]="template" [settings]="settings"></tree-internal>
</div>
<ng-template [ngIf]="tree.isNodeExpanded() && !tree.keepNodesInDOM()">
<tree-internal *ngFor="let child of tree.childrenAsync | async" [tree]="child" [template]="template" [settings]="settings"></tree-internal>
</ng-template>
</li>
</ul>
`
}]
}], ctorParameters: function () { return [{ type: i1.NodeMenuService }, { type: i2.TreeService }, { type: i0.ElementRef }]; }, propDecorators: { tree: [{
type: Input
}], settings: [{
type: Input
}], template: [{
type: Input
}], checkboxElementRef: [{
type: ViewChild,
args: ['checkbox', { static: false }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS1pbnRlcm5hbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHJlZS1pbnRlcm5hbC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVMLFNBQVMsRUFFVCxLQUFLLEVBTUwsU0FBUyxFQUNWLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDL0MsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUM5QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbkQsT0FBTyxFQUFFLGtCQUFrQixFQUE2QixNQUFNLG9CQUFvQixDQUFDO0FBQ25GLE9BQU8sRUFBcUIsdUJBQXVCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUd4RixPQUFPLEtBQUssVUFBVSxNQUFNLHFCQUFxQixDQUFDO0FBRWxELE9BQU8sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFOUMsT0FBTyxFQUFFLEtBQUssRUFBTSxNQUFNLE1BQU0sQ0FBQztBQUNqQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7OztBQTZEeEMsTUFBTSxPQUFPLHFCQUFxQjtJQW1CdEI7SUFDRDtJQUNBO0lBcEJPLElBQUksQ0FBTztJQUVYLFFBQVEsQ0FBNEI7SUFFcEMsUUFBUSxDQUFtQjtJQUVwQyxVQUFVLEdBQUcsS0FBSyxDQUFDO0lBQ25CLGtCQUFrQixHQUFHLEtBQUssQ0FBQztJQUMzQixpQkFBaUIsR0FBRyxLQUFLLENBQUM7SUFDMUIsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUNuQixVQUFVLENBQWlCO0lBRzNCLGtCQUFrQixDQUFhO0lBRTlCLGFBQWEsR0FBbUIsRUFBRSxDQUFDO0lBRTNDLFlBQ1UsZUFBZ0MsRUFDakMsV0FBd0IsRUFDeEIsY0FB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LEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCAqIGFzIFRyZWVUeXBlcyBmcm9tICcuL3RyZWUudHlwZXMnO1xuaW1wb3J0IHsgTmcyVHJlZVNldHRpbmdzIH0gZnJvbSAnLi90cmVlLnR5cGVzJztcbmltcG9ydCB7IFRyZWUgfSBmcm9tICcuL3RyZWUnO1xuaW1wb3J0IHsgVHJlZUNvbnRyb2xsZXIgfSBmcm9tICcuL3RyZWUtY29udHJvbGxlcic7XG5pbXBvcnQgeyBOb2RlTWVudVNlcnZpY2UgfSBmcm9tICcuL21lbnUvbm9kZS1tZW51LnNlcnZpY2UnO1xuaW1wb3J0IHsgTm9kZU1lbnVJdGVtQWN0aW9uLCBOb2RlTWVudUl0ZW1TZWxlY3RlZEV2ZW50IH0gZnJvbSAnLi9tZW51L21lbnUuZXZlbnRzJztcbmltcG9ydCB7IE5vZGVFZGl0YWJsZUV2ZW50LCBOb2RlRWRpdGFibGVFdmVudEFjdGlvbiB9IGZyb20gJy4vZWRpdGFibGUvZWRpdGFibGUuZXZlbnRzJztcbmltcG9ydCB7IE5vZGVDaGVja2VkRXZlbnQsIE5vZGVFdmVudCB9IGZyb20gJy4vdHJlZS5ldmVudHMnO1xuaW1wb3J0IHsgVHJlZVNlcnZpY2UgfSBmcm9tICcuL3RyZWUuc2VydmljZSc7XG5pbXBvcnQgKiBhcyBFdmVudFV0aWxzIGZyb20gJy4vdXRpbHMvZXZlbnQudXRpbHMnO1xuaW1wb3J0IHsgTm9kZURyYWdnYWJsZUV2ZW50IH0gZnJvbSAnLi9kcmFnZ2FibGUvZHJhZ2dhYmxlLmV2ZW50cyc7XG5pbXBvcnQgeyBnZXQsIGlzTmlsIH0gZnJvbSAnLi91dGlscy9mbi51dGlscyc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1lcmdlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlsdGVyIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0cmVlLWludGVybmFsJyxcbiAgdGVtcGxhdGU6IGBcbiAgPHVsIGNsYXNzPVwidHJlZVwiICpuZ0lmPVwidHJlZVwiIFtuZ0NsYXNzXT1cIntyb290bGVzczogaXNSb290SGlkZGVuKCl9XCI+XG4gICAgPGxpPlxuICAgICAgPGRpdiBjbGFzcz1cInZhbHVlLWNvbnRhaW5lclwiXG4gICAgICAgIFtuZ0NsYXNzXT1cIntyb290bGVzczogaXNSb290SGlkZGVuKCl9XCJcbiAgICAgICAgW2NsYXNzLnNlbGVjdGVkXT1cImlzU2VsZWN0ZWRcIlxuICAgICAgICAoY29udGV4dG1lbnUpPVwic2hvd1JpZ2h0TWVudSgkZXZlbnQpXCJcbiAgICAgICAgW25vZGVEcmFnZ2FibGVdPVwibm9kZUVsZW1lbnRSZWZcIlxuICAgICAgICBbdHJlZV09XCJ0cmVlXCI+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZvbGRpbmdcIiAoY2xpY2spPVwib25Td2l0Y2hGb2xkaW5nVHlwZSgpXCIgW25nQ2xhc3NdPVwidHJlZS5mb2xkaW5nQ3NzQ2xhc3NcIj48L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwibm9kZS1jaGVja2JveFwiICpuZ0lmPVwic2V0dGluZ3Muc2hvd0NoZWNrYm94ZXNcIj5cbiAgICAgICAgPGlucHV0IGNoZWNrYm94ICB0eXBlPVwiY2hlY2tib3hcIiBbZGlzYWJsZWRdPVwiaXNSZWFkT25seVwiIFtjaGVja2VkXT1cInRoaXMudHJlZS5jaGVja2VkXCIgKGNoYW5nZSk9XCJzd2l0Y2hOb2RlQ2hlY2tTdGF0dXMoKVwiICNjaGVja2JveCAvPlxuICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm5vZGUtdmFsdWVcIlxuICAgICAgICAgICpuZ0lmPVwiIXNob3VsZFNob3dJbnB1dEZvclRyZWVWYWx1ZSgpXCJcbiAgICAgICAgICBbY2xhc3Mubm9kZS1zZWxlY3RlZF09XCJpc1NlbGVjdGVkXCJcbiAgICAgICAgICAoY2xpY2spPVwib25Ob2RlU2VsZWN0ZWQoJGV2ZW50KVwiPlxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cInRyZWUubm9kZVRlbXBsYXRlXCIgY2xhc3M9XCJub2RlLXRlbXBsYXRlXCIgW2lubmVySFRNTF09XCJ0cmVlLm5vZGVUZW1wbGF0ZSB8IHNhZmVIdG1sXCI+PC9kaXY+XG4gICAgICAgICAgICA8c3BhbiAqbmdJZj1cIiF0ZW1wbGF0ZVwiIGNsYXNzPVwibm9kZS1uYW1lXCIgW2lubmVySFRNTF09XCJ0cmVlLnZhbHVlIHwgc2FmZUh0bWxcIj48L3NwYW4+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImxvYWRpbmctY2hpbGRyZW5cIiAqbmdJZj1cInRyZWUuY2hpbGRyZW5BcmVCZWluZ0xvYWRlZCgpXCI+PC9zcGFuPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInRlbXBsYXRlXCIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiB0cmVlLm5vZGUgfVwiPjwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwibm9kZS12YWx1ZVwiXG4gICAgICAgICAgICpuZ0lmPVwic2hvdWxkU2hvd0lucHV0Rm9yVHJlZVZhbHVlKClcIlxuICAgICAgICAgICBbbm9kZUVkaXRhYmxlXT1cInRyZWUudmFsdWVcIlxuICAgICAgICAgICAodmFsdWVDaGFuZ2VkKT1cImFwcGx5TmV3VmFsdWUoJGV2ZW50KVwiLz5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwibm9kZS1sZWZ0LW1lbnVcIiAqbmdJZj1cInRyZWUuaGFzTGVmdE1lbnUoKVwiIChjbGljayk9XCJzaG93TGVmdE1lbnUoJGV2ZW50KVwiIFtpbm5lckhUTUxdPVwidHJlZS5sZWZ0TWVudVRlbXBsYXRlXCI+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8bm9kZS1tZW51ICpuZ0lmPVwidHJlZS5oYXNMZWZ0TWVudSgpICYmIGlzTGVmdE1lbnVWaXNpYmxlICYmICFoYXNDdXN0b21NZW51KClcIlxuICAgICAgICAgIChtZW51SXRlbVNlbGVjdGVkKT1cIm9uTWVudUl0ZW1TZWxlY3RlZCgkZXZlbnQpXCI+XG4gICAgICAgIDwvbm9kZS1tZW51PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxub2RlLW1lbnUgKm5nSWY9XCJpc1JpZ2h0TWVudVZpc2libGUgJiYgIWhhc0N1c3RvbU1lbnUoKVwiXG4gICAgICAgICAgIChtZW51SXRlbVNlbGVjdGVkKT1cIm9uTWVudUl0ZW1TZWxlY3RlZCgkZXZlbnQpXCI+XG4gICAgICA8L25vZGUtbWVudT5cblxuICAgICAgPG5vZGUtbWVudSAqbmdJZj1cImhhc0N1c3RvbU1lbnUoKSAmJiAoaXNSaWdodE1lbnVWaXNpYmxlIHx8IGlzTGVmdE1lbnVWaXNpYmxlKVwiXG4gICAgICAgICAgIFttZW51SXRlbXNdPVwidHJlZS5tZW51SXRlbXNcIlxuICAgICAgICAgICAobWVudUl0ZW1TZWxlY3RlZCk9XCJvbk1lbnVJdGVtU2VsZWN0ZWQoJGV2ZW50KVwiPlxuICAgICAgPC9ub2RlLW1lbnU+XG5cbiAgICAgIDxkaXYgKm5nSWY9XCJ0cmVlLmtlZXBOb2Rlc0luRE9NKClcIiBbbmdTdHlsZV09XCJ7J2Rpc3BsYXknOiB0cmVlLmlzTm9kZUV4cGFuZGVkKCkgPyAnYmxvY2snIDogJ25vbmUnfVwiPlxuICAgICAgICA8dHJlZS1pbnRlcm5hbCAqbmdGb3I9XCJsZXQgY2hpbGQgb2YgdHJlZS5jaGlsZHJlbkFzeW5jIHwgYXN5bmNcIiBbdHJlZV09XCJjaGlsZFwiIFt0ZW1wbGF0ZV09XCJ0ZW1wbGF0ZVwiIFtzZXR0aW5nc109XCJzZXR0aW5nc1wiPjwvdHJlZS1pbnRlcm5hbD5cbiAgICAgIDwvZGl2PlxuICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cInRyZWUuaXNOb2RlRXhwYW5kZWQoKSAmJiAhdHJlZS5rZWVwTm9kZXNJbkRPTSgpXCI+XG4gICAgICAgIDx0cmVlLWludGVybmFsICpuZ0Zvcj1cImxldCBjaGlsZCBvZiB0cmVlLmNoaWxkcmVuQXN5bmMgfCBhc3luY1wiIFt0cmVlXT1cImNoaWxkXCIgW3RlbXBsYXRlXT1cInRlbXBsYXRlXCIgW3NldHRpbmdzXT1cInNldHRpbmdzXCI+PC90cmVlLWludGVybmFsPlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L2xpPlxuICA8L3VsPlxuICBgXG59KVxuZXhwb3J0IGNsYXNzIFRyZWVJbnRlcm5hbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuICBASW5wdXQoKSBwdWJsaWMgdHJlZTogVHJlZTtcblxuICBASW5wdXQoKSBwdWJsaWMgc2V0dGluZ3M6IFRyZWVUeXBlcy5OZzJUcmVlU2V0dGluZ3M7XG5cbiAgQElucHV0KCkgcHVibGljIHRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIHB1YmxpYyBpc1NlbGVjdGVkID0gZmFsc2U7XG4gIHB1YmxpYyBpc1JpZ2h0TWVudVZpc2libGUgPSBmYWxzZTtcbiAgcHVibGljIGlzTGVmdE1lbnVWaXNpYmxlID0gZmFsc2U7XG4gIHB1YmxpYyBpc1JlYWRPbmx5ID0gZmFsc2U7XG4gIHB1YmxpYyBjb250cm9sbGVyOiBUcmVlQ29udHJvbGxlcjtcblxuICBAVmlld0NoaWxkKCdjaGVja2JveCcsIHsgc3RhdGljOiBmYWxzZSB9KVxuICBwdWJsaWMgY2hlY2tib3hFbGVtZW50UmVmOiBFbGVtZW50UmVmO1xuXG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBub2RlTWVudVNlcnZpY2U6IE5vZGVNZW51U2VydmljZSxcbiAgICBwdWJsaWMgdHJlZVNlcnZpY2U6IFRyZWVTZXJ2aWNlLFxuICAgIHB1YmxpYyBub2RlRWxlbWVudFJlZjogRWxlbWVudFJlZlxuICApIHt9XG5cbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy50cmVlLmNoZWNrZWQgJiYgISh0aGlzLnRyZWUgYXMgYW55KS5maXJzdENoZWNrZWRGaXJlZCkge1xuICAgICAgKHRoaXMudHJlZSBhcyBhbnkpLmZpcnN0Q2hlY2tlZEZpcmVkID0gdHJ1ZTtcbiAgICAgIHRoaXMudHJlZVNlcnZpY2UuZmlyZU5vZGVDaGVja2VkKHRoaXMudHJlZSk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGNvbnN0IG5vZGVJZCA9IGdldCh0aGlzLnRyZWUsICdub2RlLmlkJywgJycpO1xuICAgIGlmIChub2RlSWQpIHtcbiAgICAgIHRoaXMuY29udHJvbGxlciA9IG5ldyBUcmVlQ29udHJvbGxlcih0aGlzKTtcbiAgICAgIHRoaXMudHJlZVNlcnZpY2Uuc2V0Q29udHJvbGxlcihub2RlSWQsIHRoaXMuY29udHJvbGxlcik7XG4gICAgfVxuXG4gICAgdGhpcy5zZXR0aW5ncyA9IHRoaXMuc2V0dGluZ3MgfHwgbmV3IE5nMlRyZWVTZXR0aW5ncygpO1xuICAgIHRoaXMuaXNSZWFkT25seSA9ICFnZXQodGhpcy5zZXR0aW5ncywgJ2VuYWJsZUNoZWNrYm94ZXMnLCB0cnVlKTtcblxuICAgIGlmICh0aGlzLnRyZWUuaXNSb290KCkgJiYgdGhpcy5zZXR0aW5ncy5yb290SXNWaXNpYmxlID09PSBmYWxzZSkge1xuICAgICAgdGhpcy50cmVlLmRpc2FibGVDb2xsYXBzZU9uSW5pdCgpO1xuICAgIH1cblxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgdGhpcy5ub2RlTWVudVNlcnZpY2UuaGlkZU1lbnVTdHJlYW0odGhpcy5ub2RlRWxlbWVudFJlZikuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5pc1JpZ2h0TWVudVZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc0xlZnRNZW51VmlzaWJsZSA9IGZhbHNlO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2godGhpcy50cmVlU2VydmljZS51bnNlbGVjdFN0cmVhbSh0aGlzLnRyZWUpLnN1YnNjcmliZSgoKSA9PiAodGhpcy5pc1NlbGVjdGVkID0gZmFsc2UpKSk7XG5cbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMudHJlZVNlcnZpY2UuZHJhZ2dlZFN0cmVhbSh0aGlzLnRyZWUsIHRoaXMubm9kZUVsZW1lbnRSZWYpLnN1YnNjcmliZSgoZTogTm9kZURyYWdnYWJsZUV2ZW50KSA9PiB7XG4gICAgICAgIGlmICh0aGlzLnRyZWUuaGFzU2libGluZyhlLmNhcHR1cmVkLnRyZWUpKSB7XG4gICAgICAgICAgdGhpcy5zd2FwV2l0aFNpYmxpbmcoZS5jYXB0dXJlZC50cmVlLCB0aGlzLnRyZWUpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMudHJlZS5pc0JyYW5jaCgpKSB7XG4gICAgICAgICAgdGhpcy5tb3ZlTm9kZVRvVGhpc1RyZWVBbmRSZW1vdmVGcm9tUHJldmlvdXNPbmUoZSwgdGhpcy50cmVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLm1vdmVOb2RlVG9QYXJlbnRUcmVlQW5kUmVtb3ZlRnJvbVByZXZpb3VzT25lKGUsIHRoaXMudHJlZSk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgbWVyZ2UodGhpcy50cmVlU2VydmljZS5ub2RlQ2hlY2tlZCQsIHRoaXMudHJlZVNlcnZpY2Uubm9kZVVuY2hlY2tlZCQpXG4gICAgICAgIC5waXBlKGZpbHRlcigoZTogTm9kZUNoZWNrZWRFdmVudCkgPT4gdGhpcy5ldmVudENvbnRhaW5zSWQoZSkgJiYgdGhpcy50cmVlLmhhc0NoaWxkKGUubm9kZSkpKVxuICAgICAgICAuc3Vic2NyaWJlKChlOiBOb2RlQ2hlY2tlZEV2ZW50KSA9PiB0aGlzLnVwZGF0ZUNoZWNrYm94U3RhdGUoKSlcbiAgICApO1xuICB9XG5cbiAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xsZXIgPSBuZXcgVHJlZUNvbnRyb2xsZXIodGhpcyk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgaWYgKGdldCh0aGlzLnRyZWUsICdub2RlLmlkJywgJycpKSB7XG4gICAgICB0aGlzLnRyZWVTZXJ2aWNlLmRlbGV0ZUNvbnRyb2xsZXIodGhpcy50cmVlLm5vZGUuaWQpO1xuICAgIH1cblxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5mb3JFYWNoKHN1YiA9PiBzdWIgJiYgc3ViLnVuc3Vic2NyaWJlKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBzd2FwV2l0aFNpYmxpbmcoc2libGluZzogVHJlZSwgdHJlZTogVHJlZSk6IHZvaWQge1xuICAgIHRyZWUuc3dhcFdpdGhTaWJsaW5nKHNpYmxpbmcpO1xuICAgIHRoaXMudHJlZVNlcnZpY2UuZmlyZU5vZGVNb3ZlZChzaWJsaW5nLCBzaWJsaW5nLnBhcmVudCk7XG4gIH1cblxuICBwcml2YXRlIG1vdmVOb2RlVG9UaGlzVHJlZUFuZFJlbW92ZUZyb21QcmV2aW91c09uZShlOiBOb2RlRHJhZ2dhYmxlRXZlbnQsIHRyZWU6IFRyZWUpOiB2b2lkIHtcbiAgICB0aGlzLnRyZWVTZXJ2aWNlLmZpcmVOb2RlUmVtb3ZlZChlLmNhcHR1cmVkLnRyZWUpO1xuICAgIGNvbnN0IGFkZGVkQ2hpbGQgPSB0cmVlLmFkZENoaWxkKGUuY2FwdHVyZWQudHJlZSk7XG4gICAgdGhpcy50cmVlU2VydmljZS5maXJlTm9kZU1vdmVkKGFkZGVkQ2hpbGQsIGUuY2FwdHVyZWQudHJlZS5wYXJlbnQpO1xuICB9XG5cbiAgcHJpdmF0ZSBtb3ZlTm9kZVRvUGFyZW50VHJlZUFuZFJlbW92ZUZyb21QcmV2aW91c09uZShlOiBOb2RlRHJhZ2dhYmxlRXZlbnQsIHRyZWU6IFRyZWUpOiB2b2lkIHtcbiAgICB0aGlzLnRyZWVTZXJ2aWNlLmZpcmVOb2RlUmVtb3ZlZChlLmNhcHR1cmVkLnRyZWUpO1xuICAgIGNvbnN0IGFkZGVkU2libGluZyA9IHRyZWUuYWRkU2libGluZyhlLmNhcHR1cmVkLnRyZWUsIHRyZWUucG9zaXRpb25JblBhcmVudCk7XG4gICAgdGhpcy50cmVlU2VydmljZS5maXJlTm9kZU1vdmVkKGFkZGVkU2libGluZywgZS5jYXB0dXJlZC50cmVlLnBhcmVudCk7XG4gIH1cblxuICBwdWJsaWMgb25Ob2RlU2VsZWN0ZWQoZTogeyBidXR0b246IG51bWJlciB9KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnRyZWUuc2VsZWN0aW9uQWxsb3dlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChFdmVudFV0aWxzLmlzTGVmdEJ1dHRvbkNsaWNrZWQoZSBhcyBNb3VzZUV2ZW50KSkge1xuICAgICAgdGhpcy5pc1NlbGVjdGVkID0gdHJ1ZTtcbiAgICAgIHRoaXMudHJlZVNlcnZpY2UuZmlyZU5vZGVTZWxlY3RlZCh0aGlzLnRyZWUpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBvbk5vZGVVbnNlbGVjdGVkKGU6IHsgYnV0dG9uOiBudW1iZXIgfSk6IHZvaWQge1xuICAgIGlmICghdGhpcy50cmVlLnNlbGVjdGlvbkFsbG93ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoRXZlbnRVdGlscy5pc0xlZnRCdXR0b25DbGlja2VkKGUgYXMgTW91c2VFdmVudCkpIHtcbiAgICAgIHRoaXMuaXNTZWxlY3RlZCA9IGZhbHNlO1xuICAgICAgdGhpcy50cmVlU2VydmljZS5maXJlTm9kZVVuc2VsZWN0ZWQodGhpcy50cmVlKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgc2hvd1JpZ2h0TWVudShlOiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnRyZWUuaGFzUmlnaHRNZW51KCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoRXZlbnRVdGlscy5pc1JpZ2h0QnV0dG9uQ2xpY2tlZChlKSkge1xuICAgICAgdGhpcy5pc1JpZ2h0TWVudVZpc2libGUgPSAhdGhpcy5pc1JpZ2h0TWVudVZpc2libGU7XG4gICAgICB0aGlzLm5vZGVNZW51U2VydmljZS5oaWRlTWVudUZvckFsbE5vZGVzRXhjZXB0KHRoaXMubm9kZUVsZW1lbnRSZWYpO1xuICAgIH1cbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gIH1cblxuICBwdWJsaWMgc2hvd0xlZnRNZW51KGU6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMudHJlZS5oYXNMZWZ0TWVudSgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKEV2ZW50VXRpbHMuaXNMZWZ0QnV0dG9uQ2xpY2tlZChlKSkge1xuICAgICAgdGhpcy5pc0xlZnRNZW51VmlzaWJsZSA9ICF0aGlzLmlzTGVmdE1lbnVWaXNpYmxlO1xuICAgICAgdGhpcy5ub2RlTWVudVNlcnZpY2UuaGlkZU1lbnVGb3JBbGxOb2Rlc0V4Y2VwdCh0aGlzLm5vZGVFbGVtZW50UmVmKTtcbiAgICAgIGlmICh0aGlzLmlzTGVmdE1lbnVWaXNpYmxlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwdWJsaWMgb25NZW51SXRlbVNlbGVjdGVkKGU6IE5vZGVNZW51SXRlbVNlbGVjdGVkRXZlbnQpOiB2b2lkIHtcbiAgICBzd2l0Y2ggKGUubm9kZU1lbnVJdGVtQWN0aW9uKSB7XG4gICAgICBjYXNlIE5vZGVNZW51SXRlbUFjdGlvbi5OZXdUYWc6XG4gICAgICAgIHRoaXMub25OZXdTZWxlY3RlZChlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIE5vZGVNZW51SXRlbUFjdGlvbi5OZXdGb2xkZXI6XG4gICAgICAgIHRoaXMub25OZXdTZWxlY3RlZChlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIE5vZGVNZW51SXRlbUFjdGlvbi5SZW5hbWU6XG4gICAgICAgIHRoaXMub25SZW5hbWVTZWxlY3RlZCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTm9kZU1lbnVJdGVtQWN0aW9uLlJlbW92ZTpcbiAgICAgICAgdGhpcy5vblJlbW92ZVNlbGVjdGVkKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBOb2RlTWVudUl0ZW1BY3Rpb24uQ3VzdG9tOlxuICAgICAgICB0aGlzLm9uQ3VzdG9tU2VsZWN0ZWQoKTtcbiAgICAgICAgdGhpcy50cmVlU2VydmljZS5maXJlTWVudUl0ZW1TZWxlY3RlZCh0aGlzLnRyZWUsIGUubm9kZU1lbnVJdGVtU2VsZWN0ZWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2hvc2VuIG1lbnUgaXRlbSBkb2Vzbid0IGV4aXN0YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBvbk5ld1NlbGVjdGVkKGU6IE5vZGVNZW51SXRlbVNlbGVjdGVkRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLnRyZWUuY3JlYXRlTm9kZShlLm5vZGVNZW51SXRlbUFjdGlvbiA9PT0gTm9kZU1lbnVJdGVtQWN0aW9uLk5ld0ZvbGRlcik7XG4gICAgdGhpcy5pc1JpZ2h0TWVudVZpc2libGUgPSBmYWxzZTtcbiAgICB0aGlzLmlzTGVmdE1lbnVWaXNpYmxlID0gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIG9uUmVuYW1lU2VsZWN0ZWQoKTogdm9pZCB7XG4gICAgdGhpcy50cmVlLm1hcmtBc0JlaW5nUmVuYW1lZCgpO1xuICAgIHRoaXMuaXNSaWdodE1lbnVWaXNpYmxlID0gZmFsc2U7XG4gICAgdGhpcy5pc0xlZnRNZW51VmlzaWJsZSA9IGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBvblJlbW92ZVNlbGVjdGVkKCk6IHZvaWQge1xuICAgIHRoaXMudHJlZVNlcnZpY2UuZGVsZXRlQ29udHJvbGxlcihnZXQodGhpcy50cmVlLCAnbm9kZS5pZCcsICcnKSk7XG4gICAgdGhpcy50cmVlU2VydmljZS5maXJlTm9kZVJlbW92ZWQodGhpcy50cmVlKTtcbiAgfVxuXG4gIHByaXZhdGUgb25DdXN0b21TZWxlY3RlZCgpOiB2b2lkIHtcbiAgICB0aGlzLmlzUmlnaHRNZW51VmlzaWJsZSA9IGZhbHNlO1xuICAgIHRoaXMuaXNMZWZ0TWVudVZpc2libGUgPSBmYWxzZTtcbiAgfVxuXG4gIHB1YmxpYyBvblN3aXRjaEZvbGRpbmdUeXBlKCk6IHZvaWQge1xuICAgIHRoaXMudHJlZS5zd2l0Y2hGb2xkaW5nVHlwZSgpO1xuICAgIHRoaXMudHJlZVNlcnZpY2UuZmlyZU5vZGVTd2l0Y2hGb2xkaW5nVHlwZSh0aGlzLnRyZWUpO1xuICB9XG5cbiAgcHVibGljIGFwcGx5TmV3VmFsdWUoZTogTm9kZUVkaXRhYmxlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoKGUuYWN0aW9uID09PSBOb2RlRWRpdGFibGVFdmVudEFjdGlvbi5DYW5jZWwgfHwgdGhpcy50cmVlLmlzTmV3KCkpICYmIFRyZWUuaXNWYWx1ZUVtcHR5KGUudmFsdWUpKSB7XG4gICAgICByZXR1cm4gdGhpcy50cmVlU2VydmljZS5maXJlTm9kZVJlbW92ZWQodGhpcy50cmVlKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy50cmVlLmlzTmV3KCkpIHtcbiAgICAgIHRoaXMudHJlZS52YWx1ZSA9IGUudmFsdWU7XG4gICAgICB0aGlzLnRyZWVTZXJ2aWNlLmZpcmVOb2RlQ3JlYXRlZCh0aGlzLnRyZWUpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRyZWUuaXNCZWluZ1JlbmFtZWQoKSkge1xuICAgICAgY29uc3Qgb2xkVmFsdWUgPSB0aGlzLnRyZWUudmFsdWU7XG4gICAgICB0aGlzLnRyZWUudmFsdWUgPSBlLnZhbHVlO1xuICAgICAgdGhpcy50cmVlU2VydmljZS5maXJlTm9kZVJlbmFtZWQob2xkVmFsdWUsIHRoaXMudHJlZSk7XG4gICAgfVxuXG4gICAgdGhpcy50cmVlLm1hcmtBc01vZGlmaWVkKCk7XG4gIH1cblxuICBwdWJsaWMgc2hvdWxkU2hvd0lucHV0Rm9yVHJlZVZhbHVlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnRyZWUuaXNOZXcoKSB8fCB0aGlzLnRyZWUuaXNCZWluZ1JlbmFtZWQoKTtcbiAgfVxuXG4gIHB1YmxpYyBpc1Jvb3RIaWRkZW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMudHJlZS5pc1Jvb3QoKSAmJiAhdGhpcy5zZXR0aW5ncy5yb290SXNWaXNpYmxlO1xuICB9XG5cbiAgcHVibGljIGhhc0N1c3RvbU1lbnUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMudHJlZS5oYXNDdXN0b21NZW51KCk7XG4gIH1cblxuICBwdWJsaWMgc3dpdGNoTm9kZUNoZWNrU3RhdHVzKCkge1xuICAgIGlmICghdGhpcy50cmVlLmNoZWNrZWQpIHtcbiAgICAgIHRoaXMub25Ob2RlQ2hlY2tlZCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm9uTm9kZVVuY2hlY2tlZCgpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBvbk5vZGVDaGVja2VkKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jaGVja2JveEVsZW1lbnRSZWYpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmNoZWNrYm94RWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmluZGV0ZXJtaW5hdGUgPSBmYWxzZTtcbiAgICB0aGlzLnRyZWVTZXJ2aWNlLmZpcmVOb2RlQ2hlY2tlZCh0aGlzLnRyZWUpO1xuICAgIHRoaXMuZXhlY3V0ZU9uQ2hpbGRDb250cm9sbGVyKGNvbnRyb2xsZXIgPT4gY29udHJvbGxlci5jaGVjaygpKTtcbiAgICB0aGlzLnRyZWUuY2hlY2tlZCA9IHRydWU7XG4gIH1cblxuICBwdWJsaWMgb25Ob2RlVW5jaGVja2VkKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jaGVja2JveEVsZW1lbnRSZWYpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmNoZWNrYm94RWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmluZGV0ZXJtaW5hdGUgPSBmYWxzZTtcbiAgICB0aGlzLnRyZWVTZXJ2aWNlLmZpcmVOb2RlVW5jaGVja2VkKHRoaXMudHJlZSk7XG4gICAgdGhpcy5leGVjdXRlT25DaGlsZENvbnRyb2xsZXIoY29udHJvbGxlciA9PiBjb250cm9sbGVyLnVuY2hlY2soKSk7XG4gICAgdGhpcy50cmVlLmNoZWNrZWQgPSBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgZXhlY3V0ZU9uQ2hpbGRDb250cm9sbGVyKGV4ZWN1dG9yOiAoY29udHJvbGxlcjogVHJlZUNvbnRyb2xsZXIpID0+IHZvaWQpIHtcbiAgICBpZiAodGhpcy50cmVlLmhhc0xvYWRlZENoaWxkZXJuKCkpIHtcbiAgICAgIHRoaXMudHJlZS5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZDogVHJlZSkgPT4ge1xuICAgICAgICBjb25zdCBjb250cm9sbGVyID0gdGhpcy50cmVlU2VydmljZS5nZXRDb250cm9sbGVyKGNoaWxkLmlkKTtcbiAgICAgICAgaWYgKCFpc05pbChjb250cm9sbGVyKSkge1xuICAgICAgICAgIGV4ZWN1dG9yKGNvbnRyb2xsZXIpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICB1cGRhdGVDaGVja2JveFN0YXRlKCk6IHZvaWQge1xuICAgIC8vIENhbGxpbmcgc2V0VGltZW91dCBzbyB0aGUgdmFsdWUgb2YgaXNDaGVja2VkIHdpbGwgYmUgdXBkYXRlZCBhbmQgYWZ0ZXIgdGhhdCBJJ2xsIGNoZWNrIHRoZSBjaGlsZHJlbiBzdGF0dXMuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBjb25zdCBjaGVja2VkQ2hpbGRyZW5BbW91bnQgPSB0aGlzLnRyZWUuY2hlY2tlZENoaWxkcmVuQW1vdW50KCk7XG4gICAgICBpZiAoY2hlY2tlZENoaWxkcmVuQW1vdW50ID09PSAwKSB7XG4gICAgICAgIHRoaXMuY2hlY2tib3hFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuaW5kZXRlcm1pbmF0ZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnRyZWUuY2hlY2tlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnRyZWVTZXJ2aWNlLmZpcmVOb2RlVW5jaGVja2VkKHRoaXMudHJlZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoZWNrZWRDaGlsZHJlbkFtb3VudCA9PT0gdGhpcy50cmVlLmxvYWRlZENoaWxkcmVuQW1vdW50KCkpIHtcbiAgICAgICAgdGhpcy5jaGVja2JveEVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5pbmRldGVybWluYXRlID0gZmFsc2U7XG4gICAgICAgIHRoaXMudHJlZS5jaGVja2VkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy50cmVlU2VydmljZS5maXJlTm9kZUNoZWNrZWQodGhpcy50cmVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMudHJlZS5jaGVja2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY2hlY2tib3hFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuaW5kZXRlcm1pbmF0ZSA9IHRydWU7XG4gICAgICAgIHRoaXMudHJlZVNlcnZpY2UuZmlyZU5vZGVJbmRldGVybWluZWQodGhpcy50cmVlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZXZlbnRDb250YWluc0lkKGV2ZW50OiBOb2RlRXZlbnQpOiBib29sZWFuIHtcbiAgICBpZiAoIWV2ZW50Lm5vZGUuaWQpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ1wiTm9kZSB3aXRoIGNoZWNrYm94XCIgZmVhdHVyZSByZXF1aXJlcyBhIHVuaXF1ZSBpZCBhc3NpZ25lZCB0byBldmVyeSBub2RlLCBwbGVhc2UgY29uc2lkZXIgdG8gYWRkIGl0LidcbiAgICAgICk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG4iXX0=