@duoduo-oba/ng-devui
Version:
DevUI components based on Angular
508 lines • 55.4 kB
JavaScript
/**
* @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