UNPKG

ng2-tree

Version:

angular2 component for visualizing data that can be naturally represented as a tree

399 lines (383 loc) 49.8 kB
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=