ngx-bootstrap
Version:
Native Angular Bootstrap Components
735 lines • 52.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/* tslint:disable:max-file-line-count */
// todo: should we support enforce focus in?
// todo: in original bs there are was a way to prevent modal from showing
// todo: original modal had resize events
import { Directive, ElementRef, EventEmitter, HostListener, Input, Output, Renderer2, ViewContainerRef, Optional, Inject } from '@angular/core';
import { document, window, isBs3, Utils } from 'ngx-bootstrap/utils';
import { ModalBackdropComponent } from './modal-backdrop.component';
import { CLASS_NAME, DISMISS_REASONS, modalConfigDefaults, ModalOptions, MODAL_CONFIG_DEFAULT_OVERRIDE } from './modal-options.class';
import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
/** @type {?} */
var TRANSITION_DURATION = 300;
/** @type {?} */
var BACKDROP_TRANSITION_DURATION = 150;
/**
* Mark any code with directive to show it's content in modal
*/
var ModalDirective = /** @class */ (function () {
function ModalDirective(_element, _viewContainerRef, _renderer, clf, modalDefaultOption) {
this._element = _element;
this._renderer = _renderer;
/**
* This event fires immediately when the `show` instance method is called.
*/
this.onShow = new EventEmitter();
/**
* This event is fired when the modal has been made visible to the user
* (will wait for CSS transitions to complete)
*/
this.onShown = new EventEmitter();
/**
* This event is fired immediately when
* the hide instance method has been called.
*/
this.onHide = new EventEmitter();
/**
* This event is fired when the modal has finished being
* hidden from the user (will wait for CSS transitions to complete).
*/
this.onHidden = new EventEmitter();
this._isShown = false;
this.isBodyOverflowing = false;
this.originalBodyPadding = 0;
this.scrollbarWidth = 0;
this.timerHideModal = 0;
this.timerRmBackDrop = 0;
this.isNested = false;
this.clickStartedInContent = false;
this._backdrop = clf.createLoader(_element, _viewContainerRef, _renderer);
this._config = modalConfigDefaults || modalConfigDefaults;
}
Object.defineProperty(ModalDirective.prototype, "config", {
get: /**
* @return {?}
*/
function () {
return this._config;
},
/** allows to set modal configuration via element property */
set: /**
* allows to set modal configuration via element property
* @param {?} conf
* @return {?}
*/
function (conf) {
this._config = this.getConfig(conf);
},
enumerable: true,
configurable: true
});
Object.defineProperty(ModalDirective.prototype, "isShown", {
get: /**
* @return {?}
*/
function () {
return this._isShown;
},
enumerable: true,
configurable: true
});
/**
* @param {?} event
* @return {?}
*/
ModalDirective.prototype.onClickStarted = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.clickStartedInContent = event.target !== this._element.nativeElement;
};
/**
* @param {?} event
* @return {?}
*/
ModalDirective.prototype.onClickStop = /**
* @param {?} event
* @return {?}
*/
function (event) {
/** @type {?} */
var clickedInBackdrop = event.target === this._element.nativeElement && !this.clickStartedInContent;
if (this.config.ignoreBackdropClick ||
this.config.backdrop === 'static' ||
!clickedInBackdrop) {
this.clickStartedInContent = false;
return;
}
this.dismissReason = DISMISS_REASONS.BACKRDOP;
this.hide(event);
};
// todo: consider preventing default and stopping propagation
// todo: consider preventing default and stopping propagation
/**
* @param {?} event
* @return {?}
*/
ModalDirective.prototype.onEsc =
// todo: consider preventing default and stopping propagation
/**
* @param {?} event
* @return {?}
*/
function (event) {
if (!this._isShown) {
return;
}
// tslint:disable-next-line:deprecation
if (event.keyCode === 27 || event.key === 'Escape') {
event.preventDefault();
}
if (this.config.keyboard) {
this.dismissReason = DISMISS_REASONS.ESC;
this.hide();
}
};
/**
* @return {?}
*/
ModalDirective.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.config = void 0;
if (this._isShown) {
this._isShown = false;
this.hideModal();
this._backdrop.dispose();
}
};
/**
* @return {?}
*/
ModalDirective.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
this._config = this._config || this.getConfig();
setTimeout((/**
* @return {?}
*/
function () {
if (_this._config.show) {
_this.show();
}
}), 0);
};
/* Public methods */
/** Allows to manually toggle modal visibility */
/* Public methods */
/**
* Allows to manually toggle modal visibility
* @return {?}
*/
ModalDirective.prototype.toggle = /* Public methods */
/**
* Allows to manually toggle modal visibility
* @return {?}
*/
function () {
return this._isShown ? this.hide() : this.show();
};
/** Allows to manually open modal */
/**
* Allows to manually open modal
* @return {?}
*/
ModalDirective.prototype.show = /**
* Allows to manually open modal
* @return {?}
*/
function () {
var _this = this;
this.dismissReason = null;
this.onShow.emit(this);
if (this._isShown) {
return;
}
clearTimeout(this.timerHideModal);
clearTimeout(this.timerRmBackDrop);
this._isShown = true;
this.checkScrollbar();
this.setScrollbar();
if (document && document.body) {
if (document.body.classList.contains(CLASS_NAME.OPEN)) {
this.isNested = true;
}
else {
this._renderer.addClass(document.body, CLASS_NAME.OPEN);
}
}
this.showBackdrop((/**
* @return {?}
*/
function () {
_this.showElement();
}));
};
/** Allows to manually close modal */
/**
* Allows to manually close modal
* @param {?=} event
* @return {?}
*/
ModalDirective.prototype.hide = /**
* Allows to manually close modal
* @param {?=} event
* @return {?}
*/
function (event) {
var _this = this;
if (event) {
event.preventDefault();
}
this.onHide.emit(this);
// todo: add an option to prevent hiding
if (!this._isShown) {
return;
}
window.clearTimeout(this.timerHideModal);
window.clearTimeout(this.timerRmBackDrop);
this._isShown = false;
this._renderer.removeClass(this._element.nativeElement, CLASS_NAME.IN);
if (!isBs3()) {
this._renderer.removeClass(this._element.nativeElement, CLASS_NAME.SHOW);
}
// this._addClassIn = false;
if (this._config.animated) {
this.timerHideModal = window.setTimeout((/**
* @return {?}
*/
function () { return _this.hideModal(); }), TRANSITION_DURATION);
}
else {
this.hideModal();
}
};
/** Private methods @internal */
/**
* Private methods \@internal
* @protected
* @param {?=} config
* @return {?}
*/
ModalDirective.prototype.getConfig = /**
* Private methods \@internal
* @protected
* @param {?=} config
* @return {?}
*/
function (config) {
return Object.assign({}, this._config, config);
};
/**
* Show dialog
* @internal
*/
/**
* Show dialog
* \@internal
* @protected
* @return {?}
*/
ModalDirective.prototype.showElement = /**
* Show dialog
* \@internal
* @protected
* @return {?}
*/
function () {
var _this = this;
// todo: replace this with component loader usage
if (!this._element.nativeElement.parentNode ||
this._element.nativeElement.parentNode.nodeType !== Node.ELEMENT_NODE) {
// don't move modals dom position
if (document && document.body) {
document.body.appendChild(this._element.nativeElement);
}
}
this._renderer.setAttribute(this._element.nativeElement, 'aria-hidden', 'false');
this._renderer.setAttribute(this._element.nativeElement, 'aria-modal', 'true');
this._renderer.setStyle(this._element.nativeElement, 'display', 'block');
this._renderer.setProperty(this._element.nativeElement, 'scrollTop', 0);
if (this._config.animated) {
Utils.reflow(this._element.nativeElement);
}
// this._addClassIn = true;
this._renderer.addClass(this._element.nativeElement, CLASS_NAME.IN);
if (!isBs3()) {
this._renderer.addClass(this._element.nativeElement, CLASS_NAME.SHOW);
}
/** @type {?} */
var transitionComplete = (/**
* @return {?}
*/
function () {
if (_this._config.focus) {
_this._element.nativeElement.focus();
}
_this.onShown.emit(_this);
});
if (this._config.animated) {
setTimeout(transitionComplete, TRANSITION_DURATION);
}
else {
transitionComplete();
}
};
/** @internal */
/**
* \@internal
* @protected
* @return {?}
*/
ModalDirective.prototype.hideModal = /**
* \@internal
* @protected
* @return {?}
*/
function () {
var _this = this;
this._renderer.setAttribute(this._element.nativeElement, 'aria-hidden', 'true');
this._renderer.setStyle(this._element.nativeElement, 'display', 'none');
this.showBackdrop((/**
* @return {?}
*/
function () {
if (!_this.isNested) {
if (document && document.body) {
_this._renderer.removeClass(document.body, CLASS_NAME.OPEN);
}
_this.resetScrollbar();
}
_this.resetAdjustments();
_this.focusOtherModal();
_this.onHidden.emit(_this);
}));
};
// todo: original show was calling a callback when done, but we can use
// promise
/** @internal */
// todo: original show was calling a callback when done, but we can use
// promise
/**
* \@internal
* @protected
* @param {?=} callback
* @return {?}
*/
ModalDirective.prototype.showBackdrop =
// todo: original show was calling a callback when done, but we can use
// promise
/**
* \@internal
* @protected
* @param {?=} callback
* @return {?}
*/
function (callback) {
var _this = this;
if (this._isShown &&
this.config.backdrop &&
(!this.backdrop || !this.backdrop.instance.isShown)) {
this.removeBackdrop();
this._backdrop
.attach(ModalBackdropComponent)
.to('body')
.show({ isAnimated: this._config.animated });
this.backdrop = this._backdrop._componentRef;
if (!callback) {
return;
}
if (!this._config.animated) {
callback();
return;
}
setTimeout(callback, BACKDROP_TRANSITION_DURATION);
}
else if (!this._isShown && this.backdrop) {
this.backdrop.instance.isShown = false;
/** @type {?} */
var callbackRemove = (/**
* @return {?}
*/
function () {
_this.removeBackdrop();
if (callback) {
callback();
}
});
if (this.backdrop.instance.isAnimated) {
this.timerRmBackDrop = window.setTimeout(callbackRemove, BACKDROP_TRANSITION_DURATION);
}
else {
callbackRemove();
}
}
else if (callback) {
callback();
}
};
/** @internal */
/**
* \@internal
* @protected
* @return {?}
*/
ModalDirective.prototype.removeBackdrop = /**
* \@internal
* @protected
* @return {?}
*/
function () {
this._backdrop.hide();
};
/** Events tricks */
// no need for it
// protected setEscapeEvent():void {
// if (this._isShown && this._config.keyboard) {
// $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {
// if (event.which === 27) {
// this.hide()
// }
// })
//
// } else if (!this._isShown) {
// $(this._element).off(Event.KEYDOWN_DISMISS)
// }
// }
// protected setResizeEvent():void {
// console.log(this.renderer.listenGlobal('', Event.RESIZE));
// if (this._isShown) {
// $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this))
// } else {
// $(window).off(Event.RESIZE)
// }
// }
/**
* Events tricks
* @protected
* @return {?}
*/
// no need for it
// protected setEscapeEvent():void {
// if (this._isShown && this._config.keyboard) {
// $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {
// if (event.which === 27) {
// this.hide()
// }
// })
//
// } else if (!this._isShown) {
// $(this._element).off(Event.KEYDOWN_DISMISS)
// }
// }
// protected setResizeEvent():void {
// console.log(this.renderer.listenGlobal('', Event.RESIZE));
// if (this._isShown) {
// $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this))
// } else {
// $(window).off(Event.RESIZE)
// }
// }
ModalDirective.prototype.focusOtherModal = /**
* Events tricks
* @protected
* @return {?}
*/
// no need for it
// protected setEscapeEvent():void {
// if (this._isShown && this._config.keyboard) {
// $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {
// if (event.which === 27) {
// this.hide()
// }
// })
//
// } else if (!this._isShown) {
// $(this._element).off(Event.KEYDOWN_DISMISS)
// }
// }
// protected setResizeEvent():void {
// console.log(this.renderer.listenGlobal('', Event.RESIZE));
// if (this._isShown) {
// $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this))
// } else {
// $(window).off(Event.RESIZE)
// }
// }
function () {
if (this._element.nativeElement.parentElement == null) {
return;
}
/** @type {?} */
var otherOpenedModals = this._element.nativeElement.parentElement.querySelectorAll('.in[bsModal]');
if (!otherOpenedModals.length) {
return;
}
otherOpenedModals[otherOpenedModals.length - 1].focus();
};
/** @internal */
/**
* \@internal
* @protected
* @return {?}
*/
ModalDirective.prototype.resetAdjustments = /**
* \@internal
* @protected
* @return {?}
*/
function () {
this._renderer.setStyle(this._element.nativeElement, 'paddingLeft', '');
this._renderer.setStyle(this._element.nativeElement, 'paddingRight', '');
};
/** Scroll bar tricks */
/** @internal */
/** Scroll bar tricks */
/**
* \@internal
* @protected
* @return {?}
*/
ModalDirective.prototype.checkScrollbar = /** Scroll bar tricks */
/**
* \@internal
* @protected
* @return {?}
*/
function () {
this.isBodyOverflowing = document.body.clientWidth < window.innerWidth;
this.scrollbarWidth = this.getScrollbarWidth();
};
/**
* @protected
* @return {?}
*/
ModalDirective.prototype.setScrollbar = /**
* @protected
* @return {?}
*/
function () {
if (!document) {
return;
}
this.originalBodyPadding = parseInt(window
.getComputedStyle(document.body)
.getPropertyValue('padding-right') || 0, 10);
if (this.isBodyOverflowing) {
document.body.style.paddingRight = this.originalBodyPadding +
this.scrollbarWidth + "px";
}
};
/**
* @protected
* @return {?}
*/
ModalDirective.prototype.resetScrollbar = /**
* @protected
* @return {?}
*/
function () {
document.body.style.paddingRight = this.originalBodyPadding + "px";
};
// thx d.walsh
// thx d.walsh
/**
* @protected
* @return {?}
*/
ModalDirective.prototype.getScrollbarWidth =
// thx d.walsh
/**
* @protected
* @return {?}
*/
function () {
/** @type {?} */
var scrollDiv = this._renderer.createElement('div');
this._renderer.addClass(scrollDiv, CLASS_NAME.SCROLLBAR_MEASURER);
this._renderer.appendChild(document.body, scrollDiv);
/** @type {?} */
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
this._renderer.removeChild(document.body, scrollDiv);
return scrollbarWidth;
};
ModalDirective.decorators = [
{ type: Directive, args: [{
selector: '[bsModal]',
exportAs: 'bs-modal'
},] }
];
/** @nocollapse */
ModalDirective.ctorParameters = function () { return [
{ type: ElementRef },
{ type: ViewContainerRef },
{ type: Renderer2 },
{ type: ComponentLoaderFactory },
{ type: ModalOptions, decorators: [{ type: Optional }, { type: Inject, args: [MODAL_CONFIG_DEFAULT_OVERRIDE,] }] }
]; };
ModalDirective.propDecorators = {
config: [{ type: Input }],
onShow: [{ type: Output }],
onShown: [{ type: Output }],
onHide: [{ type: Output }],
onHidden: [{ type: Output }],
onClickStarted: [{ type: HostListener, args: ['mousedown', ['$event'],] }],
onClickStop: [{ type: HostListener, args: ['mouseup', ['$event'],] }],
onEsc: [{ type: HostListener, args: ['keydown.esc', ['$event'],] }]
};
return ModalDirective;
}());
export { ModalDirective };
if (false) {
/**
* This event fires immediately when the `show` instance method is called.
* @type {?}
*/
ModalDirective.prototype.onShow;
/**
* This event is fired when the modal has been made visible to the user
* (will wait for CSS transitions to complete)
* @type {?}
*/
ModalDirective.prototype.onShown;
/**
* This event is fired immediately when
* the hide instance method has been called.
* @type {?}
*/
ModalDirective.prototype.onHide;
/**
* This event is fired when the modal has finished being
* hidden from the user (will wait for CSS transitions to complete).
* @type {?}
*/
ModalDirective.prototype.onHidden;
/**
* This field contains last dismiss reason.
* Possible values: `backdrop-click`, `esc` and `id: number`
* (if modal was closed by direct call of `.hide()`).
* @type {?}
*/
ModalDirective.prototype.dismissReason;
/**
* @type {?}
* @protected
*/
ModalDirective.prototype._config;
/**
* @type {?}
* @protected
*/
ModalDirective.prototype._isShown;
/**
* @type {?}
* @protected
*/
ModalDirective.prototype.isBodyOverflowing;
/**
* @type {?}
* @protected
*/
ModalDirective.prototype.originalBodyPadding;
/**
* @type {?}
* @protected
*/
ModalDirective.prototype.scrollbarWidth;
/**
* @type {?}
* @protected
*/
ModalDirective.prototype.timerHideModal;
/**
* @type {?}
* @protected
*/
ModalDirective.prototype.timerRmBackDrop;
/**
* @type {?}
* @protected
*/
ModalDirective.prototype.backdrop;
/**
* @type {?}
* @private
*/
ModalDirective.prototype._backdrop;
/**
* @type {?}
* @private
*/
ModalDirective.prototype.isNested;
/**
* @type {?}
* @private
*/
ModalDirective.prototype.clickStartedInContent;
/**
* @type {?}
* @private
*/
ModalDirective.prototype._element;
/**
* @type {?}
* @private
*/
ModalDirective.prototype._renderer;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LWJvb3RzdHJhcC9tb2RhbC8iLCJzb3VyY2VzIjpbIm1vZGFsLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUtBLE9BQU8sRUFDUyxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUNuRCxNQUFNLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQ3pFLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNwRSxPQUFPLEVBQ0wsVUFBVSxFQUFFLGVBQWUsRUFBRSxtQkFBbUIsRUFBRSxZQUFZLEVBQUUsNkJBQTZCLEVBQzlGLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUFtQixzQkFBc0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDOztJQUVuRixtQkFBbUIsR0FBRyxHQUFHOztJQUN6Qiw0QkFBNEIsR0FBRyxHQUFHOzs7O0FBR3hDO0lBNkRFLHdCQUNVLFFBQW9CLEVBQzVCLGlCQUFtQyxFQUMzQixTQUFvQixFQUM1QixHQUEyQixFQUN3QixrQkFBZ0M7UUFKM0UsYUFBUSxHQUFSLFFBQVEsQ0FBWTtRQUVwQixjQUFTLEdBQVQsU0FBUyxDQUFXOzs7O1FBL0M5QixXQUFNLEdBQWlDLElBQUksWUFBWSxFQUFrQixDQUFDOzs7OztRQUsxRSxZQUFPLEdBQWlDLElBQUksWUFBWSxFQUFrQixDQUFDOzs7OztRQUszRSxXQUFNLEdBQWlDLElBQUksWUFBWSxFQUFrQixDQUFDOzs7OztRQUsxRSxhQUFRLEdBQWlDLElBQUksWUFBWSxFQUFrQixDQUFDO1FBYWxFLGFBQVEsR0FBRyxLQUFLLENB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QVksU0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUM7OEJBS3BDLFlBQVksU0FBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUM7d0JBaUJsQyxZQUFZLFNBQUMsYUFBYSxFQUFFLENBQUMsUUFBUSxDQUFDOztJQWlWekMscUJBQUM7Q0FBQSxBQWxiRCxJQWtiQztTQTlhWSxjQUFjOzs7Ozs7SUFZekIsZ0NBQzBFOzs7Ozs7SUFJMUUsaUNBQzJFOzs7Ozs7SUFJM0UsZ0NBQzBFOzs7Ozs7SUFJMUUsa0NBQzRFOzs7Ozs7O0lBTTVFLHVDQUFzQjs7Ozs7SUFNdEIsaUNBQWdDOzs7OztJQUNoQyxrQ0FBMkI7Ozs7O0lBRTNCLDJDQUFvQzs7Ozs7SUFDcEMsNkNBQWtDOzs7OztJQUNsQyx3Q0FBNkI7Ozs7O0lBRTdCLHdDQUE2Qjs7Ozs7SUFDN0IseUNBQThCOzs7OztJQUc5QixrQ0FBeUQ7Ozs7O0lBQ3pELG1DQUEyRDs7Ozs7SUFFM0Qsa0NBQXlCOzs7OztJQUN6QiwrQ0FBc0M7Ozs7O0lBR3BDLGtDQUE0Qjs7Ozs7SUFFNUIsbUNBQTRCIiwic291cmNlc0NvbnRlbnQiOlsiLyogdHNsaW50OmRpc2FibGU6bWF4LWZpbGUtbGluZS1jb3VudCAqL1xuLy8gdG9kbzogc2hvdWxkIHdlIHN1cHBvcnQgZW5mb3JjZSBmb2N1cyBpbj9cbi8vIHRvZG86IGluIG9yaWdpbmFsIGJzIHRoZXJlIGFyZSB3YXMgYSB3YXkgdG8gcHJldmVudCBtb2RhbCBmcm9tIHNob3dpbmdcbi8vIHRvZG86IG9yaWdpbmFsIG1vZGFsIGhhZCByZXNpemUgZXZlbnRzXG5cbmltcG9ydCB7XG4gIENvbXBvbmVudFJlZiwgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIEhvc3RMaXN0ZW5lciwgSW5wdXQsXG4gIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFJlbmRlcmVyMiwgVmlld0NvbnRhaW5lclJlZiwgT3B0aW9uYWwsIEluamVjdFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgZG9jdW1lbnQsIHdpbmRvdywgaXNCczMsIFV0aWxzIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC91dGlscyc7XG5pbXBvcnQgeyBNb2RhbEJhY2tkcm9wQ29tcG9uZW50IH0gZnJvbSAnLi9tb2RhbC1iYWNrZHJvcC5jb21wb25lbnQnO1xuaW1wb3J0IHtcbiAgQ0xBU1NfTkFNRSwgRElTTUlTU19SRUFTT05TLCBtb2RhbENvbmZpZ0RlZmF1bHRzLCBNb2RhbE9wdGlvbnMsIE1PREFMX0NPTkZJR19ERUZBVUxUX09WRVJSSURFXG59IGZyb20gJy4vbW9kYWwtb3B0aW9ucy5jbGFzcyc7XG5pbXBvcnQgeyBDb21wb25lbnRMb2FkZXIsIENvbXBvbmVudExvYWRlckZhY3RvcnkgfSBmcm9tICduZ3gtYm9vdHN0cmFwL2NvbXBvbmVudC1sb2FkZXInO1xuXG5jb25zdCBUUkFOU0lUSU9OX0RVUkFUSU9OID0gMzAwO1xuY29uc3QgQkFDS0RST1BfVFJBTlNJVElPTl9EVVJBVElPTiA9IDE1MDtcblxuLyoqIE1hcmsgYW55IGNvZGUgd2l0aCBkaXJlY3RpdmUgdG8gc2hvdyBpdCdzIGNvbnRlbnQgaW4gbW9kYWwgKi9cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tic01vZGFsXScsXG4gIGV4cG9ydEFzOiAnYnMtbW9kYWwnXG59KVxuZXhwb3J0IGNsYXNzIE1vZGFsRGlyZWN0aXZlIGltcGxlbWVudHMgT25EZXN0cm95LCBPbkluaXQge1xuICAvKiogYWxsb3dzIHRvIHNldCBtb2RhbCBjb25maWd1cmF0aW9uIHZpYSBlbGVtZW50IHByb3BlcnR5ICovXG4gIEBJbnB1dCgpXG4gIHNldCBjb25maWcoY29uZjogTW9kYWxPcHRpb25zKSB7XG4gICAgdGhpcy5fY29uZmlnID0gdGhpcy5nZXRDb25maWcoY29uZik7XG4gIH1cblxuICBnZXQgY29uZmlnKCk6IE1vZGFsT3B0aW9ucyB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZztcbiAgfVxuXG4gIC8qKiBUaGlzIGV2ZW50IGZpcmVzIGltbWVkaWF0ZWx5IHdoZW4gdGhlIGBzaG93YCBpbnN0YW5jZSBtZXRob2QgaXMgY2FsbGVkLiAqL1xuICBAT3V0cHV0KClcbiAgb25TaG93OiBFdmVudEVtaXR0ZXI8TW9kYWxEaXJlY3RpdmU+ID0gbmV3IEV2ZW50RW1pdHRlcjxNb2RhbERpcmVjdGl2ZT4oKTtcbiAgLyoqIFRoaXMgZXZlbnQgaXMgZmlyZWQgd2hlbiB0aGUgbW9kYWwgaGFzIGJlZW4gbWFkZSB2aXNpYmxlIHRvIHRoZSB1c2VyXG4gICAqICh3aWxsIHdhaXQgZm9yIENTUyB0cmFuc2l0aW9ucyB0byBjb21wbGV0ZSlcbiAgICovXG4gIEBPdXRwdXQoKVxuICBvblNob3duOiBFdmVudEVtaXR0ZXI8TW9kYWxEaXJlY3RpdmU+ID0gbmV3IEV2ZW50RW1pdHRlcjxNb2RhbERpcmVjdGl2ZT4oKTtcbiAgLyoqIFRoaXMgZXZlbnQgaXMgZmlyZWQgaW1tZWRpYXRlbHkgd2hlblxuICAgKiB0aGUgaGlkZSBpbnN0YW5jZSBtZXRob2QgaGFzIGJlZW4gY2FsbGVkLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIG9uSGlkZTogRXZlbnRFbWl0dGVyPE1vZGFsRGlyZWN0aXZlPiA9IG5ldyBFdmVudEVtaXR0ZXI8TW9kYWxEaXJlY3RpdmU+KCk7XG4gIC8qKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gdGhlIG1vZGFsIGhhcyBmaW5pc2hlZCBiZWluZ1xuICAgKiBoaWRkZW4gZnJvbSB0aGUgdXNlciAod2lsbCB3YWl0IGZvciBDU1MgdHJhbnNpdGlvbnMgdG8gY29tcGxldGUpLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIG9uSGlkZGVuOiBFdmVudEVtaXR0ZXI8TW9kYWxEaXJlY3RpdmU+ID0gbmV3IEV2ZW50RW1pdHRlcjxNb2RhbERpcmVjdGl2ZT4oKTtcblxuICAvKiogVGhpcyBmaWVsZCBjb250YWlucyBsYXN0IGRpc21pc3MgcmVhc29uLlxuICAgKiBQb3NzaWJsZSB2YWx1ZXM6IGBiYWNrZHJvcC1jbGlja2AsIGBlc2NgIGFuZCBgaWQ6IG51bWJlcmBcbiAgICogKGlmIG1vZGFsIHdhcyBjbG9zZWQgYnkgZGlyZWN0IGNhbGwgb2YgYC5oaWRlKClgKS5cbiAgICovXG4gIGRpc21pc3NSZWFzb246IHN0cmluZztcblxuICBnZXQgaXNTaG93bigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5faXNTaG93bjtcbiAgfVxuXG4gIHByb3RlY3RlZCBfY29uZmlnOiBNb2RhbE9wdGlvbnM7XG4gIHByb3RlY3RlZCBfaXNTaG93biA9IGZhbHNlO1xuXG4gIHByb3RlY3RlZCBpc0JvZHlPdmVyZmxvd2luZyA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgb3JpZ2luYWxCb2R5UGFkZGluZyA9IDA7XG4gIHByb3RlY3RlZCBzY3JvbGxiYXJXaWR0aCA9IDA7XG5cbiAgcHJvdGVjdGVkIHRpbWVySGlkZU1vZGFsID0gMDtcbiAgcHJvdGVjdGVkIHRpbWVyUm1CYWNrRHJvcCA9IDA7XG5cbiAgLy8gcmVmZXJlbmNlIHRvIGJhY2tkcm9wIGNvbXBvbmVudFxuICBwcm90ZWN0ZWQgYmFja2Ryb3A6IENvbXBvbmVudFJlZjxNb2RhbEJhY2tkcm9wQ29tcG9uZW50PjtcbiAgcHJpdmF0ZSBfYmFja2Ryb3A6IENvbXBvbmVudExvYWRlcjxNb2RhbEJhY2tkcm9wQ29tcG9uZW50PjtcblxuICBwcml2YXRlIGlzTmVzdGVkID0gZmFsc2U7XG4gIHByaXZhdGUgY2xpY2tTdGFydGVkSW5Db250ZW50ID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfZWxlbWVudDogRWxlbWVudFJlZixcbiAgICBfdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZixcbiAgICBwcml2YXRlIF9yZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgIGNsZjogQ29tcG9uZW50TG9hZGVyRmFjdG9yeSxcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KE1PREFMX0NPTkZJR19ERUZBVUxUX09WRVJSSURFKSBtb2RhbERlZmF1bHRPcHRpb246IE1vZGFsT3B0aW9ucykge1xuICAgIHRoaXMuX2JhY2tkcm9wID0gY2xmLmNyZWF0ZUxvYWRlcjxNb2RhbEJhY2tkcm9wQ29tcG9uZW50PihcbiAgICAgIF9lbGVtZW50LFxuICAgICAgX3ZpZXdDb250YWluZXJSZWYsXG4gICAgICBfcmVuZGVyZXJcbiAgICApO1xuICAgIHRoaXMuX2NvbmZpZyA9IG1vZGFsQ29uZmlnRGVmYXVsdHMgfHwgbW9kYWxDb25maWdEZWZhdWx0cztcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlZG93bicsIFsnJGV2ZW50J10pXG4gIG9uQ2xpY2tTdGFydGVkKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgdGhpcy5jbGlja1N0YXJ0ZWRJbkNvbnRlbnQgPSBldmVudC50YXJnZXQgIT09IHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNldXAnLCBbJyRldmVudCddKVxuICBvbkNsaWNrU3RvcChldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGNsaWNrZWRJbkJhY2tkcm9wID0gZXZlbnQudGFyZ2V0ID09PSB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQgJiYgIXRoaXMuY2xpY2tTdGFydGVkSW5Db250ZW50O1xuICAgIGlmIChcbiAgICAgIHRoaXMuY29uZmlnLmlnbm9yZUJhY2tkcm9wQ2xpY2sgfHxcbiAgICAgIHRoaXMuY29uZmlnLmJhY2tkcm9wID09PSAnc3RhdGljJyB8fFxuICAgICAgIWNsaWNrZWRJbkJhY2tkcm9wXG4gICAgKSB7XG4gICAgICB0aGlzLmNsaWNrU3RhcnRlZEluQ29udGVudCA9IGZhbHNlO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuZGlzbWlzc1JlYXNvbiA9IERJU01JU1NfUkVBU09OUy5CQUNLUkRPUDtcbiAgICB0aGlzLmhpZGUoZXZlbnQpO1xuICB9XG5cbiAgLy8gdG9kbzogY29uc2lkZXIgcHJldmVudGluZyBkZWZhdWx0IGFuZCBzdG9wcGluZyBwcm9wYWdhdGlvblxuICBASG9zdExpc3RlbmVyKCdrZXlkb3duLmVzYycsIFsnJGV2ZW50J10pXG4gIG9uRXNjKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9pc1Nob3duKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpkZXByZWNhdGlvblxuICAgIGlmIChldmVudC5rZXlDb2RlID09PSAyNyB8fCBldmVudC5rZXkgPT09ICdFc2NhcGUnKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZy5rZXlib2FyZCkge1xuICAgICAgdGhpcy5kaXNtaXNzUmVhc29uID0gRElTTUlTU19SRUFTT05TLkVTQztcbiAgICAgIHRoaXMuaGlkZSgpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuY29uZmlnID0gdm9pZCAwO1xuICAgIGlmICh0aGlzLl9pc1Nob3duKSB7XG4gICAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG4gICAgICB0aGlzLmhpZGVNb2RhbCgpO1xuICAgICAgdGhpcy5fYmFja2Ryb3AuZGlzcG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2NvbmZpZyB8fCB0aGlzLmdldENvbmZpZygpO1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuX2NvbmZpZy5zaG93KSB7XG4gICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgfVxuICAgIH0sIDApO1xuICB9XG5cbiAgLyogUHVibGljIG1ldGhvZHMgKi9cblxuICAvKiogQWxsb3dzIHRvIG1hbnVhbGx5IHRvZ2dsZSBtb2RhbCB2aXNpYmlsaXR5ICovXG4gIHRvZ2dsZSgpOiB2b2lkIHtcbiAgICByZXR1cm4gdGhpcy5faXNTaG93biA/IHRoaXMuaGlkZSgpIDogdGhpcy5zaG93KCk7XG4gIH1cblxuICAvKiogQWxsb3dzIHRvIG1hbnVhbGx5IG9wZW4gbW9kYWwgKi9cbiAgc2hvdygpOiB2b2lkIHtcbiAgICB0aGlzLmRpc21pc3NSZWFzb24gPSBudWxsO1xuICAgIHRoaXMub25TaG93LmVtaXQodGhpcyk7XG4gICAgaWYgKHRoaXMuX2lzU2hvd24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2xlYXJUaW1lb3V0KHRoaXMudGltZXJIaWRlTW9kYWwpO1xuICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVyUm1CYWNrRHJvcCk7XG5cbiAgICB0aGlzLl9pc1Nob3duID0gdHJ1ZTtcblxuICAgIHRoaXMuY2hlY2tTY3JvbGxiYXIoKTtcbiAgICB0aGlzLnNldFNjcm9sbGJhcigpO1xuXG4gICAgaWYgKGRvY3VtZW50ICYmIGRvY3VtZW50LmJvZHkpIHtcbiAgICAgIGlmIChkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5jb250YWlucyhDTEFTU19OQU1FLk9QRU4pKSB7XG4gICAgICAgIHRoaXMuaXNOZXN0ZWQgPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIuYWRkQ2xhc3MoZG9jdW1lbnQuYm9keSwgQ0xBU1NfTkFNRS5PUEVOKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnNob3dCYWNrZHJvcCgoKSA9PiB7XG4gICAgICB0aGlzLnNob3dFbGVtZW50KCk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQWxsb3dzIHRvIG1hbnVhbGx5IGNsb3NlIG1vZGFsICovXG4gIGhpZGUoZXZlbnQ/OiBFdmVudCk6IHZvaWQge1xuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICB0aGlzLm9uSGlkZS5lbWl0KHRoaXMpO1xuXG4gICAgLy8gdG9kbzogYWRkIGFuIG9wdGlvbiB0byBwcmV2ZW50IGhpZGluZ1xuICAgIGlmICghdGhpcy5faXNTaG93bikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy50aW1lckhpZGVNb2RhbCk7XG4gICAgd2luZG93LmNsZWFyVGltZW91dCh0aGlzLnRpbWVyUm1CYWNrRHJvcCk7XG5cbiAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG4gICAgdGhpcy5fcmVuZGVyZXIucmVtb3ZlQ2xhc3ModGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LCBDTEFTU19OQU1FLklOKTtcbiAgICBpZiAoIWlzQnMzKCkpIHtcbiAgICAgIHRoaXMuX3JlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudCwgQ0xBU1NfTkFNRS5TSE9XKTtcbiAgICB9XG4gICAgLy8gdGhpcy5fYWRkQ2xhc3NJbiA9IGZhbHNlO1xuXG4gICAgaWYgKHRoaXMuX2NvbmZpZy5hbmltYXRlZCkge1xuICAgICAgdGhpcy50aW1lckhpZGVNb2RhbCA9IHdpbmRvdy5zZXRUaW1lb3V0KFxuICAgICAgICAoKSA9PiB0aGlzLmhpZGVNb2RhbCgpLFxuICAgICAgICBUUkFOU0lUSU9OX0RVUkFUSU9OXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmhpZGVNb2RhbCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBQcml2YXRlIG1ldGhvZHMgQGludGVybmFsICovXG4gIHByb3RlY3RlZCBnZXRDb25maWcoY29uZmlnPzogTW9kYWxPcHRpb25zKTogTW9kYWxPcHRpb25zIHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5fY29uZmlnLCBjb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqICBTaG93IGRpYWxvZ1xuICAgKiAgQGludGVybmFsXG4gICAqL1xuICBwcm90ZWN0ZWQgc2hvd0VsZW1lbnQoKTogdm9pZCB7XG4gICAgLy8gdG9kbzogcmVwbGFjZSB0aGlzIHdpdGggY29tcG9uZW50IGxvYWRlciB1c2FnZVxuICAgIGlmIChcbiAgICAgICF0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQucGFyZW50Tm9kZSB8fFxuICAgICAgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LnBhcmVudE5vZGUubm9kZVR5cGUgIT09IE5vZGUuRUxFTUVOVF9OT0RFXG4gICAgKSB7XG4gICAgICAvLyBkb24ndCBtb3ZlIG1vZGFscyBkb20gcG9zaXRpb25cbiAgICAgIGlmIChkb2N1bWVudCAmJiBkb2N1bWVudC5ib2R5KSB7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLl9yZW5kZXJlci5zZXRBdHRyaWJ1dGUoXG4gICAgICB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsXG4gICAgICAnYXJpYS1oaWRkZW4nLFxuICAgICAgJ2ZhbHNlJ1xuICAgICk7XG4gICAgdGhpcy5fcmVuZGVyZXIuc2V0QXR0cmlidXRlKFxuICAgICAgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LFxuICAgICAgJ2FyaWEtbW9kYWwnLFxuICAgICAgJ3RydWUnXG4gICAgKTtcbiAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZShcbiAgICAgIHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudCxcbiAgICAgICdkaXNwbGF5JyxcbiAgICAgICdibG9jaydcbiAgICApO1xuICAgIHRoaXMuX3JlbmRlcmVyLnNldFByb3BlcnR5KFxuICAgICAgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LFxuICAgICAgJ3Njcm9sbFRvcCcsXG4gICAgICAwXG4gICAgKTtcblxuICAgIGlmICh0aGlzLl9jb25maWcuYW5pbWF0ZWQpIHtcbiAgICAgIFV0aWxzLnJlZmxvdyh0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpO1xuICAgIH1cblxuICAgIC8vIHRoaXMuX2FkZENsYXNzSW4gPSB0cnVlO1xuICAgIHRoaXMuX3JlbmRlcmVyLmFkZENsYXNzKHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudCwgQ0xBU1NfTkFNRS5JTik7XG4gICAgaWYgKCFpc0JzMygpKSB7XG4gICAgICB0aGlzLl9yZW5kZXJlci5hZGRDbGFzcyh0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsIENMQVNTX05BTUUuU0hPVyk7XG4gICAgfVxuXG4gICAgY29uc3QgdHJhbnNpdGlvbkNvbXBsZXRlID0gKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuX2NvbmZpZy5mb2N1cykge1xuICAgICAgICB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH1cbiAgICAgIHRoaXMub25TaG93bi5lbWl0KHRoaXMpO1xuICAgIH07XG5cbiAgICBpZiAodGhpcy5fY29uZmlnLmFuaW1hdGVkKSB7XG4gICAgICBzZXRUaW1lb3V0KHRyYW5zaXRpb25Db21wbGV0ZSwgVFJBTlNJVElPTl9EVVJBVElPTik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRyYW5zaXRpb25Db21wbGV0ZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJvdGVjdGVkIGhpZGVNb2RhbCgpOiB2b2lkIHtcbiAgICB0aGlzLl9yZW5kZXJlci5zZXRBdHRyaWJ1dGUoXG4gICAgICB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsXG4gICAgICAnYXJpYS1oaWRkZW4nLFxuICAgICAgJ3RydWUnXG4gICAgKTtcbiAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZShcbiAgICAgIHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudCxcbiAgICAgICdkaXNwbGF5JyxcbiAgICAgICdub25lJ1xuICAgICk7XG4gICAgdGhpcy5zaG93QmFja2Ryb3AoKCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLmlzTmVzdGVkKSB7XG4gICAgICAgIGlmIChkb2N1bWVudCAmJiBkb2N1bWVudC5ib2R5KSB7XG4gICAgICAgICAgdGhpcy5fcmVuZGVyZXIucmVtb3ZlQ2xhc3MoZG9jdW1lbnQuYm9keSwgQ0xBU1NfTkFNRS5PUEVOKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlc2V0U2Nyb2xsYmFyKCk7XG4gICAgICB9XG4gICAgICB0aGlzLnJlc2V0QWRqdXN0bWVudHMoKTtcbiAgICAgIHRoaXMuZm9jdXNPdGhlck1vZGFsKCk7XG4gICAgICB0aGlzLm9uSGlkZGVuLmVtaXQodGhpcyk7XG4gICAgfSk7XG4gIH1cblxuICAvLyB0b2RvOiBvcmlnaW5hbCBzaG93IHdhcyBjYWxsaW5nIGEgY2FsbGJhY2sgd2hlbiBkb25lLCBidXQgd2UgY2FuIHVzZVxuICAvLyBwcm9taXNlXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJvdGVjdGVkIHNob3dCYWNrZHJvcChjYWxsYmFjaz86IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5faXNTaG93biAmJlxuICAgICAgdGhpcy5jb25maWcuYmFja2Ryb3AgJiZcbiAgICAgICghdGhpcy5iYWNrZHJvcCB8fCAhdGhpcy5iYWNrZHJvcC5pbnN0YW5jZS5pc1Nob3duKVxuICAgICkge1xuICAgICAgdGhpcy5yZW1vdmVCYWNrZHJvcCgpO1xuICAgICAgdGhpcy5fYmFja2Ryb3BcbiAgICAgICAgLmF0dGFjaChNb2RhbEJhY2tkcm9wQ29tcG9uZW50KVxuICAgICAgICAudG8oJ2JvZHknKVxuICAgICAgICAuc2hvdyh7IGlzQW5pbWF0ZWQ6IHRoaXMuX2NvbmZpZy5hbmltYXRlZCB9KTtcbiAgICAgIHRoaXMuYmFja2Ryb3AgPSB0aGlzLl9iYWNrZHJvcC5fY29tcG9uZW50UmVmO1xuXG4gICAgICBpZiAoIWNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLl9jb25maWcuYW5pbWF0ZWQpIHtcbiAgICAgICAgY2FsbGJhY2soKTtcblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIEJBQ0tEUk9QX1RSQU5TSVRJT05fRFVSQVRJT04pO1xuICAgIH0gZWxzZSBpZiAoIXRoaXMuX2lzU2hvd24gJiYgdGhpcy5iYWNrZHJvcCkge1xuICAgICAgdGhpcy5iYWNrZHJvcC5pbnN0YW5jZS5pc1Nob3duID0gZmFsc2U7XG5cbiAgICAgIGNvbnN0IGNhbGxiYWNrUmVtb3ZlID0gKCkgPT4ge1xuICAgICAgICB0aGlzLnJlbW92ZUJhY2tkcm9wKCk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICh0aGlzLmJhY2tkcm9wLmluc3RhbmNlLmlzQW5pbWF0ZWQpIHtcbiAgICAgICAgdGhpcy50aW1lclJtQmFja0Ryb3AgPSB3aW5kb3cuc2V0VGltZW91dChcbiAgICAgICAgICBjYWxsYmFja1JlbW92ZSxcbiAgICAgICAgICBCQUNLRFJPUF9UUkFOU0lUSU9OX0RVUkFUSU9OXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFja1JlbW92ZSgpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBwcm90ZWN0ZWQgcmVtb3ZlQmFja2Ryb3AoKTogdm9pZCB7XG4gICAgdGhpcy5fYmFja2Ryb3AuaGlkZSgpO1xuICB9XG5cbiAgLyoqIEV2ZW50cyB0cmlja3MgKi9cblxuICAvLyBubyBuZWVkIGZvciBpdFxuICAvLyBwcm90ZWN0ZWQgc2V0RXNjYXBlRXZlbnQoKTp2b2lkIHtcbiAgLy8gICBpZiAodGhpcy5faXNTaG93biAmJiB0aGlzLl9jb25maWcua2V5Ym9hcmQpIHtcbiAgLy8gICAgICQodGhpcy5fZWxlbWVudCkub24oRXZlbnQuS0VZRE9XTl9ESVNNSVNTLCAoZXZlbnQpID0+IHtcbiAgLy8gICAgICAgaWYgKGV2ZW50LndoaWNoID09PSAyNykge1xuICAvLyAgICAgICAgIHRoaXMuaGlkZSgpXG4gIC8vICAgICAgIH1cbiAgLy8gICAgIH0pXG4gIC8vXG4gIC8vICAgfSBlbHNlIGlmICghdGhpcy5faXNTaG93bikge1xuICAvLyAgICAgJCh0aGlzLl9lbGVtZW50KS5vZmYoRXZlbnQuS0VZRE9XTl9ESVNNSVNTKVxuICAvLyAgIH1cbiAgLy8gfVxuXG4gIC8vIHByb3RlY3RlZCBzZXRSZXNpemVFdmVudCgpOnZvaWQge1xuICAvLyBjb25zb2xlLmxvZyh0aGlzLnJlbmRlcmVyLmxpc3Rlbkdsb2JhbCgnJywgRXZlbnQuUkVTSVpFKSk7XG4gIC8vIGlmICh0aGlzLl9pc1Nob3duKSB7XG4gIC8vICAgJCh3aW5kb3cpLm9uKEV2ZW50LlJFU0laRSwgJC5wcm94eSh0aGlzLl9oYW5kbGVVcGRhdGUsIHRoaXMpKVxuICAvLyB9IGVsc2Uge1xuICAvLyAgICQod2luZG93KS5vZmYoRXZlbnQuUkVTSVpFKVxuICAvLyB9XG4gIC8vIH1cblxuICBwcm90ZWN0ZWQgZm9jdXNPdGhlck1vZGFsKCkge1xuICAgIGlmICh0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQucGFyZW50RWxlbWVudCA9PSBudWxsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG90aGVyT3BlbmVkTW9kYWxzID0gdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LnBhcmVudEVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCg