igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
756 lines • 64.4 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Directive, ElementRef, HostListener, Input, NgModule, ChangeDetectorRef, Output, EventEmitter, Optional, HostBinding, Inject } from '@angular/core';
import { useAnimation } from '@angular/animations';
import { scaleInCenter } from '../../animations/scale/index';
import { fadeOut } from '../../animations/fade/index';
import { IgxOverlayService } from '../../services/overlay/overlay';
import { HorizontalAlignment, AutoPositionStrategy } from '../../services';
import { CommonModule } from '@angular/common';
import { IgxNavigationService } from '../../core/navigation';
import { IgxToggleDirective, IgxToggleActionDirective } from '../toggle/toggle.directive';
/**
* @record
*/
export function ITooltipShowEventArgs() { }
if (false) {
/** @type {?} */
ITooltipShowEventArgs.prototype.target;
/** @type {?} */
ITooltipShowEventArgs.prototype.tooltip;
/** @type {?} */
ITooltipShowEventArgs.prototype.cancel;
}
/**
* @record
*/
export function ITooltipHideEventArgs() { }
if (false) {
/** @type {?} */
ITooltipHideEventArgs.prototype.target;
/** @type {?} */
ITooltipHideEventArgs.prototype.tooltip;
/** @type {?} */
ITooltipHideEventArgs.prototype.cancel;
}
/**
* **Ignite UI for Angular Tooltip Target** -
* [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/tooltip.html)
*
* The Ignite UI for Angular Tooltip Target directive is used to mark an HTML element in the markup as one that has a tooltip.
* The tooltip target is used in combination with the Ignite UI for Angular Tooltip by assigning the exported tooltip reference to the
* target's selector property.
*
* Example:
* ```html
* <button [igxTooltipTarget]="tooltipRef">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
export class IgxTooltipTargetDirective extends IgxToggleActionDirective {
/**
* @param {?} _element
* @param {?} _navigationService
*/
constructor(_element, _navigationService) {
super(_element, _navigationService);
this._element = _element;
this._navigationService = _navigationService;
/**
* Gets/sets the amount of milliseconds that should pass before showing the tooltip.
*
* ```typescript
* // get
* let tooltipShowDelay = this.tooltipTarget.showDelay;
* ```
*
* ```html
* <!--set-->
* <button [igxTooltipTarget]="tooltipRef" showDelay="1500">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.showDelay = 500;
/**
* Gets/sets the amount of milliseconds that should pass before hiding the tooltip.
*
* ```typescript
* // get
* let tooltipHideDelay = this.tooltipTarget.hideDelay;
* ```
*
* ```html
* <!--set-->
* <button [igxTooltipTarget]="tooltipRef" hideDelay="1500">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.hideDelay = 500;
/**
* Specifies if the tooltip should not show when hovering its target with the mouse. (defaults to false)
* While setting this property to 'true' will disable the user interactions that shows/hides the tooltip,
* the developer will still be able to show/hide the tooltip through the API.
*
* ```typescript
* // get
* let tooltipDisabledValue = this.tooltipTarget.tooltipDisabled;
* ```
*
* ```html
* <!--set-->
* <button [igxTooltipTarget]="tooltipRef" [tooltipDisabled]="true">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.tooltipDisabled = false;
/**
* Emits an event when the tooltip that is associated with this target starts showing.
* This event is fired before the start of the countdown to showing the tooltip.
*
* ```typescript
* tooltipShowing(args: ITooltipShowEventArgs) {
* alert("Tooltip started showing!");
* }
* ```
*
* ```html
* <button [igxTooltipTarget]="tooltipRef"
* (onTooltipShow)='tooltipShowing($event)'>Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.onTooltipShow = new EventEmitter();
/**
* Emits an event when the tooltip that is associated with this target starts hiding.
* This event is fired before the start of the countdown to hiding the tooltip.
*
* ```typescript
* tooltipHiding(args: ITooltipHideEventArgs) {
* alert("Tooltip started hiding!");
* }
* ```
*
* ```html
* <button [igxTooltipTarget]="tooltipRef"
* (onTooltipHide)='tooltipHiding($event)'>Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.onTooltipHide = new EventEmitter();
}
/**
* @hidden
* @param {?} target
* @return {?}
*/
set target(target) {
if (target !== null && target !== '') {
this._target = target;
}
}
/**
* @hidden
* @return {?}
*/
get target() {
if (typeof this._target === 'string') {
return this._navigationService.get(this._target);
}
return this._target;
}
/**
* Gets the respective native element of the directive.
*
* ```typescript
* let tooltipTargetElement = this.tooltipTarget.nativeElement;
* ```
* @return {?}
*/
get nativeElement() {
return this._element.nativeElement;
}
/**
* Indicates if the tooltip that is is associated with this target is currently hidden.
*
* ```typescript
* let tooltipHiddenValue = this.tooltipTarget.tooltipHidden;
* ```
* @return {?}
*/
get tooltipHidden() {
return !this.target || this.target.collapsed;
}
/**
* @hidden
* @return {?}
*/
ngOnInit() {
super.ngOnInit();
/** @type {?} */
const positionSettings = {
target: this.nativeElement,
horizontalDirection: HorizontalAlignment.Center,
horizontalStartPoint: HorizontalAlignment.Center,
openAnimation: useAnimation(scaleInCenter, { params: { duration: '150ms' } }),
closeAnimation: useAnimation(fadeOut, { params: { duration: '75ms' } })
};
this._overlayDefaults.positionStrategy = new AutoPositionStrategy(positionSettings);
this._overlayDefaults.closeOnOutsideClick = false;
}
/**
* @private
* @return {?}
*/
checkOutletAndOutsideClick() {
if (this.closeOnOutsideClick !== undefined) {
this._overlayDefaults.closeOnOutsideClick = this.closeOnOutsideClick;
}
if (this.outlet) {
this._overlayDefaults.outlet = this.outlet;
}
}
/**
* @private
* @return {?}
*/
get mergedOverlaySettings() {
return Object.assign({}, this._overlayDefaults, this.overlaySettings);
}
// Return true if the execution in onMouseEnter should be terminated after this method
/**
* @private
* @return {?}
*/
preMouseEnterCheck() {
// If tooltip is about to be opened
if (this.target.toBeShown) {
clearTimeout(this.target.timeoutId);
this.target.toBeShown = false;
}
// If Tooltip is opened or about to be hidden
if (!this.target.collapsed || this.target.toBeHidden) {
clearTimeout(this.target.timeoutId);
/** @type {?} */
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return true;
}
// if close animation has started finish it, or close the tooltip with no animation
this.target.forceClose(this.mergedOverlaySettings);
this.target.toBeHidden = false;
}
return false;
}
// Return true if the execution in onMouseLeave should be terminated after this method
/**
* @private
* @return {?}
*/
preMouseLeaveCheck() {
clearTimeout(this.target.timeoutId);
// If tooltip is about to be opened
if (this.target.toBeShown) {
this.target.toBeShown = false;
this.target.toBeHidden = false;
return true;
}
return false;
}
/**
* @hidden
* @return {?}
*/
onKeydownEscape() {
/** @type {?} */
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
this.target.toBeHidden = true;
this.target.close();
this.target.toBeHidden = false;
}
/**
* @hidden
* @return {?}
*/
onClick() {
if (!this.target.collapsed) {
/** @type {?} */
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
this.target.forceClose(this.mergedOverlaySettings);
}
}
/**
* @hidden
* @return {?}
*/
onMouseEnter() {
if (this.tooltipDisabled) {
return;
}
this.checkOutletAndOutsideClick();
/** @type {?} */
const shouldReturn = this.preMouseEnterCheck();
if (shouldReturn) {
return;
}
/** @type {?} */
const showingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipShow.emit(showingArgs);
if (showingArgs.cancel) {
return;
}
this.target.toBeShown = true;
this.target.timeoutId = setTimeout(() => {
this.target.open(this.mergedOverlaySettings); // Call open() of IgxTooltipDirective
this.target.toBeShown = false;
}, this.showDelay);
}
/**
* @hidden
* @return {?}
*/
onMouseLeave() {
if (this.tooltipDisabled) {
return;
}
this.checkOutletAndOutsideClick();
/** @type {?} */
const shouldReturn = this.preMouseLeaveCheck();
if (shouldReturn || this.target.collapsed) {
return;
}
/** @type {?} */
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
this.target.toBeHidden = true;
this.target.timeoutId = setTimeout(() => {
this.target.close(); // Call close() of IgxTooltipDirective
this.target.toBeHidden = false;
}, this.hideDelay);
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onTouchStart(event) {
if (this.tooltipDisabled) {
return;
}
event.preventDefault();
this.showTooltip();
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onDocumentTouchStart(event) {
if (this.tooltipDisabled) {
return;
}
if (this.nativeElement !== event.target &&
!this.nativeElement.contains(event.target)) {
this.hideTooltip();
}
}
/**
* Shows the tooltip by respecting the 'showDelay' property.
*
* ```typescript
* this.tooltipTarget.showTooltip();
* ```
* @return {?}
*/
showTooltip() {
clearTimeout(this.target.timeoutId);
if (!this.target.collapsed) {
/** @type {?} */
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
// if close animation has started finish it, or close the tooltip with no animation
this.target.forceClose(this.mergedOverlaySettings);
this.target.toBeHidden = false;
}
/** @type {?} */
const showingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipShow.emit(showingArgs);
if (showingArgs.cancel) {
return;
}
this.target.toBeShown = true;
this.target.timeoutId = setTimeout(() => {
this.target.open(this.mergedOverlaySettings); // Call open() of IgxTooltipDirective
this.target.toBeShown = false;
}, this.showDelay);
}
/**
* Hides the tooltip by respecting the 'hideDelay' property.
*
* ```typescript
* this.tooltipTarget.hideTooltip();
* ```
* @return {?}
*/
hideTooltip() {
if (this.target.collapsed && this.target.toBeShown) {
clearTimeout(this.target.timeoutId);
}
if (this.target.collapsed || this.target.toBeHidden) {
return;
}
/** @type {?} */
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
this.target.toBeHidden = true;
this.target.timeoutId = setTimeout(() => {
this.target.close(); // Call close() of IgxTooltipDirective
this.target.toBeHidden = false;
}, this.hideDelay);
}
}
IgxTooltipTargetDirective.decorators = [
{ type: Directive, args: [{
exportAs: 'tooltipTarget',
selector: '[igxTooltipTarget]'
},] }
];
/** @nocollapse */
IgxTooltipTargetDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: IgxNavigationService, decorators: [{ type: Optional }] }
];
IgxTooltipTargetDirective.propDecorators = {
showDelay: [{ type: Input, args: ['showDelay',] }],
hideDelay: [{ type: Input, args: ['hideDelay',] }],
tooltipDisabled: [{ type: Input, args: ['tooltipDisabled',] }],
target: [{ type: Input, args: ['igxTooltipTarget',] }],
onTooltipShow: [{ type: Output }],
onTooltipHide: [{ type: Output }],
onKeydownEscape: [{ type: HostListener, args: ['document:keydown.escape', ['$event'],] }],
onClick: [{ type: HostListener, args: ['click',] }],
onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }],
onTouchStart: [{ type: HostListener, args: ['touchstart', ['$event'],] }],
onDocumentTouchStart: [{ type: HostListener, args: ['document:touchstart', ['$event'],] }]
};
if (false) {
/**
* Gets/sets the amount of milliseconds that should pass before showing the tooltip.
*
* ```typescript
* // get
* let tooltipShowDelay = this.tooltipTarget.showDelay;
* ```
*
* ```html
* <!--set-->
* <button [igxTooltipTarget]="tooltipRef" showDelay="1500">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
* @type {?}
*/
IgxTooltipTargetDirective.prototype.showDelay;
/**
* Gets/sets the amount of milliseconds that should pass before hiding the tooltip.
*
* ```typescript
* // get
* let tooltipHideDelay = this.tooltipTarget.hideDelay;
* ```
*
* ```html
* <!--set-->
* <button [igxTooltipTarget]="tooltipRef" hideDelay="1500">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
* @type {?}
*/
IgxTooltipTargetDirective.prototype.hideDelay;
/**
* Specifies if the tooltip should not show when hovering its target with the mouse. (defaults to false)
* While setting this property to 'true' will disable the user interactions that shows/hides the tooltip,
* the developer will still be able to show/hide the tooltip through the API.
*
* ```typescript
* // get
* let tooltipDisabledValue = this.tooltipTarget.tooltipDisabled;
* ```
*
* ```html
* <!--set-->
* <button [igxTooltipTarget]="tooltipRef" [tooltipDisabled]="true">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
* @type {?}
*/
IgxTooltipTargetDirective.prototype.tooltipDisabled;
/**
* Emits an event when the tooltip that is associated with this target starts showing.
* This event is fired before the start of the countdown to showing the tooltip.
*
* ```typescript
* tooltipShowing(args: ITooltipShowEventArgs) {
* alert("Tooltip started showing!");
* }
* ```
*
* ```html
* <button [igxTooltipTarget]="tooltipRef"
* (onTooltipShow)='tooltipShowing($event)'>Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
* @type {?}
*/
IgxTooltipTargetDirective.prototype.onTooltipShow;
/**
* Emits an event when the tooltip that is associated with this target starts hiding.
* This event is fired before the start of the countdown to hiding the tooltip.
*
* ```typescript
* tooltipHiding(args: ITooltipHideEventArgs) {
* alert("Tooltip started hiding!");
* }
* ```
*
* ```html
* <button [igxTooltipTarget]="tooltipRef"
* (onTooltipHide)='tooltipHiding($event)'>Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
* @type {?}
*/
IgxTooltipTargetDirective.prototype.onTooltipHide;
/**
* @type {?}
* @private
*/
IgxTooltipTargetDirective.prototype._element;
/**
* @type {?}
* @private
*/
IgxTooltipTargetDirective.prototype._navigationService;
}
/** @type {?} */
let NEXT_ID = 0;
/**
* **Ignite UI for Angular Tooltip** -
* [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/tooltip.html)
*
* The Ignite UI for Angular Tooltip directive is used to mark an HTML element in the markup as one that should behave as a tooltip.
* The tooltip is used in combination with the Ignite UI for Angular Tooltip Target by assigning the exported tooltip reference to the
* respective target's selector property.
*
* Example:
* ```html
* <button [igxTooltipTarget]="tooltipRef">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
export class IgxTooltipDirective extends IgxToggleDirective {
/**
* @hidden
* @param {?} elementRef
* @param {?} cdr
* @param {?} overlayService
* @param {?} navigationService
*/
constructor(elementRef, cdr, overlayService, navigationService) {
// D.P. constructor duplication due to es6 compilation, might be obsolete in the future
super(elementRef, cdr, overlayService, navigationService);
/**
* @hidden
* Returns whether close time out has started
*/
this.toBeHidden = false;
/**
* @hidden
* Returns whether open time out has started
*/
this.toBeShown = false;
/**
* Identifier for the tooltip.
* If this is property is not explicitly set, it will be automatically generated.
*
* ```typescript
* let tooltipId = this.tooltip.id;
* ```
*/
this.id = `igx-tooltip-${NEXT_ID++}`;
}
/**
* @hidden
* @return {?}
*/
get hiddenClass() {
return this.collapsed;
}
/**
* @hidden
* @return {?}
*/
get defaultClass() {
return !this.collapsed;
}
/**
* Get the role attribute of the tooltip.
*
* ```typescript
* let tooltipRole = this.tooltip.role;
* ```
* @return {?}
*/
get role() {
return 'tooltip';
}
/**
* If there is open animation in progress this method will finish is.
* If there is no open animation in progress this method will open the toggle with no animation.
* @protected
* @param {?=} overlaySettings setting to use for opening the toggle
* @return {?}
*/
forceOpen(overlaySettings) {
/** @type {?} */
const info = this.overlayService.getOverlayById(this._overlayId);
/** @type {?} */
const hasOpenAnimation = info ? info.openAnimationPlayer : false;
if (hasOpenAnimation) {
info.openAnimationPlayer.finish();
info.openAnimationPlayer.reset();
info.openAnimationPlayer = null;
}
else if (this.collapsed) {
/** @type {?} */
const animation = overlaySettings.positionStrategy.settings.openAnimation;
overlaySettings.positionStrategy.settings.openAnimation = null;
this.open(overlaySettings);
overlaySettings.positionStrategy.settings.openAnimation = animation;
}
}
/**
* If there is close animation in progress this method will finish is.
* If there is no close animation in progress this method will close the toggle with no animation.
* @protected
* @param {?=} overlaySettings settings to use for closing the toggle
* @return {?}
*/
forceClose(overlaySettings) {
/** @type {?} */
const info = this.overlayService.getOverlayById(this._overlayId);
/** @type {?} */
const hasCloseAnimation = info ? info.closeAnimationPlayer : false;
if (hasCloseAnimation) {
info.closeAnimationPlayer.finish();
info.closeAnimationPlayer.reset();
info.closeAnimationPlayer = null;
}
else if (!this.collapsed) {
/** @type {?} */
const animation = overlaySettings.positionStrategy.settings.closeAnimation;
overlaySettings.positionStrategy.settings.closeAnimation = null;
this.close();
overlaySettings.positionStrategy.settings.closeAnimation = animation;
}
}
}
IgxTooltipDirective.decorators = [
{ type: Directive, args: [{
exportAs: 'tooltip',
selector: '[igxTooltip]'
},] }
];
/** @nocollapse */
IgxTooltipDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: ChangeDetectorRef },
{ type: IgxOverlayService, decorators: [{ type: Inject, args: [IgxOverlayService,] }] },
{ type: IgxNavigationService, decorators: [{ type: Optional }] }
];
IgxTooltipDirective.propDecorators = {
hiddenClass: [{ type: HostBinding, args: ['class.igx-tooltip--hidden',] }],
defaultClass: [{ type: HostBinding, args: ['class.igx-tooltip--desktop',] }],
context: [{ type: Input, args: ['context',] }],
id: [{ type: HostBinding, args: ['attr.id',] }, { type: Input }],
role: [{ type: HostBinding, args: ['attr.role',] }]
};
if (false) {
/**
* @hidden
* @type {?}
*/
IgxTooltipDirective.prototype.timeoutId;
/**
* @hidden
* Returns whether close time out has started
* @type {?}
*/
IgxTooltipDirective.prototype.toBeHidden;
/**
* @hidden
* Returns whether open time out has started
* @type {?}
*/
IgxTooltipDirective.prototype.toBeShown;
/**
* Gets/sets any tooltip related data.
* The 'context' can be used for storing any information that is necessary
* to access when working with the tooltip.
*
* ```typescript
* // get
* let tooltipContext = this.tooltip.context;
* ```
*
* ```typescript
* // set
* this.tooltip.context = "Tooltip's context";
* ```
* @type {?}
*/
IgxTooltipDirective.prototype.context;
/**
* Identifier for the tooltip.
* If this is property is not explicitly set, it will be automatically generated.
*
* ```typescript
* let tooltipId = this.tooltip.id;
* ```
* @type {?}
*/
IgxTooltipDirective.prototype.id;
}
/**
* @hidden
*/
export class IgxTooltipModule {
}
IgxTooltipModule.decorators = [
{ type: NgModule, args: [{
declarations: [IgxTooltipDirective, IgxTooltipTargetDirective],
exports: [IgxTooltipDirective, IgxTooltipTargetDirective],
imports: [CommonModule],
providers: [IgxOverlayService]
},] }
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHRpcC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9pZ25pdGV1aS1hbmd1bGFyLyIsInNvdXJjZXMiOlsibGliL2RpcmVjdGl2ZXMvdG9vbHRpcC90b29sdGlwLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNILFNBQVMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsaUJBQWlCLEVBQ3ZFLE1BQU0sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBYSxNQUFNLEVBQ2pFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDN0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxvQkFBb0IsRUFBcUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5RyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLHdCQUF3QixFQUFFLE1BQU0sNEJBQTRCLENBQUM7Ozs7QUFHMUYsMkNBSUM7OztJQUhHLHVDQUFrQzs7SUFDbEMsd0NBQTZCOztJQUM3Qix1Q0FBZ0I7Ozs7O0FBRXBCLDJDQUlDOzs7SUFIRyx1Q0FBa0M7O0lBQ2xDLHdDQUE2Qjs7SUFDN0IsdUNBQWdCOzs7Ozs7Ozs7Ozs7Ozs7O0FBcUJwQixNQUFNLE9BQU8seUJBQTBCLFNBQVEsd0JBQXdCOzs7OztJQXNJbkUsWUFBb0IsUUFBb0IsRUFDaEIsa0JBQXdDO1FBQzVELEtBQUss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LFNBQUMsU0FBUztpQkFXZixXQUFXLFNBQUMsU0FBUyxjQUNyQixLQUFLO21CQVVMLFdBQVcsU0FBQyxXQUFXOzs7Ozs7O0lBbkV4Qix3Q0FBaUI7Ozs7OztJQU1qQix5Q0FBMEI7Ozs7OztJQU0xQix3Q0FBeUI7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBaUN6QixzQ0FDZTs7Ozs7Ozs7OztJQVVmLGlDQUV1Qzs7Ozs7QUEyRTNDLE1BQU0sT0FBTyxnQkFBZ0I7OztZQU41QixRQUFRLFNBQUM7Z0JBQ04sWUFBWSxFQUFFLENBQUMsbUJBQW1CLEVBQUUseUJBQXlCLENBQUM7Z0JBQzlELE9BQU8sRUFBRSxDQUFDLG1CQUFtQixFQUFFLHlCQUF5QixDQUFDO2dCQUN6RCxPQUFPLEVBQUUsQ0FBQyxZQUFZLENBQUM7Z0JBQ3ZCLFNBQVMsRUFBRSxDQUFDLGlCQUFpQixDQUFDO2FBQ2pDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBEaXJlY3RpdmUsIEVsZW1lbnRSZWYsIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE5nTW9kdWxlLCBDaGFuZ2VEZXRlY3RvclJlZiwgT25Jbml0LFxuICAgIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBPcHRpb25hbCwgSG9zdEJpbmRpbmcsIE9uRGVzdHJveSwgSW5qZWN0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdXNlQW5pbWF0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvYW5pbWF0aW9ucyc7XG5pbXBvcnQgeyBzY2FsZUluQ2VudGVyIH0gZnJvbSAnLi4vLi4vYW5pbWF0aW9ucy9zY2FsZS9pbmRleCc7XG5pbXBvcnQgeyBmYWRlT3V0IH0gZnJvbSAnLi4vLi4vYW5pbWF0aW9ucy9mYWRlL2luZGV4JztcbmltcG9ydCB7IElneE92ZXJsYXlTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvb3ZlcmxheS9vdmVybGF5JztcbmltcG9ydCB7IEhvcml6b250YWxBbGlnbm1lbnQsIEF1dG9Qb3NpdGlvblN0cmF0ZWd5LCBQb3NpdGlvblNldHRpbmdzLCBPdmVybGF5U2V0dGluZ3MgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcyc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgSWd4TmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb3JlL25hdmlnYXRpb24nO1xuaW1wb3J0IHsgSWd4VG9nZ2xlRGlyZWN0aXZlLCBJZ3hUb2dnbGVBY3Rpb25EaXJlY3RpdmUgfSBmcm9tICcuLi90b2dnbGUvdG9nZ2xlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuZXhwb3J0IGludGVyZmFjZSBJVG9vbHRpcFNob3dFdmVudEFyZ3Mge1xuICAgIHRhcmdldDogSWd4VG9vbHRpcFRhcmdldERpcmVjdGl2ZTtcbiAgICB0b29sdGlwOiBJZ3hUb29sdGlwRGlyZWN0aXZlO1xuICAgIGNhbmNlbDogYm9vbGVhbjtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgSVRvb2x0aXBIaWRlRXZlbnRBcmdzIHtcbiAgICB0YXJnZXQ6IElneFRvb2x0aXBUYXJnZXREaXJlY3RpdmU7XG4gICAgdG9vbHRpcDogSWd4VG9vbHRpcERpcmVjdGl2ZTtcbiAgICBjYW5jZWw6IGJvb2xlYW47XG59XG5cbi8qKlxuICogKipJZ25pdGUgVUkgZm9yIEFuZ3VsYXIgVG9vbHRpcCBUYXJnZXQqKiAtXG4gKiBbRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuaW5mcmFnaXN0aWNzLmNvbS9wcm9kdWN0cy9pZ25pdGUtdWktYW5ndWxhci9hbmd1bGFyL2NvbXBvbmVudHMvdG9vbHRpcC5odG1sKVxuICpcbiAqIFRoZSBJZ25pdGUgVUkgZm9yIEFuZ3VsYXIgVG9vbHRpcCBUYXJnZXQgZGlyZWN0aXZlIGlzIHVzZWQgdG8gbWFyayBhbiBIVE1MIGVsZW1lbnQgaW4gdGhlIG1hcmt1cCBhcyBvbmUgdGhhdCBoYXMgYSB0b29sdGlwLlxuICogVGhlIHRvb2x0aXAgdGFyZ2V0IGlzIHVzZWQgaW4gY29tYmluYXRpb24gd2l0aCB0aGUgSWduaXRlIFVJIGZvciBBbmd1bGFyIFRvb2x0aXAgYnkgYXNzaWduaW5nIHRoZSBleHBvcnRlZCB0b29sdGlwIHJlZmVyZW5jZSB0byB0aGVcbiAqIHRhcmdldCdzIHNlbGVjdG9yIHByb3BlcnR5LlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGBodG1sXG4gKiA8YnV0dG9uIFtpZ3hUb29sdGlwVGFyZ2V0XT1cInRvb2x0aXBSZWZcIj5Ib3ZlciBtZTwvYnV0dG9uPlxuICogPHNwYW4gI3Rvb2x0aXBSZWY9XCJ0b29sdGlwXCIgaWd4VG9vbHRpcD5IZWxsbyB0aGVyZSwgSSBhbSBhIHRvb2x0aXAhPC9zcGFuPlxuICogYGBgXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIGV4cG9ydEFzOiAndG9vbHRpcFRhcmdldCcsXG4gICAgc2VsZWN0b3I6ICdbaWd4VG9vbHRpcFRhcmdldF0nXG59KVxuZXhwb3J0IGNsYXNzIElneFRvb2x0aXBUYXJnZXREaXJlY3RpdmUgZXh0ZW5kcyBJZ3hUb2dnbGVBY3Rpb25EaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQge1xuICAgIC8qKlxuICAgICAqIEdldHMvc2V0cyB0aGUgYW1vdW50IG9mIG1pbGxpc2Vjb25kcyB0aGF0IHNob3VsZCBwYXNzIGJlZm9yZSBzaG93aW5nIHRoZSB0b29sdGlwLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIC8vIGdldFxuICAgICAqIGxldCB0b29sdGlwU2hvd0RlbGF5ID0gdGhpcy50b29sdGlwVGFyZ2V0LnNob3dEZWxheTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8IS0tc2V0LS0+XG4gICAgICogPGJ1dHRvbiBbaWd4VG9vbHRpcFRhcmdldF09XCJ0b29sdGlwUmVmXCIgc2hvd0RlbGF5PVwiMTUwMFwiPkhvdmVyIG1lPC9idXR0b24+XG4gICAgICogPHNwYW4gI3Rvb2x0aXBSZWY9XCJ0b29sdGlwXCIgaWd4VG9vbHRpcD5IZWxsbyB0aGVyZSwgSSBhbSBhIHRvb2x0aXAhPC9zcGFuPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgnc2hvd0RlbGF5JylcbiAgICBwdWJsaWMgc2hvd0RlbGF5ID0gNTAwO1xuXG4gICAgLyoqXG4gICAgICogR2V0cy9zZXRzIHRoZSBhbW91bnQgb2YgbWlsbGlzZWNvbmRzIHRoYXQgc2hvdWxkIHBhc3MgYmVmb3JlIGhpZGluZyB0aGUgdG9vbHRpcC5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiAvLyBnZXRcbiAgICAgKiBsZXQgdG9vbHRpcEhpZGVEZWxheSA9IHRoaXMudG9vbHRpcFRhcmdldC5oaWRlRGVsYXk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgYGBodG1sXG4gICAgICogPCEtLXNldC0tPlxuICAgICAqIDxidXR0b24gW2lneFRvb2x0aXBUYXJnZXRdPVwidG9vbHRpcFJlZlwiIGhpZGVEZWxheT1cIjE1MDBcIj5Ib3ZlciBtZTwvYnV0dG9uPlxuICAgICAqIDxzcGFuICN0b29sdGlwUmVmPVwidG9vbHRpcFwiIGlneFRvb2x0aXA+SGVsbG8gdGhlcmUsIEkgYW0gYSB0b29sdGlwITwvc3Bhbj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoJ2hpZGVEZWxheScpXG4gICAgcHVibGljIGhpZGVEZWxheSA9IDUwMDtcblxuICAgIC8qKlxuICAgICAqIFNwZWNpZmllcyBpZiB0aGUgdG9vbHRpcCBzaG91bGQgbm90IHNob3cgd2hlbiBob3ZlcmluZyBpdHMgdGFyZ2V0IHdpdGggdGhlIG1vdXNlLiAoZGVmYXVsdHMgdG8gZmFsc2UpXG4gICAgICogV2hpbGUgc2V0dGluZyB0aGlzIHByb3BlcnR5IHRvICd0cnVlJyB3aWxsIGRpc2FibGUgdGhlIHVzZXIgaW50ZXJhY3Rpb25zIHRoYXQgc2hvd3MvaGlkZXMgdGhlIHRvb2x0aXAsXG4gICAgICogdGhlIGRldmVsb3BlciB3aWxsIHN0aWxsIGJlIGFibGUgdG8gc2hvdy9oaWRlIHRoZSB0b29sdGlwIHRocm91Z2ggdGhlIEFQSS5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiAvLyBnZXRcbiAgICAgKiBsZXQgdG9vbHRpcERpc2FibGVkVmFsdWUgPSB0aGlzLnRvb2x0aXBUYXJnZXQudG9vbHRpcERpc2FibGVkO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDwhLS1zZXQtLT5cbiAgICAgKiA8YnV0dG9uIFtpZ3hUb29sdGlwVGFyZ2V0XT1cInRvb2x0aXBSZWZcIiBbdG9vbHRpcERpc2FibGVkXT1cInRydWVcIj5Ib3ZlciBtZTwvYnV0dG9uPlxuICAgICAqIDxzcGFuICN0b29sdGlwUmVmPVwidG9vbHRpcFwiIGlneFRvb2x0aXA+SGVsbG8gdGhlcmUsIEkgYW0gYSB0b29sdGlwITwvc3Bhbj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoJ3Rvb2x0aXBEaXNhYmxlZCcpXG4gICAgcHVibGljIHRvb2x0aXBEaXNhYmxlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIEBJbnB1dCgnaWd4VG9vbHRpcFRhcmdldCcpXG4gICAgc2V0IHRhcmdldCh0YXJnZXQ6IGFueSkge1xuICAgICAgICBpZiAodGFyZ2V0ICE9PSBudWxsICYmIHRhcmdldCAhPT0gJycpIHtcbiAgICAgICAgICAgIHRoaXMuX3RhcmdldCA9IHRhcmdldDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXQgdGFyZ2V0KCk6IGFueSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5fdGFyZ2V0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX25hdmlnYXRpb25TZXJ2aWNlLmdldCh0aGlzLl90YXJnZXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl90YXJnZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmVzcGVjdGl2ZSBuYXRpdmUgZWxlbWVudCBvZiB0aGUgZGlyZWN0aXZlLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGxldCB0b29sdGlwVGFyZ2V0RWxlbWVudCA9IHRoaXMudG9vbHRpcFRhcmdldC5uYXRpdmVFbGVtZW50O1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgbmF0aXZlRWxlbWVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgaWYgdGhlIHRvb2x0aXAgdGhhdCBpcyBpcyBhc3NvY2lhdGVkIHdpdGggdGhpcyB0YXJnZXQgaXMgY3VycmVudGx5IGhpZGRlbi5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgdG9vbHRpcEhpZGRlblZhbHVlID0gdGhpcy50b29sdGlwVGFyZ2V0LnRvb2x0aXBIaWRkZW47XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldCB0b29sdGlwSGlkZGVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gIXRoaXMudGFyZ2V0IHx8IHRoaXMudGFyZ2V0LmNvbGxhcHNlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSB0b29sdGlwIHRoYXQgaXMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFyZ2V0IHN0YXJ0cyBzaG93aW5nLlxuICAgICAqIFRoaXMgZXZlbnQgaXMgZmlyZWQgYmVmb3JlIHRoZSBzdGFydCBvZiB0aGUgY291bnRkb3duIHRvIHNob3dpbmcgdGhlIHRvb2x0aXAuXG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdG9vbHRpcFNob3dpbmcoYXJnczogSVRvb2x0aXBTaG93RXZlbnRBcmdzKSB7XG4gICAgICogICAgYWxlcnQoXCJUb29sdGlwIHN0YXJ0ZWQgc2hvd2luZyFcIik7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxidXR0b24gW2lneFRvb2x0aXBUYXJnZXRdPVwidG9vbHRpcFJlZlwiXG4gICAgICogICAgICAgICAob25Ub29sdGlwU2hvdyk9J3Rvb2x0aXBTaG93aW5nKCRldmVudCknPkhvdmVyIG1lPC9idXR0b24+XG4gICAgICogPHNwYW4gI3Rvb2x0aXBSZWY9XCJ0b29sdGlwXCIgaWd4VG9vbHRpcD5IZWxsbyB0aGVyZSwgSSBhbSBhIHRvb2x0aXAhPC9zcGFuPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvblRvb2x0aXBTaG93ID0gbmV3IEV2ZW50RW1pdHRlcjxJVG9vbHRpcFNob3dFdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSB0b29sdGlwIHRoYXQgaXMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFyZ2V0IHN0YXJ0cyBoaWRpbmcuXG4gICAgICogVGhpcyBldmVudCBpcyBmaXJlZCBiZWZvcmUgdGhlIHN0YXJ0IG9mIHRoZSBjb3VudGRvd24gdG8gaGlkaW5nIHRoZSB0b29sdGlwLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRvb2x0aXBIaWRpbmcoYXJnczogSVRvb2x0aXBIaWRlRXZlbnRBcmdzKSB7XG4gICAgICogICAgYWxlcnQoXCJUb29sdGlwIHN0YXJ0ZWQgaGlkaW5nIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgYGBodG1sXG4gICAgICogPGJ1dHRvbiBbaWd4VG9vbHRpcFRhcmdldF09XCJ0b29sdGlwUmVmXCJcbiAgICAgKiAgICAgICAgIChvblRvb2x0aXBIaWRlKT0ndG9vbHRpcEhpZGluZygkZXZlbnQpJz5Ib3ZlciBtZTwvYnV0dG9uPlxuICAgICAqIDxzcGFuICN0b29sdGlwUmVmPVwidG9vbHRpcFwiIGlneFRvb2x0aXA+SGVsbG8gdGhlcmUsIEkgYW0gYSB0b29sdGlwITwvc3Bhbj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25Ub29sdGlwSGlkZSA9IG5ldyBFdmVudEVtaXR0ZXI8SVRvb2x0aXBIaWRlRXZlbnRBcmdzPigpO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBfZWxlbWVudDogRWxlbWVudFJlZixcbiAgICAgICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBfbmF2aWdhdGlvblNlcnZpY2U6IElneE5hdmlnYXRpb25TZXJ2aWNlKSB7XG4gICAgICAgIHN1cGVyKF9lbGVtZW50LCBfbmF2aWdhdGlvblNlcnZpY2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgbmdPbkluaXQoKSB7XG4gICAgICAgIHN1cGVyLm5nT25Jbml0KCk7XG5cbiAgICAgICAgY29uc3QgcG9zaXRpb25TZXR0aW5nczogUG9zaXRpb25TZXR0aW5ncyA9IHtcbiAgICAgICAgICAgIHRhcmdldDogdGhpcy5uYXRpdmVFbGVtZW50LFxuICAgICAgICAgICAgaG9yaXpvbnRhbERpcmVjdGlvbjogSG9yaXpvbnRhbEFsaWdubWVudC5DZW50ZXIsXG4gICAgICAgICAgICBob3Jpem9udGFsU3RhcnRQb2ludDogSG9yaXpvbnRhbEFsaWdubWVudC5DZW50ZXIsXG4gICAgICAgICAgICBvcGVuQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oc2NhbGVJbkNlbnRlciwgeyBwYXJhbXM6IHsgZHVyYXRpb246ICcxNTBtcycgfSB9KSxcbiAgICAgICAgICAgIGNsb3NlQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oZmFkZU91dCwgeyBwYXJhbXM6IHsgZHVyYXRpb246ICc3NW1zJyB9IH0pXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5fb3ZlcmxheURlZmF1bHRzLnBvc2l0aW9uU3RyYXRlZ3kgPSBuZXcgQXV0b1Bvc2l0aW9uU3RyYXRlZ3kocG9zaXRpb25TZXR0aW5ncyk7XG4gICAgICAgIHRoaXMuX292ZXJsYXlEZWZhdWx0cy5jbG9zZU9uT3V0c2lkZUNsaWNrID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjaGVja091dGxldEFuZE91dHNpZGVDbGljaygpIHtcbiAgICAgICAgaWYgKHRoaXMuY2xvc2VPbk91dHNpZGVDbGljayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLl9vdmVybGF5RGVmYXVsdHMuY2xvc2VPbk91dHNpZGVDbGljayA9IHRoaXMuY2xvc2VPbk91dHNpZGVDbGljaztcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vdXRsZXQpIHtcbiAgICAgICAgICAgIHRoaXMuX292ZXJsYXlEZWZhdWx0cy5vdXRsZXQgPSB0aGlzLm91dGxldDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IG1lcmdlZE92ZXJsYXlTZXR0aW5ncygpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHRoaXMuX292ZXJsYXlEZWZhdWx0cywgdGhpcy5vdmVybGF5U2V0dGluZ3MpO1xuICAgIH1cblxuICAgIC8vIFJldHVybiB0cnVlIGlmIHRoZSBleGVjdXRpb24gaW4gb25Nb3VzZUVudGVyIHNob3VsZCBiZSB0ZXJtaW5hdGVkIGFmdGVyIHRoaXMgbWV0aG9kXG4gICAgcHJpdmF0ZSBwcmVNb3VzZUVudGVyQ2hlY2soKSB7XG4gICAgICAgIC8vIElmIHRvb2x0aXAgaXMgYWJvdXQgdG8gYmUgb3BlbmVkXG4gICAgICAgIGlmICh0aGlzLnRhcmdldC50b0JlU2hvd24pIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRhcmdldC50aW1lb3V0SWQpO1xuICAgICAgICAgICAgdGhpcy50YXJnZXQudG9CZVNob3duID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBUb29sdGlwIGlzIG9wZW5lZCBvciBhYm91dCB0byBiZSBoaWRkZW5cbiAgICAgICAgaWYgKCF0aGlzLnRhcmdldC5jb2xsYXBzZWQgfHwgdGhpcy50YXJnZXQudG9CZUhpZGRlbikge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMudGFyZ2V0LnRpbWVvdXRJZCk7XG5cbiAgICAgICAgICAgIGNvbnN0IGhpZGluZ0FyZ3MgPSB7IHRhcmdldDogdGhpcywgdG9vbHRpcDogdGhpcy50YXJnZXQsIGNhbmNlbDogZmFsc2UgfTtcbiAgICAgICAgICAgIHRoaXMub25Ub29sdGlwSGlkZS5lbWl0KGhpZGluZ0FyZ3MpO1xuXG4gICAgICAgICAgICBpZiAoaGlkaW5nQXJncy5jYW5jZWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gIGlmIGNsb3NlIGFuaW1hdGlvbiBoYXMgc3RhcnRlZCBmaW5pc2ggaXQsIG9yIGNsb3NlIHRoZSB0b29sdGlwIHdpdGggbm8gYW5pbWF0aW9uXG4gICAgICAgICAgICB0aGlzLnRhcmdldC5mb3JjZUNsb3NlKHRoaXMubWVyZ2VkT3ZlcmxheVNldHRpbmdzKTtcbiAgICAgICAgICAgIHRoaXMudGFyZ2V0LnRvQ