cm-angular-tooltip
Version:
Tooltip for Angular
486 lines • 52.5 kB
JavaScript
import { Directive, HostListener, Input, Output, EventEmitter, Inject, Optional } from '@angular/core';
import { TooltipComponent } from './tooltip.component';
import { backwardCompatibilityOptions, defaultOptions } from './tooltip-options';
import { TooltipOptionsService } from './tooltip-options.service';
import * as i0 from "@angular/core";
export class TooltipDirective {
set options(value) {
if (value && defaultOptions) {
this._options = value;
}
}
get options() {
return this._options;
}
// Content type
set contentTypeBackwardCompatibility(value) {
if (value) {
this._contentType = value;
}
}
set contentType(value) {
if (value) {
this._contentType = value;
}
}
get contentType() {
return this._contentType;
}
// z-index
set zIndexBackwardCompatibility(value) {
if (value) {
this._zIndex = value;
}
}
set zIndex(value) {
if (value) {
this._zIndex = value;
}
}
get zIndex() {
return this._zIndex;
}
// Animation duration
set animationDurationBackwardCompatibility(value) {
if (value) {
this._animationDuration = value;
}
}
set animationDuration(value) {
if (value) {
this._animationDuration = value;
}
}
get animationDuration() {
return this._animationDuration;
}
// Tooltip class
set tooltipClassBackwardCompatibility(value) {
if (value) {
this._tooltipClass = value;
}
}
set tooltipClass(value) {
if (value) {
this._tooltipClass = value;
}
}
get tooltipClass() {
return this._tooltipClass;
}
// Max width
set maxWidthBackwardCompatibility(value) {
if (value) {
this._maxWidth = value;
}
}
set maxWidth(value) {
if (value) {
this._maxWidth = value;
}
}
get maxWidth() {
return this._maxWidth;
}
// Show delay
set showDelayBackwardCompatibility(value) {
if (value) {
this._showDelay = value;
}
}
set showDelay(value) {
if (value) {
this._showDelay = value;
}
}
get showDelay() {
return this._showDelay;
}
// Hide delay
set hideDelayBackwardCompatibility(value) {
if (value) {
this._hideDelay = value;
}
}
set hideDelay(value) {
if (value) {
this._hideDelay = value;
}
}
get hideDelay() {
return this._hideDelay;
}
get isTooltipDestroyed() {
return this.componentRef && this.componentRef.hostView.destroyed;
}
get destroyDelay() {
if (this._destroyDelay) {
return this._destroyDelay;
}
else {
return Number(this.getHideDelay()) + Number(this.options['animationDuration']);
}
}
set destroyDelay(value) {
this._destroyDelay = value;
}
get tooltipPosition() {
if (this.options['position']) {
return this.options['position'];
}
else {
return this.elementPosition;
}
}
constructor(initOptions, elementRef, componentFactoryResolver, appRef, injector) {
this.initOptions = initOptions;
this.elementRef = elementRef;
this.componentFactoryResolver = componentFactoryResolver;
this.appRef = appRef;
this.injector = injector;
this._options = {};
this._contentType = "string";
this.events = new EventEmitter();
}
onMouseEnter() {
if (this.isDisplayOnHover == false) {
return;
}
this.show();
}
onMouseLeave() {
if (this.options['trigger'] === 'hover') {
this.destroyTooltip();
}
}
onClick() {
if (this.isDisplayOnClick == false) {
return;
}
this.show();
this.hideAfterClickTimeoutId = window.setTimeout(() => {
this.destroyTooltip();
}, this.options['hideDelayAfterClick']);
}
ngOnInit() {
}
ngOnChanges(changes) {
this.initOptions = this.renameProperties(this.initOptions);
let changedOptions = this.getProperties(changes);
changedOptions = this.renameProperties(changedOptions);
this.applyOptionsDefault(defaultOptions, changedOptions);
}
ngOnDestroy() {
this.destroyTooltip({
fast: true
});
if (this.componentSubscribe) {
this.componentSubscribe.unsubscribe();
}
}
getShowDelay() {
return this.options['showDelay'];
}
getHideDelay() {
const hideDelay = this.options['hideDelay'];
const hideDelayTouchscreen = this.options['hideDelayTouchscreen'];
return this.isTouchScreen ? hideDelayTouchscreen : hideDelay;
}
getProperties(changes) {
let directiveProperties = {};
let customProperties = {};
let allProperties = {};
for (var prop in changes) {
if (prop !== 'options' && prop !== 'tooltipValue') {
directiveProperties[prop] = changes[prop].currentValue;
}
if (prop === 'options') {
customProperties = changes[prop].currentValue;
}
}
allProperties = Object.assign({}, customProperties, directiveProperties);
return allProperties;
}
renameProperties(options) {
for (var prop in options) {
if (backwardCompatibilityOptions[prop]) {
options[backwardCompatibilityOptions[prop]] = options[prop];
delete options[prop];
}
}
return options;
}
getElementPosition() {
this.elementPosition = this.elementRef.nativeElement.getBoundingClientRect();
}
createTooltip() {
this.clearTimeouts();
this.getElementPosition();
this.createTimeoutId = window.setTimeout(() => {
this.appendComponentToBody(TooltipComponent);
}, this.getShowDelay());
this.showTimeoutId = window.setTimeout(() => {
this.showTooltipElem();
}, this.getShowDelay());
}
destroyTooltip(options = {
fast: false
}) {
this.clearTimeouts();
if (this.isTooltipDestroyed == false) {
this.hideTimeoutId = window.setTimeout(() => {
this.hideTooltip();
}, options.fast ? 0 : this.getHideDelay());
this.destroyTimeoutId = window.setTimeout(() => {
if (!this.componentRef || this.isTooltipDestroyed) {
return;
}
this.appRef.detachView(this.componentRef.hostView);
this.componentRef.destroy();
this.events.emit({
type: 'hidden',
position: this.tooltipPosition
});
}, options.fast ? 0 : this.destroyDelay);
}
}
showTooltipElem() {
this.clearTimeouts();
this.componentRef.instance.show = true;
this.events.emit({
type: 'show',
position: this.tooltipPosition
});
}
hideTooltip() {
if (!this.componentRef || this.isTooltipDestroyed) {
return;
}
this.componentRef.instance.show = false;
this.events.emit({
type: 'hide',
position: this.tooltipPosition
});
}
appendComponentToBody(component, data = {}) {
this.componentRef = this.componentFactoryResolver
.resolveComponentFactory(component)
.create(this.injector);
this.componentRef.instance.data = {
value: this.tooltipValue,
element: this.elementRef.nativeElement,
elementPosition: this.tooltipPosition,
options: this.options
};
this.appRef.attachView(this.componentRef.hostView);
const domElem = this.componentRef.hostView.rootNodes[0];
document.body.appendChild(domElem);
this.componentSubscribe = this.componentRef.instance.events.subscribe((event) => {
this.handleEvents(event);
});
}
clearTimeouts() {
if (this.createTimeoutId) {
clearTimeout(this.createTimeoutId);
}
if (this.showTimeoutId) {
clearTimeout(this.showTimeoutId);
}
if (this.hideTimeoutId) {
clearTimeout(this.hideTimeoutId);
}
if (this.destroyTimeoutId) {
clearTimeout(this.destroyTimeoutId);
}
}
get isDisplayOnHover() {
if (this.options['display'] == false) {
return false;
}
if (this.options['displayTouchscreen'] == false && this.isTouchScreen) {
return false;
}
if (this.options['trigger'] !== 'hover') {
return false;
}
return true;
}
get isDisplayOnClick() {
if (this.options['display'] == false) {
return false;
}
if (this.options['displayTouchscreen'] == false && this.isTouchScreen) {
return false;
}
if (this.options['trigger'] != 'click') {
return false;
}
return true;
}
get isTouchScreen() {
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
var mq = function (query) {
return window.matchMedia(query).matches;
};
if (('ontouchstart' in window)) {
return true;
}
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
// https://git.io/vznFH
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
return mq(query);
}
applyOptionsDefault(defaultOptions, options) {
this.options = Object.assign({}, defaultOptions, this.initOptions || {}, this.options, options);
}
handleEvents(event) {
if (event.type === 'shown') {
this.events.emit({
type: 'shown',
position: this.tooltipPosition
});
}
}
show() {
if (!this.tooltipValue) {
return;
}
if (!this.componentRef || this.isTooltipDestroyed) {
this.createTooltip();
}
else if (!this.isTooltipDestroyed) {
this.showTooltipElem();
}
}
hide() {
this.destroyTooltip();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TooltipDirective, deps: [{ token: TooltipOptionsService, optional: true }, { token: i0.ElementRef }, { token: i0.ComponentFactoryResolver }, { token: i0.ApplicationRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: TooltipDirective, selector: "[tooltip]", inputs: { options: "options", tooltipValue: ["tooltip", "tooltipValue"], placement: "placement", autoPlacement: "autoPlacement", contentTypeBackwardCompatibility: ["content-type", "contentTypeBackwardCompatibility"], contentType: "contentType", hideDelayMobile: ["hide-delay-mobile", "hideDelayMobile"], hideDelayTouchscreen: "hideDelayTouchscreen", zIndexBackwardCompatibility: ["z-index", "zIndexBackwardCompatibility"], zIndex: "zIndex", animationDurationBackwardCompatibility: ["animation-duration", "animationDurationBackwardCompatibility"], animationDuration: "animationDuration", trigger: "trigger", tooltipClassBackwardCompatibility: ["tooltip-class", "tooltipClassBackwardCompatibility"], tooltipClass: "tooltipClass", display: "display", displayMobile: ["display-mobile", "displayMobile"], displayTouchscreen: "displayTouchscreen", shadow: "shadow", theme: "theme", offset: "offset", width: "width", maxWidthBackwardCompatibility: ["max-width", "maxWidthBackwardCompatibility"], maxWidth: "maxWidth", id: "id", showDelayBackwardCompatibility: ["show-delay", "showDelayBackwardCompatibility"], showDelay: "showDelay", hideDelayBackwardCompatibility: ["hide-delay", "hideDelayBackwardCompatibility"], hideDelay: "hideDelay", hideDelayAfterClick: "hideDelayAfterClick", pointerEvents: "pointerEvents", position: "position" }, outputs: { events: "events" }, host: { listeners: { "focusin": "onMouseEnter()", "mouseenter": "onMouseEnter()", "focusout": "onMouseLeave()", "mouseleave": "onMouseLeave()", "click": "onClick()" } }, exportAs: ["tooltip"], usesOnChanges: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TooltipDirective, decorators: [{
type: Directive,
args: [{
selector: '[tooltip]',
exportAs: 'tooltip',
}]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [TooltipOptionsService]
}] }, { type: i0.ElementRef }, { type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }], propDecorators: { options: [{
type: Input,
args: ['options']
}], tooltipValue: [{
type: Input,
args: ['tooltip']
}], placement: [{
type: Input,
args: ['placement']
}], autoPlacement: [{
type: Input,
args: ['autoPlacement']
}], contentTypeBackwardCompatibility: [{
type: Input,
args: ['content-type']
}], contentType: [{
type: Input,
args: ['contentType']
}], hideDelayMobile: [{
type: Input,
args: ['hide-delay-mobile']
}], hideDelayTouchscreen: [{
type: Input,
args: ['hideDelayTouchscreen']
}], zIndexBackwardCompatibility: [{
type: Input,
args: ['z-index']
}], zIndex: [{
type: Input,
args: ['zIndex']
}], animationDurationBackwardCompatibility: [{
type: Input,
args: ['animation-duration']
}], animationDuration: [{
type: Input,
args: ['animationDuration']
}], trigger: [{
type: Input,
args: ['trigger']
}], tooltipClassBackwardCompatibility: [{
type: Input,
args: ['tooltip-class']
}], tooltipClass: [{
type: Input,
args: ['tooltipClass']
}], display: [{
type: Input,
args: ['display']
}], displayMobile: [{
type: Input,
args: ['display-mobile']
}], displayTouchscreen: [{
type: Input,
args: ['displayTouchscreen']
}], shadow: [{
type: Input,
args: ['shadow']
}], theme: [{
type: Input,
args: ['theme']
}], offset: [{
type: Input,
args: ['offset']
}], width: [{
type: Input,
args: ['width']
}], maxWidthBackwardCompatibility: [{
type: Input,
args: ['max-width']
}], maxWidth: [{
type: Input,
args: ['maxWidth']
}], id: [{
type: Input,
args: ['id']
}], showDelayBackwardCompatibility: [{
type: Input,
args: ['show-delay']
}], showDelay: [{
type: Input,
args: ['showDelay']
}], hideDelayBackwardCompatibility: [{
type: Input,
args: ['hide-delay']
}], hideDelay: [{
type: Input,
args: ['hideDelay']
}], hideDelayAfterClick: [{
type: Input,
args: ['hideDelayAfterClick']
}], pointerEvents: [{
type: Input,
args: ['pointerEvents']
}], position: [{
type: Input,
args: ['position']
}], events: [{
type: Output
}], onMouseEnter: [{
type: HostListener,
args: ['focusin']
}, {
type: HostListener,
args: ['mouseenter']
}], onMouseLeave: [{
type: HostListener,
args: ['focusout']
}, {
type: HostListener,
args: ['mouseleave']
}], onClick: [{
type: HostListener,
args: ['click']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHRpcC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jbS1hbmd1bGFyLXRvb2x0aXAvc3JjL2xpYi90b29sdGlwLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQTZGLE1BQU0sRUFBRSxZQUFZLEVBQWEsTUFBTSxFQUFFLFFBQVEsRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFDeE8sT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFdkQsT0FBTyxFQUFFLDRCQUE0QixFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDOztBQWNsRSxNQUFNLE9BQU8sZ0JBQWdCO0lBc0J6QixJQUFzQixPQUFPLENBQUMsS0FBcUI7UUFDL0MsSUFBSSxLQUFLLElBQUksY0FBYyxFQUFFLENBQUM7WUFDMUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDMUIsQ0FBQztJQUNMLENBQUM7SUFDRCxJQUFJLE9BQU87UUFDUCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDekIsQ0FBQztJQU1ELGVBQWU7SUFDZixJQUEyQixnQ0FBZ0MsQ0FBQyxLQUFxQztRQUM3RixJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1IsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDOUIsQ0FBQztJQUNMLENBQUM7SUFDRCxJQUEwQixXQUFXLENBQUMsS0FBcUM7UUFDdkUsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNSLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1FBQzlCLENBQUM7SUFDTCxDQUFDO0lBQ0QsSUFBSSxXQUFXO1FBQ1gsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzdCLENBQUM7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Szt1QkFBQyxlQUFlO2dCQUtLLFlBQVk7c0JBQXRDLEtBQUs7dUJBQUMsY0FBYztnQkFTSCxPQUFPO3NCQUF4QixLQUFLO3VCQUFDLFNBQVM7Z0JBQ1MsYUFBYTtzQkFBckMsS0FBSzt1QkFBQyxnQkFBZ0I7Z0JBQ00sa0JBQWtCO3NCQUE5QyxLQUFLO3VCQUFDLG9CQUFvQjtnQkFDVixNQUFNO3NCQUF0QixLQUFLO3VCQUFDLFFBQVE7Z0JBQ0MsS0FBSztzQkFBcEIsS0FBSzt1QkFBQyxPQUFPO2dCQUNHLE1BQU07c0JBQXRCLEtBQUs7dUJBQUMsUUFBUTtnQkFDQyxLQUFLO3NCQUFwQixLQUFLO3VCQUFDLE9BQU87Z0JBR1UsNkJBQTZCO3NCQUFwRCxLQUFLO3VCQUFDLFdBQVc7Z0JBS0ssUUFBUTtzQkFBOUIsS0FBSzt1QkFBQyxVQUFVO2dCQVVKLEVBQUU7c0JBQWQsS0FBSzt1QkFBQyxJQUFJO2dCQUdjLDhCQUE4QjtzQkFBdEQsS0FBSzt1QkFBQyxZQUFZO2dCQUtLLFNBQVM7c0JBQWhDLEtBQUs7dUJBQUMsV0FBVztnQkFVTyw4QkFBOEI7c0JBQXRELEtBQUs7dUJBQUMsWUFBWTtnQkFLSyxTQUFTO3NCQUFoQyxLQUFLO3VCQUFDLFdBQVc7Z0JBU1ksbUJBQW1CO3NCQUFoRCxLQUFLO3VCQUFDLHFCQUFxQjtnQkFDSixhQUFhO3NCQUFwQyxLQUFLO3VCQUFDLGVBQWU7Z0JBQ0gsUUFBUTtzQkFBMUIsS0FBSzt1QkFBQyxVQUFVO2dCQXlCUCxNQUFNO3NCQUFmLE1BQU07Z0JBV1AsWUFBWTtzQkFGWCxZQUFZO3VCQUFDLFNBQVM7O3NCQUN0QixZQUFZO3VCQUFDLFlBQVk7Z0JBVzFCLFlBQVk7c0JBRlgsWUFBWTt1QkFBQyxVQUFVOztzQkFDdkIsWUFBWTt1QkFBQyxZQUFZO2dCQVExQixPQUFPO3NCQUROLFlBQVk7dUJBQUMsT0FBTyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBJbnB1dCwgQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLCBFbWJlZGRlZFZpZXdSZWYsIEFwcGxpY2F0aW9uUmVmLCBJbmplY3RvciwgQ29tcG9uZW50UmVmLCBPbkluaXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBPbkRlc3Ryb3ksIEluamVjdCwgT3B0aW9uYWwsIFNpbXBsZUNoYW5nZXMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgVG9vbHRpcENvbXBvbmVudCB9IGZyb20gJy4vdG9vbHRpcC5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBUb29sdGlwT3B0aW9ucyB9IGZyb20gJy4vdG9vbHRpcC1vcHRpb25zLmludGVyZmFjZSc7XHJcbmltcG9ydCB7IGJhY2t3YXJkQ29tcGF0aWJpbGl0eU9wdGlvbnMsIGRlZmF1bHRPcHRpb25zIH0gZnJvbSAnLi90b29sdGlwLW9wdGlvbnMnO1xyXG5pbXBvcnQgeyBUb29sdGlwT3B0aW9uc1NlcnZpY2UgfSBmcm9tICcuL3Rvb2x0aXAtb3B0aW9ucy5zZXJ2aWNlJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQWRDb21wb25lbnQge1xyXG4gICAgZGF0YTogYW55O1xyXG4gICAgc2hvdzogYm9vbGVhbjtcclxuICAgIGNsb3NlOiBib29sZWFuO1xyXG4gICAgZXZlbnRzOiBhbnk7XHJcbn1cclxuXHJcbkBEaXJlY3RpdmUoe1xyXG4gICAgc2VsZWN0b3I6ICdbdG9vbHRpcF0nLFxyXG4gICAgZXhwb3J0QXM6ICd0b29sdGlwJyxcclxufSlcclxuXHJcbmV4cG9ydCBjbGFzcyBUb29sdGlwRGlyZWN0aXZlIHtcclxuXHJcbiAgICBoaWRlVGltZW91dElkITogbnVtYmVyO1xyXG4gICAgZGVzdHJveVRpbWVvdXRJZCE6IG51bWJlcjtcclxuICAgIGhpZGVBZnRlckNsaWNrVGltZW91dElkITogbnVtYmVyO1xyXG4gICAgY3JlYXRlVGltZW91dElkITogbnVtYmVyO1xyXG4gICAgc2hvd1RpbWVvdXRJZCE6IG51bWJlcjtcclxuICAgIGNvbXBvbmVudFJlZjogYW55O1xyXG4gICAgZWxlbWVudFBvc2l0aW9uOiBhbnk7XHJcbiAgICBfaWQ6IGFueTtcclxuICAgIF9vcHRpb25zOiBhbnkgPSB7fTtcclxuICAgIF9kZWZhdWx0T3B0aW9uczogYW55O1xyXG4gICAgX2Rlc3Ryb3lEZWxheSE6IG51bWJlcjtcclxuICAgIGNvbXBvbmVudFN1YnNjcmliZTogYW55O1xyXG4gICAgX2NvbnRlbnRUeXBlOiBcInN0cmluZ1wiIHwgXCJodG1sXCIgfCBcInRlbXBsYXRlXCIgPSBcInN0cmluZ1wiO1xyXG4gICAgX3Nob3dEZWxheSE6IG51bWJlcjtcclxuICAgIF9oaWRlRGVsYXkhOiBudW1iZXI7XHJcbiAgICBfekluZGV4ITogbnVtYmVyO1xyXG4gICAgX3Rvb2x0aXBDbGFzcyE6IHN0cmluZztcclxuICAgIF9hbmltYXRpb25EdXJhdGlvbiE6IG51bWJlcjtcclxuICAgIF9tYXhXaWR0aCE6IHN0cmluZztcclxuXHJcbiAgICBASW5wdXQoJ29wdGlvbnMnKSBzZXQgb3B0aW9ucyh2YWx1ZTogVG9vbHRpcE9wdGlvbnMpIHtcclxuICAgICAgICBpZiAodmFsdWUgJiYgZGVmYXVsdE9wdGlvbnMpIHtcclxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucyA9IHZhbHVlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGdldCBvcHRpb25zKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zO1xyXG4gICAgfVxyXG5cclxuICAgIEBJbnB1dCgndG9vbHRpcCcpIHRvb2x0aXBWYWx1ZSE6IHN0cmluZztcclxuICAgIEBJbnB1dCgncGxhY2VtZW50JykgcGxhY2VtZW50ITogc3RyaW5nO1xyXG4gICAgQElucHV0KCdhdXRvUGxhY2VtZW50JykgYXV0b1BsYWNlbWVudCE6IGJvb2xlYW47XHJcblxyXG4gICAgLy8gQ29udGVudCB0eXBlXHJcbiAgICBASW5wdXQoJ2NvbnRlbnQtdHlwZScpIHNldCBjb250ZW50VHlwZUJhY2t3YXJkQ29tcGF0aWJpbGl0eSh2YWx1ZTogXCJzdHJpbmdcIiB8IFwiaHRtbFwiIHwgXCJ0ZW1wbGF0ZVwiKSB7XHJcbiAgICAgICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2NvbnRlbnRUeXBlID0gdmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgQElucHV0KCdjb250ZW50VHlwZScpIHNldCBjb250ZW50VHlwZSh2YWx1ZTogXCJzdHJpbmdcIiB8IFwiaHRtbFwiIHwgXCJ0ZW1wbGF0ZVwiKSB7XHJcbiAgICAgICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2NvbnRlbnRUeXBlID0gdmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZ2V0IGNvbnRlbnRUeXBlKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9jb250ZW50VHlwZTtcclxuICAgIH1cclxuXHJcbiAgICBASW5wdXQoJ2hpZGUtZGVsYXktbW9iaWxlJykgaGlkZURlbGF5TW9iaWxlITogbnVtYmVyO1xyXG4gICAgQElucHV0KCdoaWRlRGVsYXlUb3VjaHNjcmVlbicpIGhpZGVEZWxheVRvdWNoc2NyZWVuITogbnVtYmVyO1xyXG5cclxuICAgIC8vIHotaW5kZXhcclxuICAgIEBJbnB1dCgnei1pbmRleCcpIHNldCB6SW5kZXhCYWNrd2FyZENvbXBhdGliaWxpdHkodmFsdWU6IG51bWJlcikge1xyXG4gICAgICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICAgICAgICB0aGlzLl96SW5kZXggPSB2YWx1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBASW5wdXQoJ3pJbmRleCcpIHNldCB6SW5kZXgodmFsdWU6IG51bWJlcikge1xyXG4gICAgICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICAgICAgICB0aGlzLl96SW5kZXggPSB2YWx1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBnZXQgekluZGV4KCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl96SW5kZXg7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQW5pbWF0aW9uIGR1cmF0aW9uXHJcbiAgICBASW5wdXQoJ2FuaW1hdGlvbi1kdXJhdGlvbicpIHNldCBhbmltYXRpb25EdXJhdGlvbkJhY2t3YXJkQ29tcGF0aWJpbGl0eSh2YWx1ZTogbnVtYmVyKSB7XHJcbiAgICAgICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2FuaW1hdGlvbkR1cmF0aW9uID0gdmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgQElucHV0KCdhbmltYXRpb25EdXJhdGlvbicpIHNldCBhbmltYXRpb25EdXJhdGlvbih2YWx1ZTogbnVtYmVyKSB7XHJcbiAgICAgICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2FuaW1hdGlvbkR1cmF0aW9uID0gdmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZ2V0IGFuaW1hdGlvbkR1cmF0aW9uKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9hbmltYXRpb25EdXJhdGlvbjtcclxuICAgIH1cclxuXHJcblxyXG4gICAgQElucHV0KCd0cmlnZ2VyJykgdHJpZ2dlciE6IHN0cmluZztcclxuXHJcbiAgICAvLyBUb29sdGlwIGNsYXNzXHJcbiAgICBASW5wdXQoJ3Rvb2x0aXAtY2xhc3MnKSBzZXQgdG9vbHRpcENsYXNzQmFja3dhcmRDb21wYXRpYmlsaXR5KHZhbHVlOiBzdHJpbmcpIHtcclxuICAgICAgICBpZiAodmFsdWUpIHtcclxuICAgICAgICAgICAgdGhpcy5fdG9vbHRpcENsYXNzID0gdmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgQElucHV0KCd0b29sdGlwQ2xhc3MnKSBzZXQgdG9vbHRpcENsYXNzKHZhbHVlOiBzdHJpbmcpIHtcclxuICAgICAgICBpZiAodmFsdWUpIHtcclxuICAgICAgICAgICAgdGhpcy5fdG9vbHRpcENsYXNzID0gdmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZ2V0IHRvb2x0aXBDbGFzcygpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fdG9vbHRpcENsYXNzO1xyXG4gICAgfVxyXG5cclxuICAgIEBJbnB1dCgnZGlzcGxheScpIGRpc3BsYXkhOiBib29sZWFuO1xyXG4gICAgQElucHV0KCdkaXNwbGF5LW1vYmlsZScpIGRpc3BsYXlNb2JpbGUhOiBib29sZWFuO1xyXG4gICAgQElucHV0KCdkaXNwbGF5VG91Y2hzY3JlZW4nKSBkaXNwbGF5VG91Y2hzY3JlZW4hOiBib29sZWFuO1xyXG4gICAgQElucHV0KCdzaGFkb3cnKSBzaGFkb3chOiBib29sZWFuO1xyXG4gICAgQElucHV0KCd0aGVtZScpIHRoZW1lITogXCJkYXJrXCIgfCBcImxpZ2h0XCI7XHJcbiAgICBASW5wdXQoJ29mZnNldCcpIG9mZnNldCE6IG51bWJlcjtcclxuICAgIEBJbnB1dCgnd2lkdGgnKSB3aWR0aCE6IHN0cmluZztcclxuXHJcbiAgICAvLyBNYXggd2lkdGhcclxuICAgIEBJbnB1dCgnbWF4LXdpZHRoJykgc2V0IG1heFdpZHRoQmFja3dhcmRDb21wYXRpYmlsaXR5KHZhbHVlOiBzdHJpbmcpIHtcclxuICAgICAgICBpZiAodmFsdWUpIHtcclxuICAgICAgICAgICAgdGhpcy5fbWF4V2lkdGggPSB2YWx1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBASW5wdXQoJ21heFdpZHRoJykgc2V0IG1heFdpZHRoKHZhbHVlOiBzdHJpbmcpIHtcclxuICAgICAgICBpZiAodmFsdWUpIHtcclxuICAgICAgICAgICAgdGhpcy5fbWF4V2lkdGggPSB2YWx1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBnZXQgbWF4V2lkdGgoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX21heFdpZHRoO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICBASW5wdXQoJ2lkJykgaWQ6IGFueTtcclxuXHJcbiAgICAvLyBTaG93IGRlbGF5XHJcbiAgICBASW5wdXQoJ3Nob3ctZGVsYXknKSBzZXQgc2hvd0RlbGF5QmFja3dhcmRDb21wYXRpYmlsaXR5KHZhbHVlOiBudW1iZXIpIHtcclxuICAgICAgICBpZiAodmFsdWUpIHtcclxuICAgICAgICAgICAgdGhpcy5fc2hvd0RlbGF5ID0gdmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgQElucHV0KCdzaG93RGVsYXknKSBzZXQgc2hvd0RlbGF5KHZhbHVlOiBudW1iZXIpIHtcclxuICAgICAgICBpZiAodmFsdWUpIHtcclxuICAgICAgICAgICAgdGhpcy5fc2hvd0RlbGF5ID0gdmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZ2V0IHNob3dEZWxheSgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fc2hvd0RlbGF5O1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEhpZGUgZGVsYXlcclxuICAgIEBJbnB1dCgnaGlkZS1kZWxheScpIHNldCBoaWRlRGVsYXlCYWNrd2FyZENvbXBhdGliaWxpdHkodmFsdWU6IG51bWJlcikge1xyXG4gICAgICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICAgICAgICB0aGlzLl9oaWRlRGVsYXkgPSB2YWx1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBASW5wdXQoJ2hpZGVEZWxheScpIHNldCBoaWRlRGVsYXkodmFsdWU6IG51bWJlcikge1xyXG4gICAgICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICAgICAgICB0aGlzLl9oaWRlRGVsYXkgPSB2YWx1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBnZXQgaGlkZURlbGF5KCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9oaWRlRGVsYXk7XHJcbiAgICB9XHJcblxyXG4gICAgQElucHV0KCdoaWRlRGVsYXlBZnRlckNsaWNrJykgaGlkZURlbGF5QWZ0ZXJDbGljayE6IG51bWJlcjtcclxuICAgIEBJbnB1dCgncG9pbnRlckV2ZW50cycpIHBvaW50ZXJFdmVudHMhOiAnYXV0bycgfCAnbm9uZSc7XHJcbiAgICBASW5wdXQoJ3Bvc2l0aW9uJykgcG9zaXRpb24hOiB7IHRvcDogbnVtYmVyLCBsZWZ0OiBudW1iZXIgfTtcclxuXHJcbiAgICBnZXQgaXNUb29sdGlwRGVzdHJveWVkKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmNvbXBvbmVudFJlZiAmJiB0aGlzLmNvbXBvbmVudFJlZi5ob3N0Vmlldy5kZXN0cm95ZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IGRlc3Ryb3lEZWxheSgpIHtcclxuICAgICAgICBpZiAodGhpcy5fZGVzdHJveURlbGF5KSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kZXN0cm95RGVsYXk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIE51bWJlcih0aGlzLmdldEhpZGVEZWxheSgpKSArIE51bWJlcih0aGlzLm9wdGlvbnNbJ2FuaW1hdGlvbkR1cmF0aW9uJ10pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHNldCBkZXN0cm95RGVsYXkodmFsdWU6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMuX2Rlc3Ryb3lEZWxheSA9IHZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCB0b29sdGlwUG9zaXRpb24oKSB7XHJcbiAgICAgICAgaWYgKHRoaXMub3B0aW9uc1sncG9zaXRpb24nXSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zWydwb3NpdGlvbiddO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnRQb3NpdGlvbjtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgQE91dHB1dCgpIGV2ZW50czogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihcclxuICAgICAgICBAT3B0aW9uYWwoKSBASW5qZWN0KFRvb2x0aXBPcHRpb25zU2VydmljZSkgcHJpdmF0ZSBpbml0T3B0aW9uczogYW55LFxyXG4gICAgICAgIHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZixcclxuICAgICAgICBwcml2YXRlIGNvbXBvbmVudEZhY3RvcnlSZXNvbHZlcjogQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxyXG4gICAgICAgIHByaXZhdGUgYXBwUmVmOiBBcHBsaWNhdGlvblJlZixcclxuICAgICAgICBwcml2YXRlIGluamVjdG9yOiBJbmplY3RvcikgeyB9XHJcblxyXG4gICAgQEhvc3RMaXN0ZW5lcignZm9jdXNpbicpXHJcbiAgICBASG9zdExpc3RlbmVyKCdtb3VzZWVudGVyJylcclxuICAgIG9uTW91c2VFbnRlcigpIHtcclxuICAgICAgICBpZiAodGhpcy5pc0Rpc3BsYXlPbkhvdmVyID09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuc2hvdygpO1xyXG4gICAgfVxyXG5cclxuICAgIEBIb3N0TGlzdGVuZXIoJ2ZvY3Vzb3V0JylcclxuICAgIEBIb3N0TGlzdGVuZXIoJ21vdXNlbGVhdmUnKVxyXG4gICAgb25Nb3VzZUxlYXZlKCkge1xyXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnNbJ3RyaWdnZXInXSA9PT0gJ2hvdmVyJykge1xyXG4gICAgICAgICAgICB0aGlzLmRlc3Ryb3lUb29sdGlwKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIEBIb3N0TGlzdGVuZXIoJ2NsaWNrJylcclxuICAgIG9uQ2xpY2soKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNEaXNwbGF5T25DbGljayA9PSBmYWxzZSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLnNob3coKTtcclxuICAgICAgICB0aGlzLmhpZGVBZnRlckNsaWNrVGltZW91dElkID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmRlc3Ryb3lUb29sdGlwKCk7XHJcbiAgICAgICAgfSwgdGhpcy5vcHRpb25zWydoaWRlRGVsYXlBZnRlckNsaWNrJ10pXHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xyXG4gICAgICAgIHRoaXMuaW5pdE9wdGlvbnMgPSB0aGlzLnJlbmFtZVByb3BlcnRpZXModGhpcy5pbml0T3B0aW9ucyk7XHJcbiAgICAgICAgbGV0IGNoYW5nZWRPcHRpb25zID0gdGhpcy5nZXRQcm9wZXJ0aWVzKGNoYW5nZXMpO1xyXG4gICAgICAgIGNoYW5nZWRPcHRpb25zID0gdGhpcy5yZW5hbWVQcm9wZXJ0aWVzKGNoYW5nZWRPcHRpb25zKTtcclxuXHJcbiAgICAgICAgdGhpcy5hcHBseU9wdGlvbnNEZWZhdWx0KGRlZmF1bHRPcHRpb25zLCBjaGFuZ2VkT3B0aW9ucyk7XHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5kZXN0cm95VG9vbHRpcCh7XHJcbiAgICAgICAgICAgIGZhc3Q6IHRydWVcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuY29tcG9uZW50U3Vic2NyaWJlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50U3Vic2NyaWJlLnVuc3Vic2NyaWJlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGdldFNob3dEZWxheSgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zWydzaG93RGVsYXknXTtcclxuICAgIH1cclxuXHJcbiAgICBnZXRIaWRlRGVsYXkoKSB7XHJcbiAgICAgICAgY29uc3QgaGlkZURlbGF5ID0gdGhpcy5vcHRpb25zWydoaWRlRGVsYXknXTtcclxuICAgICAgICBjb25zdCBoaWRlRGVsYXlUb3VjaHNjcmVlbiA9IHRoaXMub3B0aW9uc1snaGlkZURlbGF5VG91Y2hzY3JlZW4nXTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNUb3VjaFNjcmVlbiA/IGhpZGVEZWxheVRvdWNoc2NyZWVuIDogaGlkZURlbGF5O1xyXG4gICAgfVxyXG5cclxuICAgIGdldFByb3BlcnRpZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xyXG4gICAgICAgIGxldCBkaXJlY3RpdmVQcm9wZXJ0aWVzOiBhbnkgPSB7fTtcclxuICAgICAgICBsZXQgY3VzdG9tUHJvcGVydGllczogYW55ID0ge307XHJcbiAgICAgICAgbGV0IGFsbFByb3BlcnRpZXM6IGFueSA9IHt9O1xyXG5cclxuICAgICAgICBmb3IgKHZhciBwcm9wIGluIGNoYW5nZXMpIHtcclxuICAgICAgICAgICAgaWYgKHByb3AgIT09ICdvcHRpb25zJyAmJiBwcm9wICE9PSAndG9vbHRpcFZhbHVlJykge1xyXG4gICAgICAgICAgICAgICAgZGlyZWN0aXZlUHJvcGVydGllc1twcm9wXSA9IGNoYW5nZXNbcHJvcF0uY3VycmVudFZhbHVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChwcm9wID09PSAnb3B0aW9ucycpIHtcclxuICAgICAgICAgICAgICAgIGN1c3RvbVByb3BlcnRpZXMgPSBjaGFuZ2VzW3Byb3BdLmN1cnJlbnRWYWx1ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYWxsUHJvcGVydGllcyA9IE9iamVjdC5hc3NpZ24oe30sIGN1c3RvbVByb3BlcnRpZXMsIGRpcmVjdGl2ZVByb3BlcnRpZXMpO1xyXG4gICAgICAgIHJldHVybiBhbGxQcm9wZXJ0aWVzO1xyXG4gICAgfVxyXG5cclxuICAgIHJlbmFtZVByb3BlcnRpZXMob3B0aW9uczogYW55KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIGlmIChiYWNrd2FyZENvbXBhdGliaWxpdHlPcHRpb25zW3Byb3BdKSB7XHJcbiAgICAgICAgICAgICAgICBvcHRpb25zW2JhY2t3YXJkQ29tcGF0aWJpbGl0eU9wdGlvbnNbcHJvcF1dID0gb3B0aW9uc1twcm9wXTtcclxuICAgICAgICAgICAgICAgIGRlbGV0ZSBvcHRpb25zW3Byb3BdO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gb3B0aW9ucztcclxuICAgIH1cclxuXHJcbiAgICBnZXRFbGVtZW50UG9zaXRpb24oKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5lbGVtZW50UG9zaXRpb24gPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgIH1cclxuXHJcbiAgICBjcmVhdGVUb29sdGlwKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuY2xlYXJUaW1lb3V0cygpO1xyXG4gICAgICAgIHRoaXMuZ2V0RWxlbWVudFBvc2l0aW9uKCk7XHJcblxyXG4gICAgICAgIHRoaXMuY3JlYXRlVGltZW91dElkID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmFwcGVuZENvbXBvbmVudFRvQm9keShUb29sdGlwQ29tcG9uZW50KTtcclxuICAgICAgICB9LCB0aGlzLmdldFNob3dEZWxheSgpKTtcclxuXHJcbiAgICAgICAgdGhpcy5zaG93VGltZW91dElkID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnNob3dUb29sdGlwRWxlbSgpO1xyXG4gICAgICAgIH0sIHRoaXMuZ2V0U2hvd0RlbGF5KCkpO1xyXG4gICAgfVxyXG5cclxuICAgIGRlc3Ryb3lUb29sdGlwKG9wdGlvbnMgPSB7XHJcbiAgICAgICAgZmFzdDogZmFsc2VcclxuICAgIH0pOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmNsZWFyVGltZW91dHMoKTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuaXNUb29sdGlwRGVzdHJveWVkID09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuaGlkZVRpbWVvdXRJZCA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuaGlkZVRvb2x0aXAoKTtcclxuICAgICAgICAgICAgfSwgb3B0aW9ucy5mYXN0ID8gMCA6IHRoaXMuZ2V0SGlkZURlbGF5KCkpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5kZXN0cm95VGltZW91dElkID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbXBvbmVudFJlZiB8fCB0aGlzLmlzVG9vbHRpcERlc3Ryb3llZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLmFwcFJlZi5kZXRhY2hWaWV3KHRoaXMuY29tcG9uZW50UmVmLmhvc3RWaWV3KTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY29tcG9uZW50UmVmLmRlc3Ryb3koKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRzLmVtaXQoe1xyXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdoaWRkZW4nLFxyXG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiB0aGlzLnRvb2x0aXBQb3NpdGlvblxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0sIG9wdGlvbnMuZmFzdCA/IDAgOiB0aGlzLmRlc3Ryb3lEZWxheSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHNob3dUb29sdGlwRWxlbSgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmNsZWFyVGltZW91dHMoKTtcclxuICAgICAgICAoPEFkQ29tcG9uZW50PnRoaXMuY29tcG9uZW50UmVmLmluc3RhbmNlKS5zaG93ID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmV2ZW50cy5lbWl0KHtcclxuICAgICAgICAgICAgdHlwZTogJ3Nob3cnLFxyXG4gICAgICAgICAgICBwb3NpdGlvbjogdGhpcy50b29sdGlwUG9zaXRpb25cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBoaWRlVG9vbHRpcCgpOiB2b2lkIHtcclxuICAgICAgICBpZiAoIXRoaXMuY29tcG9uZW50UmVmIHx8IHRoaXMuaXNUb29sdGlwRGVzdHJveWVkKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgKDxBZENvbXBvbmVudD50aGlzLmNvbXBvbmVudFJlZi5pbnN0YW5jZSkuc2hvdyA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuZXZlbnRzLmVtaXQoe1xyXG4gICAgICAgICAgICB0eXBlOiAnaGlkZScsXHJcbiAgICAgICAgICAgIHBvc2l0aW9uOiB0aGlzLnRvb2x0aXBQb3NpdGlvblxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGFwcGVuZENvbXBvbmVudFRvQm9keShjb21wb25lbnQ6IGFueSwgZGF0YTogYW55ID0ge30pOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmNvbXBvbmVudFJlZiA9IHRoaXMuY29tcG9uZW50RmFjdG9yeVJlc29sdmVyXHJcbiAgICAgICAgICAgIC5yZXNvbHZlQ29tcG9uZW50RmFjdG9yeShjb21wb25lbnQpXHJcbiAgICAgICAgICAgIC5jcmVhdGUodGhpcy5pbmplY3Rvcik7XHJcblxyXG4gICAgICAgICg8QWRDb21wb25lbnQ+dGhpcy5jb21wb25lbnRSZWYuaW5zdGFuY2UpLmRhdGEgPSB7XHJcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLnRvb2x0aXBWYWx1ZSxcclxuICAgICAgICAgICAgZWxlbWVudDogdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXHJcbiAgICAgICAgICAgIGVsZW1lbnRQb3NpdGlvbjogdGhpcy50b29sdGlwUG9zaXRpb24sXHJcbiAgICAgICAgICAgIG9wdGlvbnM6IHRoaXMub3B0aW9uc1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmFwcFJlZi5hdHRhY2hWaWV3KHRoaXMuY29tcG9uZW50UmVmLmhvc3RWaWV3KTtcclxuICAgICAgICBjb25zdCBkb21FbGVtID0gKHRoaXMuY29tcG9uZW50UmVmLmhvc3RWaWV3IGFzIEVtYmVkZGVkVmlld1JlZjxhbnk+KS5yb290Tm9kZXNbMF0gYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkb21FbGVtKTtcclxuXHJcbiAgICAgICAgdGhpcy5jb21wb25lbnRTdWJzY3JpYmUgPSAoPEFkQ29tcG9uZW50PnRoaXMuY29tcG9uZW50UmVmLmluc3RhbmNlKS5ldmVudHMuc3Vic2NyaWJlKChldmVudDogYW55KSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRXZlbnRzKGV2ZW50KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBjbGVhclRpbWVvdXRzKCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLmNyZWF0ZVRpbWVvdXRJZCkge1xyXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5jcmVhdGVUaW1lb3V0SWQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuc2hvd1RpbWVvdXRJZCkge1xyXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5zaG93VGltZW91dElkKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmhpZGVUaW1lb3V0SWQpIHtcclxuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuaGlkZVRpbWVvdXRJZCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5kZXN0cm95VGltZW91dElkKSB7XHJcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmRlc3Ryb3lUaW1lb3V0SWQpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBnZXQgaXNEaXNwbGF5T25Ib3ZlcigpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAodGhpcy5vcHRpb25zWydkaXNwbGF5J10gPT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMub3B0aW9uc1snZGlzcGxheVRvdWNoc2NyZWVuJ10gPT0gZmFsc2UgJiYgdGhpcy5pc1RvdWNoU2NyZWVuKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLm9wdGlvb