UNPKG

@duoduo-oba/ng-devui

Version:

DevUI components based on Angular

508 lines 55.4 kB
/** * @fileoverview added by tsickle * Generated from: directives/drop-scroll-enhance.directive.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { DropScrollEnhanceTimingFunctionGroup, DropScrollOrientation } from './drop-scroll-enhance.type'; import { Directive, ElementRef, Input, NgZone } from '@angular/core'; import { fromEvent, Subscription, merge as mergeStatic } from 'rxjs'; import { throttleTime, tap } from 'rxjs/operators'; import { DragDropService } from '../services/drag-drop.service'; export class DropScrollEnhancedDirective { /** * @param {?} el * @param {?} zone * @param {?} dragDropService */ constructor(el, zone, dragDropService) { this.el = el; this.zone = zone; this.dragDropService = dragDropService; this.minSpeed = 50; this.maxSpeed = 1000; this.responseEdgeWidth = '100px'; this.speedFn = DropScrollEnhanceTimingFunctionGroup.default; this.direction = 'v'; this.subscription = new Subscription(); } /** * @return {?} */ ngAfterViewInit() { // 设置父元素 this.el.nativeElement.parentNode.style.position = 'relative'; this.el.nativeElement.parentNode.style.display = 'block'; // 创建后退前进区域和对应的滚动函数 this.forwardScrollArea = this.createScrollArea(this.direction, DropScrollOrientation.forward); this.backwardScrollArea = this.createScrollArea(this.direction, DropScrollOrientation.backward); this.forwardScrollFn = this.createScrollFn(this.direction, DropScrollOrientation.forward, this.speedFn); this.backwardScrollFn = this.createScrollFn(this.direction, DropScrollOrientation.backward, this.speedFn); this.zone.runOutsideAngular((/** * @return {?} */ () => { // 拖拽到其上触发滚动 this.subscription.add(fromEvent(this.forwardScrollArea, 'dragover') .pipe(tap((/** * @param {?} event * @return {?} */ event => { event.preventDefault(); event.stopPropagation(); })), throttleTime(100, undefined, { leading: true, trailing: true })).subscribe((/** * @param {?} event * @return {?} */ event => this.forwardScrollFn(event)))); this.subscription.add(fromEvent(this.backwardScrollArea, 'dragover') .pipe(tap((/** * @param {?} event * @return {?} */ event => { event.preventDefault(); event.stopPropagation(); })), throttleTime(100, undefined, { leading: true, trailing: true })) .subscribe((/** * @param {?} event * @return {?} */ event => this.backwardScrollFn(event)))); // 拖拽离开清除参数 this.subscription.add(mergeStatic(fromEvent(this.forwardScrollArea, 'dragleave', { passive: true }), fromEvent(this.backwardScrollArea, 'dragleave', { passive: true })).subscribe((/** * @param {?} event * @return {?} */ event => this.cleanLastScrollTime()))); // 滚动过程计算区域有效性,滚动条贴到边缘的时候无效,无效的时候设置鼠标事件可用为none this.subscription.add(fromEvent(this.el.nativeElement, 'scroll', { passive: true }) .pipe(throttleTime(300, undefined, { leading: true, trailing: true })) .subscribe((/** * @param {?} event * @return {?} */ event => { this.toggleScrollToOneEnd(this.el.nativeElement, this.forwardScrollArea, this.direction, DropScrollOrientation.forward); this.toggleScrollToOneEnd(this.el.nativeElement, this.backwardScrollArea, this.direction, DropScrollOrientation.backward); }))); // 窗口缩放的时候重绘有效性区域 this.subscription.add(fromEvent(window, 'resize', { passive: true }) .pipe(throttleTime(300, undefined, { leading: true, trailing: true })) .subscribe((/** * @param {?} event * @return {?} */ event => this.resizeArea()))); // dragstart的时候显示拖拽滚动边缘面板 this.subscription.add(this.dragDropService.dragStartEvent.subscribe((/** * @return {?} */ () => { if (!this.allowScroll()) { return; } this.zone.runOutsideAngular((/** * @return {?} */ () => { setTimeout((/** * @return {?} */ () => { // 立马出现会打断边缘元素的拖拽 this.forwardScrollArea.style.display = 'block'; this.backwardScrollArea.style.display = 'block'; })); })); }))); // dragEnd或drop的时候结束了拖拽,滚动区域影藏起来 this.subscription.add(mergeStatic(this.dragDropService.dragEndEvent, this.dragDropService.dropEvent) .subscribe((/** * @return {?} */ () => { this.forwardScrollArea.style.display = 'none'; this.backwardScrollArea.style.display = 'none'; this.lastScrollTime = undefined; }))); })); setTimeout((/** * @return {?} */ () => { this.resizeArea(); }), 0); } /** * @return {?} */ ngOnDestroy() { this.subscription.unsubscribe(); } /** * @param {?} direction * @param {?} orientation * @param {?} speedFn * @return {?} */ createScrollFn(direction, orientation, speedFn) { /** @type {?} */ const scrollAttr = (direction === 'v') ? 'scrollTop' : 'scrollLeft'; /** @type {?} */ const eventAttr = (direction === 'v') ? 'clientY' : 'clientX'; /** @type {?} */ const scrollWidthAttr = (direction === 'v') ? 'scrollHeight' : 'scrollWidth'; /** @type {?} */ const rectWidthAttr = (direction === 'v') ? 'height' : 'width'; /** @type {?} */ const compareTarget = (orientation === DropScrollOrientation.forward) ? this.forwardScrollArea : this.backwardScrollArea; /** @type {?} */ const targetAttr = this.getCriticalEdge(direction, orientation); /** @type {?} */ const scrollElement = this.el.nativeElement; return (/** * @param {?} event * @return {?} */ (event) => { /** @type {?} */ const compareTargetRect = compareTarget.getBoundingClientRect(); /** @type {?} */ const distance = event[eventAttr] - compareTargetRect[targetAttr]; /** @type {?} */ let speed = speedFn(Math.abs(distance / (compareTargetRect[rectWidthAttr] || 1))); if (speed < this.minSpeed) { speed = this.minSpeed; } if (speed > this.maxSpeed) { speed = this.maxSpeed; } if (distance < 0) { speed = -speed; } requestAnimationFrame((/** * @return {?} */ () => { /** @type {?} */ const time = new Date().getTime(); /** @type {?} */ const moveDistance = Math.ceil(speed * (time - (this.lastScrollTime || time)) / 1000); scrollElement[scrollAttr] -= moveDistance; this.lastScrollTime = time; // 判断是不是到尽头 if ((scrollElement[scrollAttr] === 0 && orientation === DropScrollOrientation.backward) || ((scrollElement[scrollAttr] + (scrollElement.getBoundingClientRect())[rectWidthAttr]) === scrollElement[scrollWidthAttr] && orientation === DropScrollOrientation.forward)) { compareTarget.style.pointerEvents = 'none'; this.toggleActiveClass(compareTarget, false); } })); }); } /** * @param {?} direction * @param {?} orientation * @return {?} */ getCriticalEdge(direction, orientation) { return (direction === 'v' && orientation === DropScrollOrientation.forward && 'bottom') || (direction === 'v' && orientation === DropScrollOrientation.backward && 'top') || (direction !== 'v' && orientation === DropScrollOrientation.forward && 'right') || (direction !== 'v' && orientation === DropScrollOrientation.backward && 'left') || 'bottom'; } /** * @param {?} direction * @return {?} */ getSecondEdge(direction) { return (direction === 'v' && 'left') || (direction !== 'v' && 'top') || 'left'; } /** * @param {?} direction * @param {?} orientation * @return {?} */ createScrollArea(direction, orientation) { /** @type {?} */ const area = document.createElement('div'); area.className = 'dropover-scroll-area ' + 'dropover-scroll-area-' + this.getCriticalEdge(direction, orientation); // 处理大小 area.classList.add('active'); this.setAreaSize(area, direction, orientation); // 处理位置 area.style.position = 'absolute'; this.setAreaStyleLayout(area, direction, orientation); // 默认不展示 area.style.display = 'none'; // 附着元素 this.el.nativeElement.parentNode.appendChild(area, this.el.nativeElement); return area; } /** * @param {?} area * @param {?} direction * @param {?} orientation * @return {?} */ setAreaSize(area, direction, orientation) { /** @type {?} */ const rect = this.el.nativeElement.getBoundingClientRect(); /** @type {?} */ const containerAttr = direction === 'v' ? 'height' : 'width'; /** @type {?} */ const responseEdgeWidth = (typeof this.responseEdgeWidth === 'string') ? this.responseEdgeWidth : this.responseEdgeWidth(rect[containerAttr]); /** @type {?} */ const settingOffset = this.viewOffset && (orientation === DropScrollOrientation.forward ? this.viewOffset.forward : this.viewOffset.backward); /** @type {?} */ let width = direction === 'v' ? (rect.width + 'px') : responseEdgeWidth; /** @type {?} */ let height = direction === 'v' ? responseEdgeWidth : (rect.height + 'px'); if (settingOffset) { if (settingOffset.widthOffset) { width = 'calc(' + width + ' + ' + (settingOffset.widthOffset) + 'px)'; } if (settingOffset.heightOffset) { height = 'calc(' + height + ' + ' + (settingOffset.heightOffset) + 'px)'; } } area.style.width = width; area.style.height = height; } /** * @param {?} area * @param {?} direction * @param {?} orientation * @return {?} */ setAreaStyleLayout(area, direction, orientation) { /** @type {?} */ const target = this.el.nativeElement; /** @type {?} */ const relatedTarget = this.el.nativeElement.parentNode; /** @type {?} */ const defaultOffset = { left: 0, right: 0, top: 0, bottom: 0 }; /** @type {?} */ const settingOffset = this.viewOffset && (orientation === DropScrollOrientation.forward ? this.viewOffset.forward : this.viewOffset.backward) || defaultOffset; /** @type {?} */ const criticalEdge = this.getCriticalEdge(direction, orientation); /** @type {?} */ const secondEdge = this.getSecondEdge(direction); [criticalEdge, secondEdge].forEach((/** * @param {?} edge * @return {?} */ edge => { area.style[edge] = this.getRelatedPosition(target, relatedTarget, edge, settingOffset[edge]); })); } /** * @param {?} target * @param {?} relatedTarget * @param {?} edge * @param {?=} offsetValue * @return {?} */ getRelatedPosition(target, relatedTarget, edge, offsetValue) { /** @type {?} */ const relatedComputedStyle = window.getComputedStyle(relatedTarget); /** @type {?} */ const relatedRect = relatedTarget.getBoundingClientRect(); /** @type {?} */ const selfRect = target.getBoundingClientRect(); /** @type {?} */ const helper = { left: ['left', 'Left'], right: ['right', 'Right'], top: ['top', 'Top'], bottom: ['bottom', 'Bottom'], }; /** @type {?} */ let factor = 1; if (edge === 'right' || edge === 'bottom') { factor = -1; } return (selfRect[helper[edge][0]] - relatedRect[helper[edge][0]] + parseInt(relatedComputedStyle['border' + helper[edge][1] + 'Width'], 10)) * factor + (offsetValue || 0) + 'px'; } /** * @return {?} */ resizeArea() { [{ area: this.forwardScrollArea, orientation: DropScrollOrientation.forward }, { area: this.backwardScrollArea, orientation: DropScrollOrientation.backward } ] .forEach((/** * @param {?} item * @return {?} */ item => { this.setAreaSize(item.area, this.direction, item.orientation); this.setAreaStyleLayout(item.area, this.direction, item.orientation); })); } /** * @param {?} scrollElement * @param {?} toggleElement * @param {?} direction * @param {?} orientation * @return {?} */ toggleScrollToOneEnd(scrollElement, toggleElement, direction, orientation) { /** @type {?} */ const scrollAttr = (direction === 'v') ? 'scrollTop' : 'scrollLeft'; /** @type {?} */ const scrollWidthAttr = (direction === 'v') ? 'scrollHeight' : 'scrollWidth'; /** @type {?} */ const rectWidthAttr = (direction === 'v') ? 'height' : 'width'; if ((scrollElement[scrollAttr] === 0 && orientation === DropScrollOrientation.backward) || (Math.abs(scrollElement[scrollAttr] + (scrollElement.getBoundingClientRect())[rectWidthAttr] - scrollElement[scrollWidthAttr]) < 1 && orientation === DropScrollOrientation.forward)) { toggleElement.style.pointerEvents = 'none'; this.toggleActiveClass(toggleElement, false); } else { toggleElement.style.pointerEvents = 'auto'; this.toggleActiveClass(toggleElement, true); } } /** * @return {?} */ cleanLastScrollTime() { this.lastScrollTime = undefined; } /** * @param {?} target * @param {?} active * @return {?} */ toggleActiveClass(target, active) { if (active) { target.classList.remove('inactive'); target.classList.add('active'); } else { target.classList.remove('active'); target.classList.add('inactive'); } } /** * @return {?} */ allowScroll() { if (!this.dropScrollScope) { return true; } /** @type {?} */ let allowed = false; if (typeof this.dropScrollScope === 'string') { if (typeof this.dragDropService.scope === 'string') { allowed = this.dragDropService.scope === this.dropScrollScope; } if (this.dragDropService.scope instanceof Array) { allowed = this.dragDropService.scope.indexOf(this.dropScrollScope) > -1; } } if (this.dropScrollScope instanceof Array) { if (typeof this.dragDropService.scope === 'string') { allowed = this.dropScrollScope.indexOf(this.dragDropService.scope) > -1; } if (this.dragDropService.scope instanceof Array) { allowed = this.dropScrollScope.filter((/** * @param {?} item * @return {?} */ (item) => { return this.dragDropService.scope.indexOf(item) !== -1; })).length > 0; } } return allowed; } } DropScrollEnhancedDirective.decorators = [ { type: Directive, args: [{ selector: '[dDropScrollEnhanced]', exportAs: 'dDropScrollEnhanced' },] } ]; /** @nocollapse */ DropScrollEnhancedDirective.ctorParameters = () => [ { type: ElementRef }, { type: NgZone }, { type: DragDropService } ]; DropScrollEnhancedDirective.propDecorators = { minSpeed: [{ type: Input }], maxSpeed: [{ type: Input }], responseEdgeWidth: [{ type: Input }], speedFn: [{ type: Input }], direction: [{ type: Input }], viewOffset: [{ type: Input }], dropScrollScope: [{ type: Input }] }; if (false) { /** @type {?} */ DropScrollEnhancedDirective.prototype.minSpeed; /** @type {?} */ DropScrollEnhancedDirective.prototype.maxSpeed; /** @type {?} */ DropScrollEnhancedDirective.prototype.responseEdgeWidth; /** @type {?} */ DropScrollEnhancedDirective.prototype.speedFn; /** @type {?} */ DropScrollEnhancedDirective.prototype.direction; /** @type {?} */ DropScrollEnhancedDirective.prototype.viewOffset; /** @type {?} */ DropScrollEnhancedDirective.prototype.dropScrollScope; /** * @type {?} * @private */ DropScrollEnhancedDirective.prototype.forwardScrollArea; /** * @type {?} * @private */ DropScrollEnhancedDirective.prototype.backwardScrollArea; /** * @type {?} * @private */ DropScrollEnhancedDirective.prototype.subscription; /** * @type {?} * @private */ DropScrollEnhancedDirective.prototype.forwardScrollFn; /** * @type {?} * @private */ DropScrollEnhancedDirective.prototype.backwardScrollFn; /** * @type {?} * @private */ DropScrollEnhancedDirective.prototype.lastScrollTime; /** * @type {?} * @private */ DropScrollEnhancedDirective.prototype.el; /** * @type {?} * @private */ DropScrollEnhancedDirective.prototype.zone; /** * @type {?} * @private */ DropScrollEnhancedDirective.prototype.dragDropService; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcC1zY3JvbGwtZW5oYW5jZS5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZy1kZXZ1aS9kcmFnZHJvcC8iLCJzb3VyY2VzIjpbImRpcmVjdGl2ZXMvZHJvcC1zY3JvbGwtZW5oYW5jZS5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxPQUFPLEVBQTRDLG9DQUFvQyxFQUMvRCxxQkFBcUIsRUFBeUIsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RyxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUE0QixNQUFNLGVBQWUsQ0FBQztBQUMvRixPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLElBQUksV0FBVyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBTWhFLE1BQU0sT0FBTywyQkFBMkI7Ozs7OztJQW1CdEMsWUFBb0IsRUFBYyxFQUFVLElBQVksRUFBVSxlQUFnQztRQUE5RSxPQUFFLEdBQUYsRUFBRSxDQUFZO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUFVLG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQWxCekYsYUFBUSxHQUFvQixFQUFFLENBQUM7UUFDL0IsYUFBUSxHQUFvQixJQUFJLENBQUM7UUFDakMsc0JBQWlCLEdBQTBDLE9BQU8sQ0FBQztRQUNuRSxZQUFPLEdBQTRCLG9DQUFvQyxDQUFDLE9BQU8sQ0FBQztRQUNoRixjQUFTLEdBQXdCLEdBQUcsQ0FBQztRQVN0QyxpQkFBWSxHQUFpQixJQUFJLFlBQVksRUFBRSxDQUFDO0lBSzZDLENBQUM7Ozs7SUFFdEcsZUFBZTtRQUNiLFFBQVE7UUFDUixJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFD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RDs7Ozs7SUFDeEQsc0RBQWdEOzs7OztJQUNoRCx1REFBaUQ7Ozs7O0lBQ2pELHFEQUF1Qjs7Ozs7SUFFWCx5Q0FBc0I7Ozs7O0lBQUUsMkNBQW9COzs7OztJQUFFLHNEQUF3QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERyb3BTY3JvbGxTcGVlZEZ1bmN0aW9uLCBEcm9wU2Nyb2xsU3BlZWQsIERyb3BTY3JvbGxFbmhhbmNlVGltaW5nRnVuY3Rpb25Hcm91cCwgRHJvcFNjcm9sbERpcmVjdGlvbixcclxuICBEcm9wU2Nyb2xsQXJlYU9mZnNldCwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLCBEcm9wU2Nyb2xsVHJpZ2dlckVkZ2UgfSBmcm9tICcuL2Ryb3Atc2Nyb2xsLWVuaGFuY2UudHlwZSc7XHJcbmltcG9ydCB7IERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgSW5wdXQsIE5nWm9uZSwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IGZyb21FdmVudCwgU3Vic2NyaXB0aW9uLCBtZXJnZSBhcyBtZXJnZVN0YXRpYyB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyB0aHJvdHRsZVRpbWUsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgRHJhZ0Ryb3BTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvZHJhZy1kcm9wLnNlcnZpY2UnO1xyXG5cclxuQERpcmVjdGl2ZSh7XHJcbiAgc2VsZWN0b3I6ICdbZERyb3BTY3JvbGxFbmhhbmNlZF0nLFxyXG4gIGV4cG9ydEFzOiAnZERyb3BTY3JvbGxFbmhhbmNlZCdcclxufSlcclxuZXhwb3J0IGNsYXNzIERyb3BTY3JvbGxFbmhhbmNlZERpcmVjdGl2ZSBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgQElucHV0KCkgbWluU3BlZWQ6IERyb3BTY3JvbGxTcGVlZCA9IDUwO1xyXG4gIEBJbnB1dCgpIG1heFNwZWVkOiBEcm9wU2Nyb2xsU3BlZWQgPSAxMDAwO1xyXG4gIEBJbnB1dCgpIHJlc3BvbnNlRWRnZVdpZHRoOiBzdHJpbmcgfCAoKHRvdGFsOiBudW1iZXIpID0+IHN0cmluZykgID0gJzEwMHB4JztcclxuICBASW5wdXQoKSBzcGVlZEZuOiBEcm9wU2Nyb2xsU3BlZWRGdW5jdGlvbiA9IERyb3BTY3JvbGxFbmhhbmNlVGltaW5nRnVuY3Rpb25Hcm91cC5kZWZhdWx0O1xyXG4gIEBJbnB1dCgpIGRpcmVjdGlvbjogRHJvcFNjcm9sbERpcmVjdGlvbiA9ICd2JztcclxuICBASW5wdXQoKSB2aWV3T2Zmc2V0OiB7XHJcbiAgICBmb3J3YXJkPzogRHJvcFNjcm9sbEFyZWFPZmZzZXQ7IC8vIOS7hemHjeimgei+ueWSjOasoeimgei+ueacieaViFxyXG4gICAgYmFja3dhcmQ/OiBEcm9wU2Nyb2xsQXJlYU9mZnNldDtcclxuICB9O1xyXG4gIEBJbnB1dCgpIGRyb3BTY3JvbGxTY29wZTogc3RyaW5nIHwgQXJyYXk8c3RyaW5nPjtcclxuXHJcbiAgcHJpdmF0ZSBmb3J3YXJkU2Nyb2xsQXJlYTogSFRNTEVsZW1lbnQ7XHJcbiAgcHJpdmF0ZSBiYWNrd2FyZFNjcm9sbEFyZWE6IEhUTUxFbGVtZW50O1xyXG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XHJcbiAgcHJpdmF0ZSBmb3J3YXJkU2Nyb2xsRm46IChldmVudDogRXZlbnQpID0+IHZvaWQ7XHJcbiAgcHJpdmF0ZSBiYWNrd2FyZFNjcm9sbEZuOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkO1xyXG4gIHByaXZhdGUgbGFzdFNjcm9sbFRpbWU7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWw6IEVsZW1lbnRSZWYsIHByaXZhdGUgem9uZTogTmdab25lLCBwcml2YXRlIGRyYWdEcm9wU2VydmljZTogRHJhZ0Ryb3BTZXJ2aWNlKSB7fVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICAvLyDorr7nva7niLblhYPntKBcclxuICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5wYXJlbnROb2RlLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcclxuICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5wYXJlbnROb2RlLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xyXG4gICAgLy8g5Yib5bu65ZCO6YCA5YmN6L+b5Yy65Z+f5ZKM5a+55bqU55qE5rua5Yqo5Ye95pWwXHJcbiAgICB0aGlzLmZvcndhcmRTY3JvbGxBcmVhID0gdGhpcy5jcmVhdGVTY3JvbGxBcmVhKHRoaXMuZGlyZWN0aW9uLCBEcm9wU2Nyb2xsT3JpZW50YXRpb24uZm9yd2FyZCk7XHJcbiAgICB0aGlzLmJhY2t3YXJkU2Nyb2xsQXJlYSA9IHRoaXMuY3JlYXRlU2Nyb2xsQXJlYSh0aGlzLmRpcmVjdGlvbiwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLmJhY2t3YXJkKTtcclxuICAgIHRoaXMuZm9yd2FyZFNjcm9sbEZuID0gdGhpcy5jcmVhdGVTY3JvbGxGbih0aGlzLmRpcmVjdGlvbiwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQsIHRoaXMuc3BlZWRGbik7XHJcbiAgICB0aGlzLmJhY2t3YXJkU2Nyb2xsRm4gPSB0aGlzLmNyZWF0ZVNjcm9sbEZuKHRoaXMuZGlyZWN0aW9uLCBEcm9wU2Nyb2xsT3JpZW50YXRpb24uYmFja3dhcmQsIHRoaXMuc3BlZWRGbik7XHJcbiAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xyXG4gICAgICAvLyDmi5bmi73liLDlhbbkuIrop6blj5Hmu5rliqhcclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb24uYWRkKGZyb21FdmVudCh0aGlzLmZvcndhcmRTY3JvbGxBcmVhLCAnZHJhZ292ZXInKVxyXG4gICAgICAgIC5waXBlKFxyXG4gICAgICAgICAgdGFwKGV2ZW50ID0+IHtldmVudC5wcmV2ZW50RGVmYXVsdCgpOyBldmVudC5zdG9wUHJvcGFnYXRpb24oKTsgfSksXHJcbiAgICAgICAgICB0aHJvdHRsZVRpbWUoMTAwLCB1bmRlZmluZWQsIHtsZWFkaW5nOiB0cnVlLCB0cmFpbGluZzogdHJ1ZX0pXHJcbiAgICAgICAgKS5zdWJzY3JpYmUoZXZlbnQgPT4gdGhpcy5mb3J3YXJkU2Nyb2xsRm4oZXZlbnQpKSk7XHJcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uLmFkZChmcm9tRXZlbnQodGhpcy5iYWNrd2FyZFNjcm9sbEFyZWEsICdkcmFnb3ZlcicpXHJcbiAgICAgICAgLnBpcGUoXHJcbiAgICAgICAgICB0YXAoZXZlbnQgPT4ge2V2ZW50LnByZXZlbnREZWZhdWx0KCk7IGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyB9KSxcclxuICAgICAgICAgIHRocm90dGxlVGltZSgxMDAsIHVuZGVmaW5lZCwge2xlYWRpbmc6IHRydWUsIHRyYWlsaW5nOiB0cnVlfSkpXHJcbiAgICAgICAgLnN1YnNjcmliZShldmVudCA9PiB0aGlzLmJhY2t3YXJkU2Nyb2xsRm4oZXZlbnQpKSk7XHJcbiAgICAgIC8vIOaLluaLveemu+W8gOa4hemZpOWPguaVsFxyXG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbi5hZGQoXHJcbiAgICAgICAgbWVyZ2VTdGF0aWMoXHJcbiAgICAgICAgICBmcm9tRXZlbnQodGhpcy5mb3J3YXJkU2Nyb2xsQXJlYSwgJ2RyYWdsZWF2ZScsIHtwYXNzaXZlOiB0cnVlfSksXHJcbiAgICAgICAgICBmcm9tRXZlbnQodGhpcy5iYWNrd2FyZFNjcm9sbEFyZWEsICdkcmFnbGVhdmUnLCB7cGFzc2l2ZTogdHJ1ZX0pXHJcbiAgICAgICAgKS5zdWJzY3JpYmUoZXZlbnQgPT4gdGhpcy5jbGVhbkxhc3RTY3JvbGxUaW1lKCkpXHJcbiAgICAgICk7XHJcbiAgICAgIC8vIOa7muWKqOi/h+eoi+iuoeeul+WMuuWfn+acieaViOaAp++8jOa7muWKqOadoei0tOWIsOi+uee8mOeahOaXtuWAmeaXoOaViO+8jOaXoOaViOeahOaXtuWAmeiuvue9rum8oOagh+S6i+S7tuWPr+eUqOS4um5vbmVcclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb24uYWRkKFxyXG4gICAgICAgIGZyb21FdmVudCh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsICdzY3JvbGwnLCB7cGFzc2l2ZTogdHJ1ZX0pXHJcbiAgICAgICAgLnBpcGUodGhyb3R0bGVUaW1lKDMwMCwgdW5kZWZpbmVkLCB7bGVhZGluZzogdHJ1ZSwgdHJhaWxpbmc6IHRydWV9KSlcclxuICAgICAgICAuc3Vic2NyaWJlKGV2ZW50ID0+IHtcclxuICAgICAgICAgIHRoaXMudG9nZ2xlU2Nyb2xsVG9PbmVFbmQodGhpcy5lbC5uYXRpdmVFbGVtZW50LCB0aGlzLmZvcndhcmRTY3JvbGxBcmVhLCB0aGlzLmRpcmVjdGlvbiwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQpO1xyXG4gICAgICAgICAgdGhpcy50b2dnbGVTY3JvbGxUb09uZUVuZCh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsIHRoaXMuYmFja3dhcmRTY3JvbGxBcmVhLCB0aGlzLmRpcmVjdGlvbiwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLmJhY2t3YXJkKTtcclxuICAgICAgICB9KVxyXG4gICAgICApO1xyXG4gICAgICAvLyDnqpflj6PnvKnmlL7nmoTml7blgJnph43nu5jmnInmlYjmgKfljLrln59cclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb24uYWRkKFxyXG4gICAgICAgIGZyb21FdmVudCh3aW5kb3csICdyZXNpemUnLCB7cGFzc2l2ZTogdHJ1ZX0pXHJcbiAgICAgICAgLnBpcGUodGhyb3R0bGVUaW1lKDMwMCwgdW5kZWZpbmVkLCB7bGVhZGluZzogdHJ1ZSwgdHJhaWxpbmc6IHRydWV9KSlcclxuICAgICAgICAuc3Vic2NyaWJlKGV2ZW50ID0+IHRoaXMucmVzaXplQXJlYSgpKVxyXG4gICAgICApO1xyXG4gICAgICAvLyBkcmFnc3RhcnTnmoTml7blgJnmmL7npLrmi5bmi73mu5rliqjovrnnvJjpnaLmnb9cclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb24uYWRkKFxyXG4gICAgICAgIHRoaXMuZHJhZ0Ryb3BTZXJ2aWNlLmRyYWdTdGFydEV2ZW50LnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5hbGxvd1Njcm9sbCgpKSB7cmV0dXJuOyB9XHJcbiAgICAgICAgICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAvLyDnq4vpqazlh7rnjrDkvJrmiZPmlq3ovrnnvJjlhYPntKDnmoTmi5bmi71cclxuICAgICAgICAgICAgICAgIHRoaXMuZm9yd2FyZFNjcm9sbEFyZWEuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmJhY2t3YXJkU2Nyb2xsQXJlYS5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSlcclxuICAgICAgKTtcclxuICAgICAgLy8gZHJhZ0VuZOaIlmRyb3DnmoTml7blgJnnu5PmnZ/kuobmi5bmi73vvIzmu5rliqjljLrln5/lvbHol4/otbfmnaVcclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb24uYWRkKFxyXG4gICAgICAgICAgbWVyZ2VTdGF0aWMoIHRoaXMuZHJhZ0Ryb3BTZXJ2aWNlLmRyYWdFbmRFdmVudCwgdGhpcy5kcmFnRHJvcFNlcnZpY2UuZHJvcEV2ZW50KVxyXG4gICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuZm9yd2FyZFNjcm9sbEFyZWEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcclxuICAgICAgICAgICAgdGhpcy5iYWNrd2FyZFNjcm9sbEFyZWEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcclxuICAgICAgICAgICAgdGhpcy5sYXN0U2Nyb2xsVGltZSA9IHVuZGVmaW5lZDtcclxuICAgICAgICB9KVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgdGhpcy5yZXNpemVBcmVhKCk7XHJcbiAgICB9LCAwKTtcclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCkge1xyXG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICB9XHJcblxyXG4gIGNyZWF0ZVNjcm9sbEZuKGRpcmVjdGlvbjogRHJvcFNjcm9sbERpcmVjdGlvbiwgb3JpZW50YXRpb246IERyb3BTY3JvbGxPcmllbnRhdGlvbixcclxuICAgICAgc3BlZWRGbjogRHJvcFNjcm9sbFNwZWVkRnVuY3Rpb24pIHtcclxuICAgIGNvbnN0IHNjcm9sbEF0dHIgPSAoZGlyZWN0aW9uID09PSAndicpID8gJ3Njcm9sbFRvcCcgOiAnc2Nyb2xsTGVmdCc7XHJcbiAgICBjb25zdCBldmVudEF0dHIgPSAoZGlyZWN0aW9uID09PSAndicpID8gJ2NsaWVudFknIDogJ2NsaWVudFgnO1xyXG4gICAgY29uc3Qgc2Nyb2xsV2lkdGhBdHRyID0gKGRpcmVjdGlvbiA9PT0gJ3YnKSA/ICdzY3JvbGxIZWlnaHQnIDogJ3Njcm9sbFdpZHRoJztcclxuICAgIGNvbnN0IHJlY3RXaWR0aEF0dHIgPSAoZGlyZWN0aW9uID09PSAndicpID8gJ2hlaWdodCcgOiAnd2lkdGgnO1xyXG4gICAgY29uc3QgY29tcGFyZVRhcmdldCA9IChvcmllbnRhdGlvbiA9PT0gRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQpID8gdGhpcy5mb3J3YXJkU2Nyb2xsQXJlYSA6IHRoaXMuYmFja3dhcmRTY3JvbGxBcmVhO1xyXG4gICAgY29uc3QgdGFyZ2V0QXR0ciA9IHRoaXMuZ2V0Q3JpdGljYWxFZGdlKGRpcmVjdGlvbiwgb3JpZW50YXRpb24pO1xyXG4gICAgY29uc3Qgc2Nyb2xsRWxlbWVudCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudDtcclxuXHJcbiAgICByZXR1cm4gKGV2ZW50OiBFdmVudCkgPT4ge1xyXG4gICAgICBjb25zdCBjb21wYXJlVGFyZ2V0UmVjdCA9IGNvbXBhcmVUYXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcbiAgICAgIGNvbnN0IGRpc3RhbmNlID0gZXZlbnRbZXZlbnRBdHRyXSAtIGNvbXBhcmVUYXJnZXRSZWN0W3RhcmdldEF0dHJdO1xyXG4gICAgICBsZXQgc3BlZWQgPSBzcGVlZEZuKE1hdGguYWJzKGRpc3RhbmNlIC8gKGNvbXBhcmVUYXJnZXRSZWN0W3JlY3RXaWR0aEF0dHJdIHx8IDEpKSk7XHJcbiAgICAgIGlmIChzcGVlZCA8IHRoaXMubWluU3BlZWQpIHsgc3BlZWQgPSB0aGlzLm1pblNwZWVkOyB9XHJcbiAgICAgIGlmIChzcGVlZCA+IHRoaXMubWF4U3BlZWQpIHsgc3BlZWQgPSB0aGlzLm1heFNwZWVkOyB9XHJcbiAgICAgIGlmIChkaXN0YW5jZSA8IDApIHsgc3BlZWQgPSAtIHNwZWVkOyB9XHJcbiAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XHJcbiAgICAgICAgY29uc3QgdGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xyXG4gICAgICAgIGNvbnN0IG1vdmVEaXN0YW5jZSA9IE1hdGguY2VpbChzcGVlZCAqICh0aW1lIC0gKHRoaXMubGFzdFNjcm9sbFRpbWUgfHwgdGltZSkpIC8gMTAwMCk7XHJcbiAgICAgICAgc2Nyb2xsRWxlbWVudFtzY3JvbGxBdHRyXSAtPSBtb3ZlRGlzdGFuY2U7XHJcbiAgICAgICAgdGhpcy5sYXN0U2Nyb2xsVGltZSA9IHRpbWU7XHJcbiAgICAgICAgLy8g5Yik5pat5piv5LiN5piv5Yiw5bC95aS0XHJcbiAgICAgICAgaWYgKChzY3JvbGxFbGVtZW50W3Njcm9sbEF0dHJdID09PSAwICYmIG9yaWVudGF0aW9uID09PSBEcm9wU2Nyb2xsT3JpZW50YXRpb24uYmFja3dhcmQpXHJcbiAgICAgICAgfHwgKChzY3JvbGxFbGVtZW50W3Njcm9sbEF0dHJdICsgKHNjcm9sbEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkpW3JlY3RXaWR0aEF0dHJdKSA9PT0gc2Nyb2xsRWxlbWVudFtzY3JvbGxXaWR0aEF0dHJdXHJcbiAgICAgICAgICAmJiBvcmllbnRhdGlvbiA9PT0gRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQpXHJcbiAgICAgICAgKSB7XHJcbiAgICAgICAgICBjb21wYXJlVGFyZ2V0LnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7XHJcbiAgICAgICAgICB0aGlzLnRvZ2dsZUFjdGl2ZUNsYXNzKGNvbXBhcmVUYXJnZXQsIGZhbHNlKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfTtcclxuXHJcbiAgfVxyXG4gIGdldENyaXRpY2FsRWRnZShkaXJlY3Rpb246IERyb3BTY3JvbGxEaXJlY3Rpb24sIG9yaWVudGF0aW9uOiBEcm9wU2Nyb2xsT3JpZW50YXRpb24pOiBEcm9wU2Nyb2xsVHJpZ2dlckVkZ2Uge1xyXG4gICAgcmV0dXJuIChkaXJlY3Rpb24gPT09ICd2JyAmJiBvcmllbnRhdGlvbiA9PT0gRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQgJiYgJ2JvdHRvbScpXHJcbiAgICB8fCAoZGlyZWN0aW9uID09PSAndicgJiYgb3JpZW50YXRpb24gPT09IERyb3BTY3JvbGxPcmllbnRhdGlvbi5iYWNrd2FyZCAmJiAndG9wJylcclxuICAgIHx8IChkaXJlY3Rpb24gIT09ICd2JyAmJiBvcmllbnRhdGlvbiA9PT0gRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQgJiYgJ3JpZ2h0JylcclxuICAgIHx8IChkaXJlY3Rpb24gIT09ICd2JyAmJiBvcmllbnRhdGlvbiA9PT0gRHJvcFNjcm9sbE9yaWVudGF0aW9uLmJhY2t3YXJkICYmICdsZWZ0JykgfHwgJ2JvdHRvbSc7XHJcbiAgfVxyXG4gIGdldFNlY29uZEVkZ2UoZGlyZWN0aW9uOiBEcm9wU2Nyb2xsRGlyZWN0aW9uKTogRHJvcFNjcm9sbFRyaWdnZXJFZGdlIHtcclxuICAgIHJldHVybiAoZGlyZWN0aW9uID09PSAndicgJiYgJ2xlZnQnKVxyXG4gICAgfHwgKGRpcmVjdGlvbiAhPT0gJ3YnICYmICAndG9wJykgfHwgJ2xlZnQnO1xyXG4gIH1cclxuXHJcbiAgY3JlYXRlU2Nyb2xsQXJlYShkaXJlY3Rpb246IERyb3BTY3JvbGxEaXJlY3Rpb24sIG9yaWVudGF0aW9uOiBEcm9wU2Nyb2xsT3JpZW50YXRpb24pIHtcclxuICAgIGNvbnN0IGFyZWEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICAgIGFyZWEuY2xhc3NOYW1lID0gJ2Ryb3BvdmVyLXNjcm9sbC1hcmVhICcgKyAnZHJvcG92ZXItc2Nyb2xsLWFyZWEtJyArIHRoaXMuZ2V0Q3JpdGljYWxFZGdlKGRpcmVjdGlvbiwgb3JpZW50YXRpb24pO1xyXG4gICAgLy8g5aSE55CG5aSn5bCPXHJcbiAgICBhcmVhLmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xyXG4gICAgdGhpcy5zZXRBcmVhU2l6ZShhcmVhLCBkaXJlY3Rpb24sIG9yaWVudGF0aW9uKTtcclxuICAgIC8vIOWkhOeQhuS9jee9rlxyXG4gICAgYXJlYS5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XHJcbiAgICB0aGlzLnNldEFyZWFTdHlsZUxheW91dChhcmVhLCBkaXJlY3Rpb24sIG9yaWVudGF0aW9uKTtcclxuXHJcbiAgICAvLyDpu5jorqTkuI3lsZXnpLpcclxuICAgIGFyZWEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcclxuICAgIC8vIOmZhOedgOWFg+e0oFxyXG4gICAgdGhpcy5lbC5uYXRpdmVFbGVtZW50LnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQoYXJlYSwgdGhpcy5lbC5uYXRpdmVFbGVtZW50KTtcclxuICAgIHJldHVybiBhcmVhO1xyXG4gIH1cclxuXHJcbiAgc2V0QXJlYVNpemUoYXJlYTogSFRNTEVsZW1lbnQsIGRpcmVjdGlvbjogRHJvcFNjcm9sbERpcmVjdGlvbiwgb3JpZW50YXRpb246IERyb3BTY3JvbGxPcmllbnRhdGlvbikge1xyXG4gICAgY29uc3QgcmVjdCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgIGNvbnN0IGNvbnRhaW5lckF0dHIgPSBkaXJlY3Rpb24gPT09ICd2JyA/ICdoZWlnaHQnIDogJ3dpZHRoJztcclxuICAgIGNvbnN0IHJlc3BvbnNlRWRnZVdpZHRoID0gKHR5cGVvZiB0aGlzLnJlc3BvbnNlRWRnZVdpZHRoID09PSAnc3RyaW5nJylcclxuICAgICAgPyB0aGlzLnJlc3BvbnNlRWRnZVdpZHRoXHJcbiAgICAgIDogdGhpcy5yZXNwb25zZUVkZ2VXaWR0aChyZWN0W2NvbnRhaW5lckF0dHJdKTtcclxuICAgIGNvbnN0IHNldHRpbmdPZmZzZXQgPSB0aGlzLnZpZXdPZmZzZXRcclxuICAgICAgJiYgKG9yaWVudGF0aW9uID09PSBEcm9wU2Nyb2xsT3JpZW50YXRpb24uZm9yd2FyZCA/IHRoaXMudmlld09mZnNldC5mb3J3YXJkIDogdGhpcy52aWV3T2Zmc2V0LmJhY2t3YXJkKTtcclxuICAgIGxldCB3aWR0aCA9IGRpcmVjdGlvbiA9PT0gJ3YnID8gKHJlY3Qud2lkdGggKyAncHgnKSA6IHJlc3BvbnNlRWRnZVdpZHRoO1xyXG4gICAgbGV0IGhlaWdodCA9ICBkaXJlY3Rpb24gPT09ICd2JyA/IHJlc3BvbnNlRWRnZVdpZHRoIDogKHJlY3QuaGVpZ2h0ICsgJ3B4Jyk7XHJcbiAgICBpZiAoc2V0dGluZ09mZnNldCkge1xyXG4gICAgICBpZiAoc2V0dGluZ09mZnNldC53aWR0aE9mZnNldCkge1xyXG4gICAgICAgIHdpZHRoID0gJ2NhbGMoJyArIHdpZHRoICsgJyArICcgKyAoc2V0dGluZ09mZnNldC53aWR0aE9mZnNldCkgKyAncHgpJztcclxuICAgICAgfVxyXG4gICAgICBpZiAoc2V0dGluZ09mZnNldC5oZWlnaHRPZmZzZXQpIHtcclxuICAgICAgICBoZWlnaHQgPSAnY2FsYygnICsgaGVpZ2h0ICsgJyArICcgKyAoc2V0dGluZ09mZnNldC5oZWlnaHRPZmZzZXQpICsgJ3B4KSc7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGFyZWEuc3R5bGUud2lkdGggPSB3aWR0aDtcclxuICAgIGFyZWEuc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0O1xyXG4gIH1cclxuXHJcbiAgc2V0QXJlYVN0eWxlTGF5b3V0IChhcmVhOiBIVE1MRWxlbWVudCwgZGlyZWN0aW9uOiBEcm9wU2Nyb2xsRGlyZWN0aW9uLCBvcmllbnRhdGlvbjogRHJvcFNjcm9sbE9yaWVudGF0aW9uKSB7XHJcbiAgICBjb25zdCB0YXJnZXQgPSB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICBjb25zdCByZWxhdGVkVGFyZ2V0ID0gdGhpcy5lbC5uYXRpdmVFbGVtZW50LnBhcmVudE5vZGU7XHJcbiAgICBjb25zdCBkZWZhdWx0T2Zmc2V0ID0ge2xlZnQ6IDAsIHJpZ2h0OiAwLCB0b3A6IDAsIGJvdHRvbTogMH07XHJcbiAgICBjb25zdCBzZXR0aW5nT2Zmc2V0ID0gdGhpcy52aWV3T2Zmc2V0XHJcbiAgICAgICYmIChvcmllbnRhdGlvbiA9PT0gRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQgPyB0aGlzLnZpZXdPZmZzZXQuZm9yd2FyZCA6IHRoaXM