UNPKG

ng-feedback

Version:

An angular directive for sending feedback featuring Angular 6, Html2canvas, Angular Material, Rxjs, inspired by Google send feedback, based on angular-cli.

950 lines 95.9 kB
import { Injectable, Component, ViewChild, ElementRef, ChangeDetectorRef, HostListener, Input, Output, EventEmitter, Directive, NgModule } from '@angular/core';
import html2canvas from 'html2canvas';
import { Subject, fromEvent } from 'rxjs';
import { takeUntil, finalize, map, mergeMap } from 'rxjs/operators';
import { MatDialogRef, MatDialog, MatDialogModule, MatButtonModule, MatIconModule, MatInputModule, MatTooltipModule, MatCheckboxModule, MatProgressSpinnerModule } from '@angular/material';
import { Overlay } from '@angular/cdk/overlay';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var Feedback = /** @class */ (function () {
    function Feedback() {
    }
    return Feedback;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var FeedbackService = /** @class */ (function () {
    function FeedbackService() {
        this.initialVariables = {};
        this.highlightedColor = 'yellow';
        this.hiddenColor = 'black';
        this.screenshotCanvasSource = new Subject();
        this.screenshotCanvas$ = this.screenshotCanvasSource.asObservable();
        this.feedbackSource = new Subject();
        this.feedback$ = this.feedbackSource.asObservable();
        this.isDraggingToolbarSource = new Subject();
        this.isDraggingToolbar$ = this.isDraggingToolbarSource.asObservable();
    }
    /**
     * @return {?}
     */
    FeedbackService.prototype.initScreenshotCanvas = /**
     * @return {?}
     */
    function () {
        var _this = this;
        /** @type {?} */
        var body = document.body;
        html2canvas(body, {
            logging: false,
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight,
            x: document.documentElement.scrollLeft,
            y: document.documentElement.scrollTop,
            allowTaint: true
        }).then(function (bodyCanvas) {
            _this.screenshotCanvasSource.next(bodyCanvas);
        });
    };
    /**
     * @param {?} canvas
     * @return {?}
     */
    FeedbackService.prototype.setCanvas = /**
     * @param {?} canvas
     * @return {?}
     */
    function (canvas) {
        this.screenshotCanvasSource.next(canvas);
    };
    /**
     * @param {?} feedback
     * @return {?}
     */
    FeedbackService.prototype.setFeedback = /**
     * @param {?} feedback
     * @return {?}
     */
    function (feedback) {
        this.feedbackSource.next(feedback);
    };
    /**
     * @param {?} isDragging
     * @return {?}
     */
    FeedbackService.prototype.setIsDraggingToolbar = /**
     * @param {?} isDragging
     * @return {?}
     */
    function (isDragging) {
        this.isDraggingToolbarSource.next(isDragging);
    };
    /**
     * @param {?} canvas
     * @return {?}
     */
    FeedbackService.prototype.getImgEle = /**
     * @param {?} canvas
     * @return {?}
     */
    function (canvas) {
        /** @type {?} */
        var img = canvas.toDataURL('image/png');
        /** @type {?} */
        var imageEle = document.createElement('img');
        imageEle.setAttribute('src', img);
        Object.assign(imageEle.style, {
            position: 'absolute',
            top: '50%',
            right: '0',
            left: '0',
            margin: '0 auto',
            maxHeight: '100%',
            maxWidth: '100%',
            transform: 'translateY(-50%)'
        });
        return imageEle;
    };
    /**
     * @return {?}
     */
    FeedbackService.prototype.hideBackDrop = /**
     * @return {?}
     */
    function () {
        /** @type {?} */
        var dialogBackDrop = /** @type {?} */ (document.getElementsByClassName('dialogBackDrop')[0]);
        dialogBackDrop.style.backgroundColor = 'initial';
    };
    /**
     * @return {?}
     */
    FeedbackService.prototype.showBackDrop = /**
     * @return {?}
     */
    function () {
        /** @type {?} */
        var dialogBackDrop = /** @type {?} */ (document.getElementsByClassName('dialogBackDrop')[0]);
        if (!dialogBackDrop.getAttribute('data-html2canvas-ignore')) {
            dialogBackDrop.setAttribute('data-html2canvas-ignore', 'true');
        }
        dialogBackDrop.style.backgroundColor = 'rgba(0, 0, 0, .288)';
    };
    FeedbackService.decorators = [
        { type: Injectable }
    ];
    return FeedbackService;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var Rectangle = /** @class */ (function () {
    function Rectangle() {
        this.windowScrollY = window.scrollY;
        this.windowScrollX = window.scrollX;
    }
    return Rectangle;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var FeedbackDialogComponent = /** @class */ (function () {
    function FeedbackDialogComponent(dialogRef, feedbackService, detector, el) {
        this.dialogRef = dialogRef;
        this.feedbackService = feedbackService;
        this.detector = detector;
        this.el = el;
        this.showToolbar = false;
        this.vars = {};
        this.feedback = new Feedback();
        this.includeScreenshot = true;
        this.showSpinner = true;
        this.showToolbarTips = true;
        this.drawColor = this.feedbackService.highlightedColor;
        this.rectangles = [];
        this.scrollWidth = document.documentElement.scrollWidth;
        this.scrollHeight = document.documentElement.scrollHeight;
        this.elCouldBeHighlighted = ['button', 'a', 'span', 'em', 'i', 'h1', 'h2', 'h3', 'h4',
            'h5', 'h6', 'p', 'strong', 'small', 'sub', 'sup', 'b', 'time', 'img',
            'video', 'input', 'label', 'select', 'textarea', 'article', 'summary', 'section'];
        this.isDrawingRect = false;
        this.feedback = new Feedback();
        this.feedback.description = '';
        this.vars = this.feedbackService.initialVariables;
    }
    /**
     * @return {?}
     */
    FeedbackDialogComponent.prototype.ngAfterViewInit = /**
     * @return {?}
     */
    function () {
        var _this = this;
        this.feedbackService.screenshotCanvas$.subscribe(function (canvas) {
            _this.showSpinner = false;
            _this.feedback.screenshot = canvas.toDataURL('image/png');
            _this.screenshotEle = _this.feedbackService.getImgEle(canvas);
            _this.appendScreenshot();
        });
        this.feedbackService.isDraggingToolbar$.subscribe(function (isDragging) {
            if (isDragging) {
                _this.destroyCanvasListeners();
            }
            else {
                _this.addCanvasListeners();
            }
        });
        this.dialogRef.afterClosed().subscribe(function (sendNow) {
            if (sendNow === true) {
                _this.feedbackService.setFeedback(_this.feedback);
            }
        });
        this.feedbackService.showBackDrop();
    };
    /**
     * @return {?}
     */
    FeedbackDialogComponent.prototype.expandDrawingBoard = /**
     * @return {?}
     */
    function () {
        this.showToolbar = true;
        if (!this.drawCanvas) {
            this.detector.detectChanges();
            this.initBackgroundCanvas();
            this.feedbackService.hideBackDrop();
        }
        this.addCanvasListeners();
        this.el.nativeElement.appendChild(this.drawCanvas);
        this.feedbackService.hideBackDrop();
        console.log('expand the board');
    };
    /**
     * @param {?} evt
     * @return {?}
     */
    FeedbackDialogComponent.prototype.onEscapeKeyDownHandler = /**
     * @param {?} evt
     * @return {?}
     */
    function (evt) {
        this.showToolbar = false;
        this.includeScreenshot = true;
        this.detector.detectChanges();
        this.dialogRef.close('key down esc to close');
    };
    /**
     * @param {?} manipulation
     * @return {?}
     */
    FeedbackDialogComponent.prototype.manipulate = /**
     * @param {?} manipulation
     * @return {?}
     */
    function (manipulation) {
        if (manipulation === 'done') {
            this.showToolbarTips = false;
            this.showSpinner = true;
            this.destroyCanvasListeners();
            this.showToolbar = false;
            this.detector.detectChanges();
            this.feedbackService.initScreenshotCanvas();
        }
        else {
            this.startDraw(manipulation);
        }
    };
    /**
     * @param {?} color
     * @return {?}
     */
    FeedbackDialogComponent.prototype.startDraw = /**
     * @param {?} color
     * @return {?}
     */
    function (color) {
        this.drawColor = color;
    };
    /**
     * @return {?}
     */
    FeedbackDialogComponent.prototype.isIncludeScreenshot = /**
     * @return {?}
     */
    function () {
        if (this.includeScreenshot) {
            this.detector.detectChanges();
            this.showSpinner = false;
            this.appendScreenshot();
            this.feedback.screenshot = this.screenshotEle.getAttribute('src');
        }
        else {
            delete this.feedback['screenshot'];
            this.showSpinner = true;
        }
    };
    /**
     * @return {?}
     */
    FeedbackDialogComponent.prototype.appendScreenshot = /**
     * @return {?}
     */
    function () {
        if (this.screenshotParent) {
            this.screenshotParent.nativeElement.appendChild(this.screenshotEle);
        }
    };
    /**
     * @return {?}
     */
    FeedbackDialogComponent.prototype.initBackgroundCanvas = /**
     * @return {?}
     */
    function () {
        this.drawCanvas = /** @type {?} */ (document.getElementById('draw-canvas'));
        // The canvas to draw, must use this way to initial the height and width
        this.drawCanvas.style.height = this.scrollHeight + '';
        this.drawCanvas.style.width = this.scrollWidth + '';
        this.drawCanvas.height = this.scrollHeight;
        this.drawCanvas.width = this.scrollWidth;
        this.drawContainerRect();
    };
    /**
     * @return {?}
     */
    FeedbackDialogComponent.prototype.drawContainerRect = /**
     * @return {?}
     */
    function () {
        /** @type {?} */
        var drawContext = this.drawCanvas.getContext('2d');
        /** @type {?} */
        var width = this.scrollWidth;
        /** @type {?} */
        var height = this.scrollHeight;
        drawContext.beginPath();
        drawContext.fillStyle = 'rgba(0,0,0,0.3)';
        drawContext.clearRect(0, 0, width, height);
        drawContext.fillRect(0, 0, width, height); // draw the rectangle
    };
    /**
     * @param {?} rect
     * @return {?}
     */
    FeedbackDialogComponent.prototype.drawRectangle = /**
     * @param {?} rect
     * @return {?}
     */
    function (rect) {
        var _this = this;
        /** @type {?} */
        var context = this.drawCanvas.getContext('2d');
        context.lineJoin = 'round';
        context.beginPath();
        if (rect.color === this.feedbackService.hiddenColor) {
            context.fillStyle = 'rgba(31, 31, 31, 0.75)';
            context.fillRect(rect.startX, rect.startY, rect.width, rect.height);
            context.rect(rect.startX, rect.startY, rect.width, rect.height);
        }
        else {
            context.clearRect(rect.startX, rect.startY, rect.width, rect.height);
            context.lineWidth = 5;
            context.strokeStyle = rect.color;
            context.rect(rect.startX, rect.startY, rect.width, rect.height);
            context.stroke();
            context.clearRect(rect.startX, rect.startY, rect.width, rect.height);
            this.rectangles.forEach(function (tmpRect) {
                if (tmpRect.color === _this.feedbackService.highlightedColor) {
                    context.clearRect(tmpRect.startX, tmpRect.startY, tmpRect.width, tmpRect.height);
                }
            });
        }
    };
    /**
     * @return {?}
     */
    FeedbackDialogComponent.prototype.addCanvasListeners = /**
     * @return {?}
     */
    function () {
        /** @type {?} */
        var mouseUp = fromEvent(document.documentElement, 'mouseup');
        /** @type {?} */
        var mouseMove = fromEvent(document.documentElement, 'mousemove');
        /** @type {?} */
        var mouseDown = fromEvent(document.documentElement, 'mousedown');
        /** @type {?} */
        var scroll = fromEvent(window, 'scroll');
        this.manuallyDrawRect(mouseDown, mouseMove, mouseUp);
        this.autoDrawRect(mouseMove);
        this.changeRectPosition(scroll);
    };
    /**
     * @param {?} scroll
     * @return {?}
     */
    FeedbackDialogComponent.prototype.changeRectPosition = /**
     * @param {?} scroll
     * @return {?}
     */
    function (scroll) {
        var _this = this;
        scroll.subscribe(function (event) {
            /** @type {?} */
            var currentWindowScrollX = window.scrollX;
            /** @type {?} */
            var currentWindowScrollY = window.scrollY;
            _this.rectangles.forEach(function (rect) {
                rect.startY = rect.startY - (currentWindowScrollY - rect.windowScrollY);
                rect.startX = rect.startX - (currentWindowScrollX - rect.windowScrollX);
                rect.windowScrollY = currentWindowScrollY;
                rect.windowScrollX = currentWindowScrollX;
            });
            _this.drawPersistCanvasRectangles();
        }, function (error) { return console.error(error); });
    };
    /**
     * @return {?}
     */
    FeedbackDialogComponent.prototype.destroyCanvasListeners = /**
     * @return {?}
     */
    function () {
        if (this.manuallyDrawRect$) {
            this.manuallyDrawRect$.unsubscribe();
        }
        if (this.autoDrawRect$) {
            this.autoDrawRect$.unsubscribe();
        }
    };
    /**
     * @param {?} mouseDown
     * @param {?} mouseMove
     * @param {?} mouseUp
     * @return {?}
     */
    FeedbackDialogComponent.prototype.manuallyDrawRect = /**
     * @param {?} mouseDown
     * @param {?} mouseMove
     * @param {?} mouseUp
     * @return {?}
     */
    function (mouseDown, mouseMove, mouseUp) {
        var _this = this;
        /** @type {?} */
        var mouseDrag = mouseDown.pipe(mergeMap(function (mouseDownEvent) {
            if (_this.showToolbarTips) {
                _this.showToolbarTips = false;
            }
            _this.autoDrawRect$.unsubscribe();
            _this.isDrawingRect = true;
            /** @type {?} */
            var newRectangle = new Rectangle();
            newRectangle.startX = mouseDownEvent.clientX;
            newRectangle.startY = mouseDownEvent.clientY;
            newRectangle.color = _this.drawColor;
            return mouseMove.pipe(map(function (mouseMoveEvent) {
                newRectangle.width = mouseMoveEvent.clientX - mouseDownEvent.clientX;
                newRectangle.height = mouseMoveEvent.clientY - mouseDownEvent.clientY;
                return newRectangle;
            }), finalize(function () {
                // click to draw rectangle
                if (newRectangle.width === undefined || newRectangle.height === undefined ||
                    newRectangle.width === 0 || newRectangle.height === 0) {
                    /** @type {?} */
                    var rect = _this.drawTempCanvasRectangle(mouseDownEvent);
                    if (rect) {
                        _this.rectangles.push(rect);
                    }
                }
                else {
                    // drag to draw rectangle
                    if (newRectangle.height < 0) {
                        newRectangle.startY = newRectangle.startY + newRectangle.height;
                        newRectangle.height = Math.abs(newRectangle.height);
                    }
                    if (newRectangle.width < 0) {
                        newRectangle.startX = newRectangle.startX + newRectangle.width;
                        newRectangle.width = Math.abs(newRectangle.width);
                    }
                    _this.rectangles.push(newRectangle);
                }
                _this.drawPersistCanvasRectangles();
                _this.autoDrawRect(mouseMove);
                _this.isDrawingRect = false;
            }), takeUntil(mouseUp));
        }));
        this.manuallyDrawRect$ = mouseDrag.subscribe(function (rec) {
            _this.drawPersistCanvasRectangles();
            _this.drawRectangle(rec);
        });
    };
    /**
     * @param {?} mouseMove
     * @return {?}
     */
    FeedbackDialogComponent.prototype.autoDrawRect = /**
     * @param {?} mouseMove
     * @return {?}
     */
    function (mouseMove) {
        var _this = this;
        this.autoDrawRect$ = mouseMove.subscribe({
            next: function (mouseMoveEvent) {
                _this.drawPersistCanvasRectangles();
                _this.drawTempCanvasRectangle(mouseMoveEvent);
            },
            error: function (err) { return console.error('something wrong occurred: ' + err); },
        });
    };
    /**
     * @return {?}
     */
    FeedbackDialogComponent.prototype.drawPersistCanvasRectangles = /**
     * @return {?}
     */
    function () {
        var _this = this;
        this.drawContainerRect();
        this.rectangles.forEach(function (tmpRect) {
            _this.drawRectangle(tmpRect);
        });
    };
    /**
     * @param {?} event
     * @return {?}
     */
    FeedbackDialogComponent.prototype.drawTempCanvasRectangle = /**
     * @param {?} event
     * @return {?}
     */
    function (event) {
        /** @type {?} */
        var rectangle = null;
        /** @type {?} */
        var clientX = event.clientX;
        /** @type {?} */
        var clientY = event.clientY;
        /** @type {?} */
        var els = document.elementsFromPoint(clientX, clientY);
        /** @type {?} */
        var el = els[2];
        if ((!this.isExcludeRect(els)) && el && this.elCouldBeHighlighted.indexOf(el.nodeName.toLowerCase()) > -1) {
            rectangle = new Rectangle();
            /** @type {?} */
            var rect = el.getBoundingClientRect();
            this.drawCanvas.style.cursor = 'pointer';
            Object.assign(rectangle, {
                startX: rect.left,
                startY: rect.top,
                width: rect.width,
                height: rect.height,
                color: this.drawColor
            });
            this.drawRectangle(rectangle);
        }
        else {
            this.drawCanvas.style.cursor = 'crosshair';
        }
        return rectangle;
    };
    /**
     * @param {?} index
     * @return {?}
     */
    FeedbackDialogComponent.prototype.closeRect = /**
     * @param {?} index
     * @return {?}
     */
    function (index) {
        this.rectangles.splice(index, 1);
        this.drawPersistCanvasRectangles();
    };
    /**
     * @param {?} elements
     * @return {?}
     */
    FeedbackDialogComponent.prototype.isExcludeRect = /**
     * @param {?} elements
     * @return {?}
     */
    function (elements) {
        /** @type {?} */
        var result = elements.some(function (el) {
            return el.getAttribute('exclude-rect') === 'true';
        });
        return result;
    };
    FeedbackDialogComponent.decorators = [
        { type: Component, args: [{
                    selector: 'feedback-dialog',
                    template: "<div class=\"dialog\" *ngIf=\"!showToolbar\" data-html2canvas-ignore=\"true\">\r\n  <div class=\"dialog-title\">\r\n    <div class=\"title-font\">\r\n      {{vars['title']}}\r\n    </div>\r\n  </div>\r\n  <div class=\"dialog-content\">\r\n    <div class=\"description-tips\">\r\n      <div *ngIf=\"feedback.description==''\">{{vars['placeholder']}}</div>\r\n    </div>\r\n    <textarea\r\n      autofocus\r\n      class=\"description\"\r\n      [(ngModel)]=\"feedback.description\"\r\n    ></textarea>\r\n  </div>\r\n  <div class=\"screenshot-checkbox\">\r\n    <mat-checkbox [(ngModel)]=\"includeScreenshot\" (change)=\"isIncludeScreenshot()\">{{vars['checkboxLabel']}}</mat-checkbox>\r\n  </div>\r\n\r\n  <div #screenshotParent class=\"screenshot-content\" (click)=\"expandDrawingBoard()\" *ngIf=\"includeScreenshot\">\r\n    <mat-spinner class=\"loading\" [diameter]=\"30\" ></mat-spinner>\r\n    <div></div>\r\n    <div class=\"screenshot-tips\" *ngIf=\"!showSpinner\">\r\n      <svg focusable=\"false\" aria-label=\"\" viewBox=\"0 0 24 24\">\r\n        <path\r\n          d=\"M21 17h-2.58l2.51 2.56c-.18.69-.73 1.26-1.41 1.44L17 18.5V21h-2v-6h6v2zM19 7h2v2h-2V7zm2-2h-2V3.08c1.1 0 2 .92 2 1.92zm-6-2h2v2h-2V3zm4 8h2v2h-2v-2zM9 21H7v-2h2v2zM5 9H3V7h2v2zm0-5.92V5H3c0-1 1-1.92 2-1.92zM5 17H3v-2h2v2zM9 5H7V3h2v2zm4 0h-2V3h2v2zm0 16h-2v-2h2v2zm-8-8H3v-2h2v2zm0 8.08C3.9 21.08 3 20 3 19h2v2.08z\"></path>\r\n      </svg>\r\n      <span class=\"screenshot-tips-content\">{{vars['editTip']}}</span>\r\n    </div>\r\n  </div>\r\n\r\n  <mat-dialog-actions class=\"dialog-actions\" align=\"end\">\r\n    <button mat-button (click)=\"dialogRef.close()\" class=\"action-button\">{{vars['cancelLabel']}}</button>\r\n    <button mat-button (click)=\"dialogRef.close(true)\" class=\"submit-button action-button\">{{vars['sendLabel']}}</button>\r\n  </mat-dialog-actions>\r\n</div>\r\n<div *ngIf=\"showToolbar\" data-html2canvas-ignore=\"true\">\r\n  <div class=\"toolbar-tips\" *ngIf=\"showToolbarTips\">\r\n    {{vars['drawRectTip']}}\r\n  </div>\r\n\r\n  <feedback-toolbar [drawColor]=\"drawColor\" (manipulate)=\"manipulate($event)\"></feedback-toolbar>\r\n</div>\r\n<div *ngFor=\"let rectangle of rectangles; index as index\" >\r\n    <feedback-rectangle [rectangle]=\"rectangle\" [noHover]=\"!showToolbar || isDrawingRect\" (close)=\"closeRect(index)\">\r\n    </feedback-rectangle>\r\n</div>\r\n<canvas id=\"draw-canvas\" class=\"drawCanvas\" [ngClass]=\"{'pointerCursor': !showToolbar}\"></canvas>\r\n",
                    styles: [".dialog{z-index:1000;position:relative;width:360px;background-color:#fff}.dialog-title{background-color:#607d8b;color:#fff;height:56px}.title-font{color:#fff;float:left;font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:20px;line-height:56px;font-family:Roboto,RobotoDraft,Helvetica,Arial,sans-serif;padding:0 16px;margin:0}.dialog-content{display:-webkit-flex;flex-grow:1;height:200px;position:relative}.description{border:none;box-sizing:border-box;box-shadow:none;color:#212121;flex-grow:1;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:16px;line-height:normal;font-family:Roboto,RobotoDraft,Helvetica,Arial,sans-serif;max-width:100%;outline:0;padding:18px 16px 0;resize:none;width:100%;height:inherit}.description-tips{color:#bdbdbd;display:block;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:16px;line-height:normal;font-family:Roboto,RobotoDraft,Helvetica,Arial,sans-serif;left:0;position:absolute;padding:18px 16px 0;right:0}.screenshot-checkbox{padding:0 16px;background-color:#f8f8f8;height:40px;display:flex;flex-direction:column;justify-content:center}.screenshot-content{border:none;cursor:pointer;text-align:center;display:block;position:relative;padding:0;overflow:hidden;height:192px;width:100%;background:#ededed}.screenshot-tips{align-items:center;background-color:rgba(248,248,248,.6);border-radius:4px;box-sizing:border-box;display:-webkit-flex;flex-direction:column;justify-content:center;min-height:112px;width:224px;z-index:5;position:absolute;top:50%;right:0;bottom:0;left:0;-webkit-transform:translateY(-50%);transform:translateY(-50%);margin:0 auto}.screenshot-content:hover .screenshot-tips{background-color:rgba(248,248,248,.8)}.screenshot-content:hover .screenshot-tips-content{color:#4285f4}.screenshot-content:hover svg{color:#4285f4;fill:currentColor}.screenshot-tips svg{color:#757575;fill:currentColor;height:48px;width:48px}.screenshot-tips-content{color:#757575;font-weight:400;font-size:14px;line-height:20px;font-family:Roboto,RobotoDraft,Helvetica,Arial,sans-serif;margin-top:12px}.dialog-actions{border-top:1px solid #e0e0e0}.submit-button{margin-right:8px!important;margin-left:5px!important;color:#4285f4}.action-button{font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:14px;height:35px;line-height:normal;margin:10px 0;padding:0 8px;position:relative;min-width:75px}.loading{margin:0 auto;position:absolute;top:45%;bottom:0;left:0;right:0}.mat-dialog-actions{padding:0!important}::ng-deep .feedbackDialog .mat-dialog-container{padding:0;overflow:visible;background-color:rgba(255,255,255,0);box-shadow:initial}.toolbar-tips{background-color:rgba(255,255,255,.6);border-radius:12px;color:#757575;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:34px;line-height:40px;font-family:Roboto,RobotoDraft,Helvetica,Arial,sans-serif;margin-bottom:72px;padding:22px 0;text-align:center;visibility:visible;width:656px;height:auto;-webkit-animation:0s ease-in 5s forwards cssAnimation;animation:0s ease-in 5s forwards cssAnimation}@keyframes cssAnimation{to{width:0;height:0;overflow:hidden}}@-webkit-keyframes cssAnimation{to{width:0;height:0;visibility:hidden}}.drawCanvas{position:absolute;top:0;left:0;z-index:-1;margin:0 auto;cursor:crosshair}.pointerCursor{cursor:default!important}"]
                }] }
    ];
    /** @nocollapse */
    FeedbackDialogComponent.ctorParameters = function () { return [
        { type: MatDialogRef },
        { type: FeedbackService },
        { type: ChangeDetectorRef },
        { type: ElementRef }
    ]; };
    FeedbackDialogComponent.propDecorators = {
        screenshotParent: [{ type: ViewChild, args: ['screenshotParent',] }],
        onEscapeKeyDownHandler: [{ type: HostListener, args: ['document:keydown.escape', ['$event'],] }]
    };
    return FeedbackDialogComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var FeedbackToolbarComponent = /** @class */ (function () {
    function FeedbackToolbarComponent(el, feedbackService) {
        this.el = el;
        this.feedbackService = feedbackService;
        this.manipulate = new EventEmitter();
        this.disableToolbarTips = false;
        this.isSwitch = false;
        this.isDragging = false;
        this.vars = {};
        this.vars = feedbackService.initialVariables;
    }
    /**
     * @return {?}
     */
    FeedbackToolbarComponent.prototype.ngAfterViewInit = /**
     * @return {?}
     */
    function () {
        /** @type {?} */
        var elStyle = this.el.nativeElement.style;
        elStyle.position = 'absolute';
        elStyle.left = '43%';
        elStyle.top = '60%';
        this.addDragListenerOnMoveBtn();
    };
    /**
     * @return {?}
     */
    FeedbackToolbarComponent.prototype.ngOnChanges = /**
     * @return {?}
     */
    function () {
        this.isSwitch = this.drawColor !== this.feedbackService.highlightedColor;
    };
    /**
     * @return {?}
     */
    FeedbackToolbarComponent.prototype.done = /**
     * @return {?}
     */
    function () {
        this.manipulate.emit('done');
    };
    /**
     * @return {?}
     */
    FeedbackToolbarComponent.prototype.toggleHighlight = /**
     * @return {?}
     */
    function () {
        this.isSwitch = false;
        this.manipulate.emit(this.feedbackService.highlightedColor);
    };
    /**
     * @return {?}
     */
    FeedbackToolbarComponent.prototype.toggleHide = /**
     * @return {?}
     */
    function () {
        this.isSwitch = true;
        this.manipulate.emit(this.feedbackService.hiddenColor);
    };
    /**
     * @return {?}
     */
    FeedbackToolbarComponent.prototype.addDragListenerOnMoveBtn = /**
     * @return {?}
     */
    function () {
        var _this = this;
        /** @type {?} */
        var mouseUp = fromEvent(this.toggleMoveBtn.nativeElement, 'mouseup');
        /** @type {?} */
        var mouseMove = fromEvent(document.documentElement, 'mousemove');
        /** @type {?} */
        var mouseDown = fromEvent(this.toggleMoveBtn.nativeElement, 'mousedown');
        /** @type {?} */
        var mouseDrag = mouseDown.pipe(mergeMap(function (md) {
            _this.feedbackService.setIsDraggingToolbar(true);
            /** @type {?} */
            var startX = md.offsetX;
            /** @type {?} */
            var startY = md.offsetY;
            _this.disableToolbarTips = true;
            _this.isDragging = true;
            // Calculate dif with mousemove until mouseup
            return mouseMove.pipe(map(function (mm) {
                mm.preventDefault();
                return {
                    left: mm.clientX - startX,
                    top: mm.clientY - startY
                };
            }), finalize(function () {
                _this.isDragging = false;
                _this.disableToolbarTips = false;
                _this.feedbackService.setIsDraggingToolbar(false);
            }), takeUntil(mouseUp));
        }));
        mouseDrag.subscribe(function (pos) {
            _this.el.nativeElement.style.left = pos.left + 'px';
            _this.el.nativeElement.style.top = pos.top + 'px';
        });
    };
    FeedbackToolbarComponent.decorators = [
        { type: Component, args: [{
                    selector: 'feedback-toolbar',
                    template: "<div exclude-rect=\"true\" class=\"toolbar\">\r\n  <div class=\"move-toolbar\" #toggleMove [matTooltip]=\"vars['moveToolbarTip']\" [matTooltipDisabled]=\"disableToolbarTips\">\r\n    <svg focusable=\"false\" aria-label=\"Drag\" fill=\"#BDBDBD\" height=\"56\" width=\"16\"\r\n         viewBox=\"-2 2 12 12\">\r\n      <circle cx=\"1.5\" cy=\"1.5\" r=\"1.5\"></circle>\r\n      <circle cx=\"1.5\" cy=\"7.5\" r=\"1.5\"></circle>\r\n      <circle cx=\"1.5\" cy=\"13.5\" r=\"1.5\"></circle>\r\n      <circle cx=\"6.5\" cy=\"1.5\" r=\"1.5\"></circle>\r\n      <circle cx=\"6.5\" cy=\"7.5\" r=\"1.5\"></circle>\r\n      <circle cx=\"6.5\" cy=\"13.5\" r=\"1.5\"></circle>\r\n    </svg>\r\n  </div>\r\n  <button #highlightBtn (click)=\"toggleHighlight()\" [matTooltip]=\"vars['highlightTip']\"\r\n          [matTooltipDisabled]=\"disableToolbarTips\" class=\"highlight-toggle\" [ngClass]=\"{'deepen-color': !isSwitch}\">\r\n    <span class=\"toggle\">\r\n      <svg focusable=\"false\" aria-label=\"\" viewBox=\"0 0 24 24\" height=\"36\" width=\"36\"\r\n           fill=\"#ffd740\">\r\n        <path d=\"M3 3h18v18H3z\"></path>\r\n      </svg>\r\n\r\n      <svg focusable=\"false\" aria-label=\"\" fill=\"#757575\" viewBox=\"0 0 24 24\"\r\n           height=\"36\" width=\"36\" [ngClass]=\"{'toggle-decorator': !isSwitch}\" *ngIf=\"!isSwitch\">\r\n        <path\r\n          d=\"M21 17h-2.58l2.51 2.56c-.18.69-.73 1.26-1.41 1.44L17 18.5V21h-2v-6h6v2zM19 7h2v2h-2V7zm2-2h-2V3.08c1.1 0 2 .92 2 1.92zm-6-2h2v2h-2V3zm4 8h2v2h-2v-2zM9 21H7v-2h2v2zM5 9H3V7h2v2zm0-5.92V5H3c0-1 1-1.92 2-1.92zM5 17H3v-2h2v2zM9 5H7V3h2v2zm4 0h-2V3h2v2zm0 16h-2v-2h2v2zm-8-8H3v-2h2v2zm0 8.08C3.9 21.08 3 20 3 19h2v2.08z\"></path>\r\n      </svg>\r\n    </span>\r\n  </button>\r\n  <button (click)=\"toggleHide()\" [matTooltip]=\"vars['hideTip']\" [matTooltipDisabled]=\"disableToolbarTips\"\r\n          class=\"hide-toggle\" [ngClass]=\"{'deepen-color': isSwitch}\">\r\n    <span class=\"toggle\">\r\n      <svg focusable=\"false\" aria-label=\"\" viewBox=\"0 0 24 24\" height=\"36\" width=\"36\"\r\n           fill=\"#000\">\r\n        <path d=\"M3 3h18v18H3z\"></path>\r\n      </svg>\r\n      <svg focusable=\"false\" aria-label=\"\" fill=\"#757575\" viewBox=\"0 0 24 24\"\r\n           height=\"36\" width=\"36\" [ngClass]=\"{'toggle-decorator': isSwitch}\" *ngIf=\"isSwitch\">\r\n        <path\r\n          d=\"M21 17h-2.58l2.51 2.56c-.18.69-.73 1.26-1.41 1.44L17 18.5V21h-2v-6h6v2zM19 7h2v2h-2V7zm2-2h-2V3.08c1.1 0 2 .92 2 1.92zm-6-2h2v2h-2V3zm4 8h2v2h-2v-2zM9 21H7v-2h2v2zM5 9H3V7h2v2zm0-5.92V5H3c0-1 1-1.92 2-1.92zM5 17H3v-2h2v2zM9 5H7V3h2v2zm4 0h-2V3h2v2zm0 16h-2v-2h2v2zm-8-8H3v-2h2v2zm0 8.08C3.9 21.08 3 20 3 19h2v2.08z\"></path>\r\n      </svg>\r\n    </span>\r\n  </button>\r\n  <button mat-button class=\"merge-button\" (click)=\"done()\">{{vars['editDoneLabel']}}</button>\r\n</div>\r\n",
                    styles: [".toolbar{align-items:center;background-color:#fff;border-radius:2px;box-shadow:rgba(0,0,0,.14) 0 24px 38px 3px,rgba(0,0,0,.12) 0 9px 46px 8px,rgba(0,0,0,.2) 0 11px 15px -7px;cursor:pointer;display:-webkit-inline-flex;flex-direction:row;height:56px;min-width:232px;pointer-events:auto;overflow:visible;position:absolute;margin:0 auto;width:228px;bottom:0;top:25%;left:0;right:0;z-index:999}.move-toolbar{cursor:-webkit-grab;height:56px;padding:0 12px;position:relative}.move-toolbar:active{cursor:-webkit-grabbing}.toggle{display:inline-block;position:relative;height:36px;width:36px}.toggle-decorator{left:0;position:absolute;top:0}.highlight-toggle{align-items:center;background-color:#fff;border:none;box-sizing:border-box;cursor:pointer;display:-webkit-flex;justify-content:center;outline:0;padding:10px;pointer-events:auto;position:relative;height:56px;width:56px}.deepen-color{background-color:#e0e0e0!important}.hide-toggle{align-items:center;background-color:#fff;border:none;box-sizing:border-box;cursor:pointer;display:-webkit-flex;justify-content:center;outline:0;padding:10px;pointer-events:auto;position:relative;height:56px;width:56px}.merge-button{padding:0!important;margin:0 10px!important;min-width:56px;color:#4285f4}"]
                }] }
    ];
    /** @nocollapse */
    FeedbackToolbarComponent.ctorParameters = function () { return [
        { type: ElementRef },
        { type: FeedbackService }
    ]; };
    FeedbackToolbarComponent.propDecorators = {
        drawColor: [{ type: Input }],
        manipulate: [{ type: Output }],
        toggleMoveBtn: [{ type: ViewChild, args: ['toggleMove',] }]
    };
    return FeedbackToolbarComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var FeedbackRectangleComponent = /** @class */ (function () {
    function FeedbackRectangleComponent(feedbackService) {
        this.feedbackService = feedbackService;
        this.close = new EventEmitter();
        this.showCloseTag = false;
    }
    /**
     * @return {?}
     */
    FeedbackRectangleComponent.prototype.onMouseEnter = /**
     * @return {?}
     */
    function () {
        this.showCloseTag = this.noHover === false;
    };
    /**
     * @return {?}
     */
    FeedbackRectangleComponent.prototype.onMouseLeave = /**
     * @return {?}
     */
    function () {
        this.showCloseTag = false;
    };
    /**
     * @return {?}
     */
    FeedbackRectangleComponent.prototype.onClose = /**
     * @return {?}
     */
    function () {
        this.close.emit();
    };
    FeedbackRectangleComponent.decorators = [
        { type: Component, args: [{
                    selector: 'feedback-rectangle',
                    template: "<div exclude-rect=\"true\" class=\"rect\" [ngStyle]=\"{'left.px': rectangle.startX,\r\n                              'top.px': rectangle.startY,\r\n                              'width.px': rectangle.width ,\r\n                              'height.px': rectangle.height }\"\r\n    [ngClass]=\"{'highlight': rectangle.color === feedbackService.highlightedColor,\r\n                'hide': rectangle.color !== feedbackService.highlightedColor,\r\n                'noHover': noHover}\">\r\n  <span exclude-rect=\"true\" class=\"close\" *ngIf=\"showCloseTag\" (click)=\"onClose()\">\r\n    <svg viewBox=\"0 0 1024 1024\"\r\n         width=\"16\" height=\"16\">\r\n        <path\r\n          d=\"M896 224l-96-96-288 288-288-288-96 96 288 288-288 288 96 96 288-288 288 288 96-96-288-288 288-288z\"></path>\r\n    </svg>\r\n  </span>\r\n</div>\r\n",
                    styles: [".rect{position:fixed;background:0 0;z-index:3}.highlight:not(.noHover):hover{cursor:default;background:rgba(55,131,249,.2)}.hide{background-color:#000}.hide:not(.noHover):hover{background-color:rgba(31,31,31,.75)}.rect .close{width:24px;height:24px;background:#fff;border-radius:50%;justify-content:center;align-items:center;color:#999;position:absolute;right:-12px;top:-12px;cursor:pointer;display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}"]
                }] }
    ];
    /** @nocollapse */
    FeedbackRectangleComponent.ctorParameters = function () { return [
        { type: FeedbackService }
    ]; };
    FeedbackRectangleComponent.propDecorators = {
        rectangle: [{ type: Input }],
        noHover: [{ type: Input }],
        close: [{ type: Output }],
        onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
        onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }]
    };
    return FeedbackRectangleComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var FeedbackDirective = /** @class */ (function () {
    function FeedbackDirective(dialogRef, feedbackService, overlay) {
        var _this = this;
        this.dialogRef = dialogRef;
        this.feedbackService = feedbackService;
        this.title = 'Send feedback';
        this.placeholder = 'Describe your issue or share your ideas';
        this.editTip = 'Click to highlight or hide info';
        this.checkboxLabel = 'Include screenshot';
        this.cancelLabel = 'CANCEL';
        this.sendLabel = 'SEND';
        this.moveToolbarTip = 'move toolbar';
        this.drawRectTip = 'Draw using yellow to highlight issues or black to hide sensitive info';
        this.highlightTip = 'highlight issues';
        this.hideTip = 'hide sensitive info';
        this.editDoneLabel = 'DONE';
        this.send = new EventEmitter();
        this.feedbackService.feedback$.subscribe(function (feedback) {
            _this.send.emit(feedback);
        });
        this.overlay = overlay;
    }
    /**
     * @return {?}
     */
    FeedbackDirective.prototype.onClick = /**
     * @return {?}
     */
    function () {
        this.openFeedbackDialog();
    };
    /**
     * @return {?}
     */
    FeedbackDirective.prototype.openFeedbackDialog = /**
     * @return {?}
     */
    function () {
        this.feedbackService.initScreenshotCanvas();
        /** @type {?} */
        var dialogRef = this.dialogRef.open(FeedbackDialogComponent, {
            panelClass: 'feedbackDialog',
            backdropClass: 'dialogBackDrop',
            disableClose: true,
            height: 'auto',
            width: 'auto',
            scrollStrategy: this.overlay.scrollStrategies.reposition()
        });
    };
    /**
     * @return {?}
     */
    FeedbackDirective.prototype.ngOnInit = /**
     * @return {?}
     */
    function () {
        this.feedbackService.initialVariables = {
            title: this.title,
            placeholder: this.placeholder,
            editTip: this.editTip,
            checkboxLabel: this.checkboxLabel,
            cancelLabel: this.cancelLabel,
            sendLabel: this.sendLabel,
            moveToolbarTip: this.moveToolbarTip,
            drawRectTip: this.drawRectTip,
            highlightTip: this.highlightTip,
            hideTip: this.hideTip,
            editDoneLabel: this.editDoneLabel
        };
    };
    FeedbackDirective.decorators = [
        { type: Directive, args: [{ selector: '[feedback]' },] }
    ];
    /** @nocollapse */
    FeedbackDirective.ctorParameters = function () { return [
        { type: MatDialog },
        { type: FeedbackService },
        { type: Overlay }
    ]; };
    FeedbackDirective.propDecorators = {
        title: [{ type: Input }],
        placeholder: [{ type: Input }],
        editTip: [{ type: Input }],
        checkboxLabel: [{ type: Input }],
        cancelLabel: [{ type: Input }],
        sendLabel: [{ type: Input }],
        moveToolbarTip: [{ type: Input }],
        drawRectTip: [{ type: Input }],
        highlightTip: [{ type: Input }],
        hideTip: [{ type: Input }],
        editDoneLabel: [{ type: Input }],
        send: [{ type: Output }],
        onClick: [{ type: HostListener, args: ['click',] }]
    };
    return FeedbackDirective;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var FeedbackModule = /** @class */ (function () {
    function FeedbackModule() {
    }
    FeedbackModule.decorators = [
        { type: NgModule, args: [{
                    declarations: [
                        FeedbackDialogComponent,
                        FeedbackToolbarComponent,
                        FeedbackRectangleComponent,
                        FeedbackDirective
                    ],
                    imports: [
                        MatDialogModule,
                        MatButtonModule,
                        MatIconModule,
                        MatInputModule,
                        MatTooltipModule,
                        CommonModule,
                        FormsModule,
                        MatCheckboxModule,
                        MatProgressSpinnerModule
                    ],
                    exports: [
                        FeedbackDirective
                    ],
                    entryComponents: [
                        FeedbackDialogComponent
                    ],
                    providers: [
                        FeedbackService
                    ]
                },] }
    ];
    return FeedbackModule;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */

export { FeedbackModule, FeedbackDialogComponent as ɵa, FeedbackRectangleComponent as ɵd, FeedbackToolbarComponent as ɵc, FeedbackDirective as ɵe, FeedbackService as ɵb };

//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctZmVlZGJhY2suanMubWFwIiwic291cmNlcyI6WyJuZzovL25nLWZlZWRiYWNrL2xpYi9lbnRpdHkvZmVlZGJhY2sudHMiLCJuZzovL25nLWZlZWRiYWNrL2xpYi9mZWVkYmFjay5zZXJ2aWNlLnRzIiwibmc6Ly9uZy1mZWVkYmFjay9saWIvZW50aXR5L3JlY3RhbmdsZS50cyIsIm5nOi8vbmctZmVlZGJhY2svbGliL2ZlZWRiYWNrLWRpYWxvZy9mZWVkYmFjay1kaWFsb2cuY29tcG9uZW50LnRzIiwibmc6Ly9uZy1mZWVkYmFjay9saWIvZmVlZGJhY2stdG9vbGJhci9mZWVkYmFjay10b29sYmFyLmNvbXBvbmVudC50cyIsIm5nOi8vbmctZmVlZGJhY2svbGliL2ZlZWRiYWNrLXJlY3RhbmdsZS9mZWVkYmFjay1yZWN0YW5nbGUuY29tcG9uZW50LnRzIiwibmc6Ly9uZy1mZWVkYmFjay9saWIvZmVlZGJhY2suZGlyZWN0aXZlLnRzIiwibmc6Ly9uZy1mZWVkYmFjay9saWIvZmVlZGJhY2subW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBGZWVkYmFjayB7XHJcbiAgcHVibGljIGRlc2NyaXB0aW9uOiBzdHJpbmc7XHJcbiAgcHVibGljIHNjcmVlbnNob3Q6IHN0cmluZztcclxufVxyXG4iLCJpbXBvcnQge0luamVjdGFibGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgaHRtbDJjYW52YXMgZnJvbSAnaHRtbDJjYW52YXMnO1xyXG5pbXBvcnQge1N1YmplY3QsIE9ic2VydmFibGV9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQge0ZlZWRiYWNrfSBmcm9tICcuL2VudGl0eS9mZWVkYmFjayc7IC8vIGltcG9ydCBPYnNlcnZhYmxlIHRvIHNvbHZlIGJ1aWxkIGlzc3VlXHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBGZWVkYmFja1NlcnZpY2Uge1xyXG4gIHB1YmxpYyBpbml0aWFsVmFyaWFibGVzOiBvYmplY3QgPSB7fTtcclxuICBwdWJsaWMgaGlnaGxpZ2h0ZWRDb2xvciA9ICd5ZWxsb3cnO1xyXG4gIHB1YmxpYyBoaWRkZW5Db2xvciA9ICdibGFjayc7XHJcbiAgcHJpdmF0ZSBzY3JlZW5zaG90Q2FudmFzU291cmNlID0gbmV3IFN1YmplY3Q8SFRNTENhbnZhc0VsZW1lbnQ+KCk7XHJcbiAgcHVibGljIHNjcmVlbnNob3RDYW52YXMkOiBPYnNlcnZhYmxlPEhUTUxDYW52YXNFbGVtZW50PiA9IHRoaXMuc2NyZWVuc2hvdENhbnZhc1NvdXJjZS5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgcHJpdmF0ZSBmZWVkYmFja1NvdXJjZSA9IG5ldyBTdWJqZWN0PEZlZWRiYWNrPigpO1xyXG4gIHB1YmxpYyBmZWVkYmFjayQ6IE9ic2VydmFibGU8RmVlZGJhY2s+ID0gdGhpcy5mZWVkYmFja1NvdXJjZS5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgcHJpdmF0ZSBpc0RyYWdnaW5nVG9vbGJhclNvdXJjZSA9IG5ldyBTdWJqZWN0PGJvb2xlYW4+KCk7XHJcbiAgcHVibGljIGlzRHJhZ2dpbmdUb29sYmFyJDogT2JzZXJ2YWJsZTxib29sZWFuPiA9IHRoaXMuaXNEcmFnZ2luZ1Rvb2xiYXJTb3VyY2UuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG5cclxuICBwdWJsaWMgaW5pdFNjcmVlbnNob3RDYW52YXMoKSB7XHJcbiAgICBjb25zdCB0aGF0ID0gdGhpcztcclxuICAgIGNvbnN0IGJvZHkgPSBkb2N1bWVudC5ib2R5O1xyXG4gICAgaHRtbDJjYW52YXMoYm9keSwge1xyXG4gICAgICBsb2dnaW5nOiBmYWxzZSxcclxuICAgICAgd2lkdGg6IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCxcclxuICAgICAgaGVpZ2h0OiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0LFxyXG4gICAgICB4OiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsTGVmdCxcclxuICAgICAgeTogZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCxcclxuICAgICAgYWxsb3dUYWludCA6IHRydWVcclxuICAgIH0pLnRoZW4oYm9keUNhbnZhcyA9PiB7XHJcbiAgICAgIHRoaXMuc2NyZWVuc2hvdENhbnZhc1NvdXJjZS5uZXh0KGJvZHlDYW52YXMpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc2V0Q2FudmFzKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpOiB2b2lkIHtcclxuICAgIHRoaXMuc2NyZWVuc2hvdENhbnZhc1NvdXJjZS5uZXh0KGNhbnZhcyk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc2V0RmVlZGJhY2soZmVlZGJhY2s6IEZlZWRiYWNrKTogdm9pZCB7XHJcbiAgICB0aGlzLmZlZWRiYWNrU291cmNlLm5leHQoZmVlZGJhY2spO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHNldElzRHJhZ2dpbmdUb29sYmFyKGlzRHJhZ2dpbmc6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRoaXMuaXNEcmFnZ2luZ1Rvb2xiYXJTb3VyY2UubmV4dChpc0RyYWdnaW5nKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBnZXRJbWdFbGUoY2FudmFzKTogSFRNTEVsZW1lbnQge1xyXG4gICAgY29uc3QgaW1nID0gY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyksXHJcbiAgICAgICAgICBpbWFnZUVsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xyXG4gICAgaW1hZ2VFbGUuc2V0QXR0cmlidXRlKCdzcmMnLCBpbWcpO1xyXG4gICAgT2JqZWN0LmFzc2lnbihpbWFnZUVsZS5zdHlsZSwge1xyXG4gICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcclxuICAgICAgdG9wOiAnNTAlJyxcclxuICAgICAgcmlnaHQ6ICcwJyxcclxuICAgICAgbGVmdDogJzAnLFxyXG4gICAgICBtYXJnaW46ICcwIGF1dG8nLFxyXG4gICAgICBtYXhIZWlnaHQ6ICcxMDAlJyxcclxuICAgICAgbWF4V2lkdGg6ICcxMDAlJyxcclxuICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlWSgtNTAlKSdcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGltYWdlRWxlO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGhpZGVCYWNrRHJvcCgpIHtcclxuICAgIGNvbnN0IGRpYWxvZ0JhY2tEcm9wID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnZGlhbG9nQmFja0Ryb3AnKVswXSBhcyBIVE1MRWxlbWVudDtcclxuICAgIGRpYWxvZ0JhY2tEcm9wLnN0eWxlLmJhY2tncm91bmRDb2xvciA9ICdpbml0aWFsJztcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzaG93QmFja0Ryb3AoKSB7XHJcbiAgICBjb25zdCBkaWFsb2dCYWNrRHJvcCA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ2RpYWxvZ0JhY2tEcm9wJylbMF0gYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICBpZiAoIWRpYWxvZ0JhY2tEcm9wLmdldEF0dHJpYnV0ZSgnZGF0YS1odG1sMmNhbnZhcy1pZ25vcmUnKSkge1xyXG4gICAgICBkaWFsb2dCYWNrRHJvcC5zZXRBdHRyaWJ1dGUoJ2RhdGEtaHRtbDJjYW52YXMtaWdub3JlJywgJ3RydWUnKTtcclxuICAgIH1cclxuICAgIGRpYWxvZ0JhY2tEcm9wLnN0eWxlLmJhY2tncm91bmRDb2xvciA9ICdyZ2JhKDAsIDAsIDAsIC4yODgpJztcclxuICB9XHJcbn1cclxuIiwiZXhwb3J0IGNsYXNzIFJlY3RhbmdsZSB7XHJcbiAgcHVibGljIHN0YXJ0WDogbnVtYmVyO1xyXG4gIHB1YmxpYyBzdGFydFk6IG51bWJlcjtcclxuICBwdWJsaWMgd2lkdGg6IG51bWJlcjtcclxuICBwdWJsaWMgaGVpZ2h0OiBudW1iZXI7XHJcbiAgcHVibGljIGNvbG9yOiBzdHJpbmc7XHJcbiAgcHVibGljIHdpbmRvd1Njcm9sbFk6IG51bWJlciA9IHdpbmRvdy5zY3JvbGxZO1xyXG4gIHB1YmxpYyB3aW5kb3dTY3JvbGxYOiBudW1iZXIgPSB3aW5kb3cuc2Nyb2xsWDtcclxufVxyXG4iLCJpbXBvcnQge2Zyb20sIGZyb21FdmVudCBhcyBvYnNlcnZhYmxlRnJvbUV2ZW50LCBPYnNlcnZhYmxlLCBTdWJzY3JpcHRpb259IGZyb20gJ3J4anMnO1xyXG5cclxuaW1wb3J0IHt0YWtlVW50aWwsIGZpbmFsaXplLCBtYXAsIG1lcmdlTWFwLCB0aW1lb3V0LCBza2lwV2hpbGUsIGZpbHRlciwgc2NhbiwgZmlyc3R9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHtDb21wb25lbnQsIEFmdGVyVmlld0luaXQsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiwgQ2hhbmdlRGV0ZWN0b3JSZWYsIEhvc3RMaXN0ZW5lciwgUmVuZGVyZXIyfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtNYXREaWFsb2dSZWZ9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsJztcclxuaW1wb3J0IHtGZWVkYmFja30gZnJvbSAnLi4vZW50aXR5L2ZlZWRiYWNrJztcclxuaW1wb3J0IHtGZWVkYmFja1NlcnZpY2V9IGZyb20gJy4uL2ZlZWRiYWNrLnNlcnZpY2UnO1xyXG5cclxuaW1wb3J0IHtSZWN0YW5nbGV9IGZyb20gJy4uL2VudGl0eS9yZWN0YW5nbGUnO1xyXG5pbXBvcnQge2VsZW1lbnR9IGZyb20gJ3Byb3RyYWN0b3InO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdmZWVkYmFjay1kaWFsb2cnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9mZWVkYmFjay1kaWFsb2cuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2ZlZWRiYWNrLWRpYWxvZy5jb21wb25lbnQuY3NzJ11cclxufSlcclxuXHJcbmV4cG9ydCBjbGFzcyBGZWVkYmFja0RpYWxvZ0NvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xyXG4gIHB1YmxpYyBzaG93VG9vbGJhciA9IGZhbHNlO1xyXG4gIHB1YmxpYyB2YXJzOiBvYmplY3QgPSB7fTtcclxuICBwdWJsaWMgZmVlZGJhY2sgPSBuZXcgRmVlZGJhY2soKTtcclxuICBwdWJsaWMgaW5jbHVkZVNjcmVlbnNob3Q6IGJvb2xlYW4gPSB0cnVlO1xyXG4gIHB1YmxpYyBzaG93U3Bpbm5lciA9IHRydWU7XHJcbiAgcHVibGljIHNjcmVlbnNob3RFbGU6IEhUTUxFbGVtZW50O1xyXG4gIHB1YmxpYyBkcmF3Q2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudDtcclxuICBwdWJsaWMgc2hvd1Rvb2xiYXJUaXBzOiBib29sZWFuID0gdHJ1ZTtcclxuICBAVmlld0NoaWxkKCdzY3JlZW5zaG90UGFyZW50JylcclxuICBwdWJsaWMgc2NyZWVuc2hvdFBhcmVudDogRWxlbWVudFJlZjtcclxuICBwdWJsaWMgZHJhd0NvbG9yOiBzdHJpbmcgPSB0aGlzLmZlZWRiYWNrU2VydmljZS5oaWdobGlnaHRlZENvbG9yO1xyXG4gIHB1YmxpYyByZWN0YW5nbGVzOiBSZWN0YW5nbGVbXSA9IFtdO1xyXG4gIHByaXZhdGUgc2Nyb2xsV2lkdGggPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsV2lkdGg7XHJcbiAgcHJpdmF0ZSBzY3JvbGxIZWlnaHQgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsSGVpZ2h0O1xyXG4gIHByaXZhdGUgZWxDb3VsZEJlSGlnaGxpZ2h0ZWQgPSBbJ2J1dHRvbicsICdhJywgJ3NwYW4nLCAnZW0nLCAnaScsICdoMScsICdoMicsICdoMycsICdoNCcsXHJcbiAgICAnaDUnLCAnaDYnLCAncCcsICdzdHJvbmcnLCAnc21hbGwnLCAnc3ViJywgJ3N1cCcsICdiJywgJ3RpbWUnLCAnaW1nJyxcclxuICAgICd2aWRlbycsICdpbnB1dCcsICdsYWJlbCcsICdzZWxlY3QnLCAndGV4dGFyZWEnLCAnYXJ0aWNsZScsICdzdW1tYXJ5JywgJ3NlY3Rpb24nXTtcclxuICAvLyB0aGUgZmxhZyBmaWVsZCAnaXNNYW51YWxseURyYXdSZWN0JyB0byBzb2x2ZSBjb25mbGljdCBiZXR3ZWVuIG1hbnVhbGx5IGRyYXcgYW5kIGF1dG8gZHJhd1xyXG4gIHByaXZhdGUgbWFudWFsbHlEcmF3UmVjdCQ6IFN1YnNjcmlwdGlvbjtcclxuICBwcml2YXRlIGF1dG9EcmF3UmVjdCQ6IFN1YnNjcmlwdGlvbjtcclxuICBwdWJsaWMgaXNEcmF3aW5nUmVjdDogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICBjb25zdHJ1Y3RvcihwdWJsaWMgZGlhbG9nUmVmOiBNYXREaWFsb2dSZWY8RmVlZGJhY2tEaWFsb2dDb21wb25lbnQ+LFxyXG4gICAgICAgICAgICAgIHByaXZhdGUgZmVlZGJhY2tTZXJ2aWNlOiBGZWVkYmFja1NlcnZpY2UsXHJcbiAgICAgICAgICAgICAgcHJpdmF0ZSBkZXRlY3RvcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgICAgICAgICAgICAgcHJpdmF0ZSBlbDogRWxlbWVudFJlZikge1xyXG4gICAgdGhpcy5mZWVkYmFjayA9IG5ldyBGZWVkYmFjaygpO1xyXG4gICAgdGhpcy5mZWVkYmFjay5kZXNjcmlwdGlvbiA9ICcnO1xyXG4gICAgdGhpcy52YXJzID0gdGhpcy5mZWVkYmFja1NlcnZpY2UuaW5pdGlhbFZhcmlhYmxlcztcclxuICB9XHJcblxyXG4gIHB1YmxpYyBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICB0aGlzLmZlZWRiYWNrU2VydmljZS5zY3JlZW5zaG90Q2FudmFzJC5zdWJzY3JpYmUoKGNhbnZhcykgPT4ge1xyXG4gICAgICB0aGlzLnNob3dTcGlubmVyID0gZmFsc2U7XHJcbiAgICAgIHRoaXMuZmVlZGJhY2suc2NyZWVuc2hvdCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xyXG4gICAgICB0aGlzLnNjcmVlbnNob3RFbGUgPSB0aGlzLmZlZWRiYWNrU2VydmljZS5nZXRJbWdFbGUoY2FudmFzKTtcclxuICAgICAgdGhpcy5hcHBlbmRTY3JlZW5zaG90KCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLmZlZWRiYWNrU2VydmljZS5pc0RyYWdnaW5nVG9vbGJhciQuc3Vic2NyaWJlKChpc0RyYWdnaW5nKSA9PiB7XHJcbiAgICAgIGlmIChpc0RyYWdnaW5nKSB7XHJcbiAgICAgICAgdGhpcy5kZXN0cm95Q2FudmFzTGlzdGVuZXJzKCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5hZGRDYW52YXNMaXN0ZW5lcnMoKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5kaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUoKHNlbmROb3cpID0+IHtcclxuICAgICAgaWYgKHNlbmROb3cgPT09IHRydWUpIHtcclxuICAgICAgICB0aGlzLmZlZWRiYWNrU2VydmljZS5zZXRGZWVkYmFjayh0aGlzLmZlZWRiYWNrKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICB0aGlzLmZlZWRiYWNrU2VydmljZS5zaG93QmFja0Ryb3AoKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBleHBhbmREcmF3aW5nQm9hcmQoKSB7XHJcbiAgICB0aGlzLnNob3dUb29sYmFyID0gdHJ1ZTtcclxuICAgIGlmICghdGhpcy5kcmF3Q2FudmFzKSB7XHJcbiAgICAgIHRoaXMuZGV0ZWN0b3IuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgICB0aGlzLmluaXRCYWNrZ3JvdW5kQ2FudmFzKCk7XHJcbiAgICAgIHRoaXMuZmVlZGJhY2tTZXJ2aWNlLmhpZGVCYWNrRHJvcCgpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5hZGRDYW52YXNMaXN0ZW5lcnMoKTtcclxuICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLmRyYXdDYW52YXMpO1xyXG4gICAgdGhpcy5mZWVkYmFja1NlcnZpY2UuaGlkZUJhY2tEcm9wKCk7XHJcbiAgICBjb25zb2xlLmxvZygnZXhwYW5kIHRoZSBib2FyZCcpO1xyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6a2V5ZG93bi5lc2NhcGUnLCBbJyRldmVudCddKVxyXG4gIHB1YmxpYyBvbkVzY2FwZUtleURvd25IYW5kbGVyKGV2dDogS2V5Ym9hcmRFdmVudCkge1xyXG4gICAgdGhpcy5zaG93VG9vbGJhciA9IGZhbHNlO1xyXG4gICAgdGhpcy5pbmNsdWRlU2NyZWVuc2hvdCA9IHRydWU7XHJcbiAgICB0aGlzLmRldGVjdG9yLmRldGVjdENoYW5nZXMoKTtcclxuICAgIHRoaXMuZGlhbG9nUmVmLmNsb3NlKCdrZXkgZG93biBlc2MgdG8gY2xvc2UnKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBtYW5pcHVsYXRlKG1hbmlwdWxhdGlvbjogc3RyaW5nKSB7XHJcbiAgICBpZiAobWFuaXB1bGF0aW9uID09PSAnZG9uZScpIHtcclxuICAgICAgdGhpcy5zaG93VG9vbGJhclRpcHMgPSBmYWxzZTtcclxuICAgICAgdGhpcy5zaG93U3Bpbm5lciA9IHRydWU7XHJcbiAgICAgIHRoaXMuZGVzdHJveUNhbnZhc0xpc3RlbmVycygpO1xyXG4gICAgICB0aGlzLnNob3dUb29sYmFyID0gZmFsc2U7XHJcbiAgICAgIHRoaXMuZGV0ZWN0b3IuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgICB0aGlzLmZlZWRiYWNrU2VydmljZS5pbml0U2NyZWVuc2hvdENhbnZhcygpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5zdGFydERyYXcobWFuaXB1bGF0aW9uKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGFydERyYXcoY29sb3I6IHN0cmluZykge1xyXG4gICAgdGhpcy5kcmF3Q29sb3IgPSBjb2xvcjtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBpc0luY2x1ZGVTY3JlZW5zaG90KCkge1xyXG4gICAgaWYgKHRoaXMuaW5jbHVkZVNjcmVlbnNob3QpIHtcclxuICAgICAgdGhpcy5kZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgIHRoaXMuc2hvd1NwaW5uZXIgPSBmYWxzZTtcclxuICAgICAgdGhpcy5hcHBlbmRTY3JlZW5zaG90KCk7XHJcbiAgICAgIHRoaXMuZmVlZGJhY2suc2NyZWVuc2hvdCA9IHRoaXMuc2NyZWVuc2hvdEVsZS5nZXRBdHRyaWJ1dGUoJ3NyYycpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgZGVsZXRlIHRoaXMuZmVlZGJhY2tbJ3NjcmVlbnNob3QnXTtcclxuICAgICAgdGhpcy5zaG93U3Bpbm5lciA9IHRydWU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFwcGVuZFNjcmVlbnNob3QoKSB7XHJcbiAgICBpZiAodGhpcy5zY3JlZW5zaG90UGFyZW50KSB7IHRoaXMuc2NyZWVuc2hvdFBhcmVudC5uYXRpdmVFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMuc2NyZWVuc2hvdEVsZSk7IH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgaW5pdEJhY2tncm91bmRDYW52YXMoKSB7XHJcbiAgICB0aGlzLmRyYXdDYW52YXMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZHJhdy1jYW52YXMnKSBhcyBIVE1MQ2FudmFzRWxlbWVudDtcclxuICAgIC8vIFRoZSBjYW52YXMgdG8gZHJhdywgbXVzdCB1c2UgdGhpcyB3YXkgdG8gaW5pdGlhbCB0aGUgaGVpZ2h0IGFuZCB3aWR0aFxyXG4gICAgdGhpcy5kcmF3Q2FudmFzLnN0eWxlLmhlaWdodCA9IHRoaXMuc2Nyb2xsSGVpZ2h0ICsgJyc7XHJcbiAgICB0aGlzLmRyYXdDYW52YXMuc3R5bGUud2lkdGggPSB0aGlzLnNjcm9sbFdpZHRoICsgJyc7XHJcbiAgICB0aGlzLmRyYXdDYW52YXMuaGVpZ2h0ID0gdGhpcy5zY3JvbGxIZWlnaHQ7XHJcbiAgICB0aGlzLmRyYXdDYW52YXMud2lkdGggPSB0aGlzLnNjcm9sbFdpZHRoO1xyXG4gICAgdGhpcy5kcmF3Q29udGFpbmVyUmVjdCgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBkcmF3Q29udGFpbmVyUmVjdCgpIHtcclxuICAgIGNvbnN0IGRyYXdDb250ZXh0ID0gdGhpcy5kcmF3Q2FudmFzLmdldENvbnRleHQoJzJkJyksXHJcbiAgICAgIHdpZHRoID0gdGhpcy5zY3JvbGxXaWR0aCxcclxuICAgICAgaGVpZ2h0ID0gdGhpcy5zY3JvbGxIZWlnaHQ7XHJcbiAgICBkcmF3Q29udGV4dC5iZWdpblBhdGgoKTtcclxuICAgIGRyYXdDb250ZXh0LmZpbGxTdHlsZSA9ICdyZ2JhKDAsMCwwLDAuMyknO1xyXG4gICAgZHJhd0NvbnRleHQuY2xlYXJSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xyXG4gICAgZHJhd0NvbnRleHQuZmlsbFJlY3QoMCwgMCwgd2lkdGgsIGhlaWdodCk7IC8vIGRyYXcgdGhlIHJlY3RhbmdsZVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBkcmF3UmVjdGFuZ2xlKHJlY3Q6IFJlY3RhbmdsZSkge1xyXG4gICAgY29uc3QgY29udGV4dCA9IHRoaXMuZHJhd0NhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xyXG4gICAgY29udGV4dC5saW5lSm9pbiA9ICdyb3VuZCc7XHJcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xyXG4gICAgaWYgKHJlY3QuY29sb3IgPT09IHRoaXMuZmVlZGJhY2tTZXJ2aWNlLmhpZGRlbkNvbG9yKSB7XHJcbiAgICAgIGNvbnRleHQuZmlsbFN0eWxlID0gJ3JnYmEoMzEsIDMxLCAzMSwgMC43NSknO1xyXG4gICAgICBjb250ZXh0LmZpbGxSZWN0KHJlY3Quc3RhcnRYLCByZWN0LnN0YXJ0WSwgcmVjdC53aWR0aCwgcmVjdC5oZWlnaHQpO1xyXG4gICAgICBjb250ZXh0LnJlY3QocmVjdC5zdGFydFgsIHJlY3Quc3RhcnRZLCByZWN0LndpZHRoLCByZWN0LmhlaWdodCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb250ZXh0LmNsZWFyUmVjdChyZWN0LnN0YXJ0WCwgcmVjdC5zdGFydFksIHJlY3Qud2lkdGgsIHJlY3QuaGVpZ2h0KTtcclxuICAgICAgY29udGV4dC5saW5lV2lkdGggPSA1O1xyXG4gICAgICBjb250ZXh0LnN0cm9rZVN0eWxlID0gcmVjdC5jb2xvcjtcclxuICAgICAgY29udGV4dC5yZWN0KHJlY3Quc3RhcnRYLCByZWN0LnN0YXJ0WSwgcmVjdC53aWR0aCwgcmVjdC5oZWlnaHQpO1xyXG4gICAgICBjb250ZXh0LnN0cm9rZSgpO1xyXG4gICAgICBjb250ZXh0LmNsZWFyUmVjdChyZWN0LnN0YXJ0WCwgcmVjdC5zdGFydFksIHJlY3Qud2lkdGgsIHJlY3QuaGVpZ2h0KTtcclxuICAgICAgdGhpcy5yZWN0YW5nbGVzLmZvckVhY2godG1wUmVjdCA9PiB7XHJcbiAgICAgICAgaWYgKHRtcFJlY3QuY29sb3IgPT09IHRoaXMuZmVlZGJhY2tTZXJ2aWNlLmhpZ2hsaWdodGVkQ29sb3IpIHtcclxuICAgICAgICAgIGNvbnRleHQuY2xlYXJSZWN0KHRtcFJlY3Quc3RhcnRYLCB0bXBSZWN0LnN0YXJ0WSwgdG1wUmVjdC53aWR0aCwgdG1wUmVjdC5oZWlnaHQpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFkZENhbnZhc0xpc3RlbmVycygpOiB2b2lkIHtcclxuICAgIGNvbnN0IG1vdXNlVXAgPSBvYnNlcnZhYmxlRnJvbUV2ZW50KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgJ21vdXNldXAnKSxcclxuICAgICAgICAgIG1vdXNlTW92ZSA9IG9ic2VydmFibGVGcm9tRXZlbnQoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCAnbW91c2Vtb3ZlJyksXHJcbiAgICAgICAgICBtb3VzZURvd24gPSBvYnNlcnZhYmxlRnJvbUV2ZW50KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgJ21vdXNlZG93bicpLFxyXG4gICAgICAgICAgc2Nyb2xsID0gb2JzZXJ2YWJsZUZyb21FdmVudCh3aW5kb3csICdzY3JvbGwnKTtcclxuXHJcbiAgICB0aGlzLm1hbnVhbGx5RHJhd1JlY3QobW91c2VEb3duLCBtb3VzZU1vdmUsIG1vdXNlVXApO1xyXG4gICAgdGhpcy5hdXRvRHJhd1JlY3QobW91c2VNb3ZlKTtcclxuICAgIHRoaXMuY2hhbmdlUmVjdFBvc2l0aW9uKHNjcm9sbCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNoYW5nZVJlY3RQb3NpdGlvbihzY3JvbGw6IE9ic2VydmFibGU8RXZlbnQ+KSB7XHJcbiAgICBzY3JvbGwuc3Vic2NyaWJlKFxyXG4gICAgICBldmVudCA9PiB7XHJcbiAgICAgICAgY29uc3QgY3VycmVudFdpbmRvd1Njcm9sbFggPSB3aW5kb3cuc2Nyb2xsWCxcclxuICAgICAgICAgICAgICBjdXJyZW50V2luZG93U2Nyb2xsWSA9IHdpbmRvdy5zY3JvbGxZO1xyXG4gICAgICAgIHRoaXMucmVjdGFuZ2xlcy5mb3JFYWNoKHJlY3QgPT4ge1xyXG4gICAgICAgICAgcmVjdC5zdGFydFkgPSByZWN0LnN0YXJ0WSAtIChjdXJyZW50V2luZG93U2Nyb2xsWSAtIHJlY3Qud2luZG93U2Nyb2xsWSk7XHJcbiAgICAgICAgICByZWN0LnN0YXJ0WCA9IHJlY3Quc3RhcnRYIC0gKGN1cnJlbnRXaW5kb3dTY3JvbGxYIC0gcmVjdC53aW5kb3dTY3JvbGxYKTtcclxuICAgICAgICAgIHJlY3Qud2luZG93U2Nyb2xsWSA9IGN1cnJlbnRXaW5kb3dTY3JvbGxZO1xyXG4gICAgICAgICAgcmVjdC53aW5kb3dTY3JvbGxYID0gY3VycmVudFdpbmRvd1Njcm9sbFg7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgdGhpcy5kcmF3UGVyc2lzdENhbnZhc1JlY3RhbmdsZXMoKTtcclxuICAgICAgfSxcclxuICAgICAgZXJyb3IgPT4gY29uc29sZS5lcnJvcihlcnJvcilcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGRlc3Ryb3lDYW52YXNMaXN0ZW5lcnMoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5tYW51YWxseURyYXdSZWN0JCkgeyB0aGlzLm1hbnVhbGx5RHJhd1JlY3QkLnVuc3Vic2NyaWJlKCk7IH1cclxuICAgIGlmICh0aGlzLmF1dG9EcmF3UmVjdCQpIHsgdGhpcy5hdXRvRHJhd1JlY3QkLnVuc3Vic2NyaWJlKCk7IH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgbWFudWFsbHlEcmF3UmVjdChtb3VzZURvd246IE9ic2VydmFibGU8RXZlbnQ+LCBtb3VzZU1vdmU6IE9ic2VydmFibGU8RXZlbnQ+LCBtb3VzZVVwOiBPYnNlcnZhYmxlPEV2ZW50Pik6IHZvaWQge1xyXG4gICAgY29uc3QgbW91c2VEcmFnID0gbW91c2VEb3duLnBpcGUobWVyZ2VNYXAoKG1vdXNlRG93bkV2ZW50OiBNb3VzZUV2ZW50KSA9PiB7XHJcbiAgICAgIGlmICh0aGlzLnNob3dUb29sYmFyVGlwcykgeyB0aGlzLnNob3dUb29sYmFyVGlwcyA9IGZhbHNlOyB9XHJcbiAgICAgIHRoaXMuYXV0b0RyYXdSZWN0JC51bnN1YnNjcmliZSgpO1xyXG4gICAgICB0aGlzLmlzRHJhd2luZ1JlY3QgPSB0cnVlO1xyXG5cclxuICAgICAgY29uc3QgbmV3UmVjdGFuZ2xlID0gbmV3IFJlY3RhbmdsZSgpO1xyXG4gICAgICBuZXdSZWN0YW5nbGUuc3RhcnRYID0gbW91c2VEb3duRXZlbnQuY2xpZW50WDtcclxuICAgICAgbmV3UmVjdGFuZ2xlLnN0YXJ0WSA9IG1vdXNlRG93bkV2ZW50LmNsaWVudFk7XHJcbiAgICAgIG5ld1JlY3RhbmdsZS5jb2xvciA9IHRoaXMuZHJhd0NvbG9yO1xyXG5cclxuICAgICAgcmV0dXJuIG1vdXNlTW92ZS5waXBlKFxyXG4gICAgICAgIG1hcCgobW91c2VNb3ZlRXZlbnQ6IE1vdXNlRXZlbnQpID0+IHtcclxuICAgICAgICAgIG5ld1JlY3RhbmdsZS53aWR0aCA9IG1vdXNlTW92ZUV2ZW50LmNsaWVudFggLSBtb3VzZURvd25FdmVudC5jbGllbnRYO1xyXG4gICAgICAgICAgbmV3UmVjdGFuZ2xlLmhlaWdodCA9IG1vdXNlTW92ZUV2ZW50LmNsaWVudFkgLSBtb3VzZURvd25FdmVudC5jbGllbnRZO1xyXG4gICAgICAgICAgcmV0dXJuIG5ld1JlY3RhbmdsZTtcclxuICAgICAgICB9KSxcclxuICAgICAgICBmaW5hbGl6ZSgoKSA9PiB7XHJcbiAgICAgICAgICAvLyBjbGljayB0byBkcmF3IHJlY3RhbmdsZVxyXG4gICAgICAgICAgaWYgKG5ld1JlY3RhbmdsZS53aWR0aCA9PT0gdW5kZWZpbmVkIHx8IG5ld1JlY3RhbmdsZS5oZWlnaHQgPT09IHVuZGVmaW5lZCB8fFxyXG4gICAgICAgICAgICBuZXdSZWN0YW5nbGUud2lkdGggPT09IDAgfHwgbmV3UmVjdGFuZ2xlLmhlaWdodCA9PT0gMCkge1xyXG4gICAgICAgICAgICBjb25zdCByZWN0ID0gdGhpcy5kcmF3VGVtcENhbnZhc1JlY3RhbmdsZShtb3VzZURvd25FdmVudCk7XHJcbiAgICAgICAgICAgIGlmIChyZWN0KSB7IHRoaXMucmVjdGFuZ2xlcy5wdXNoKHJlY3QpOyB9XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLy8gZHJhZyB0byBkcmF3IHJlY3RhbmdsZVxyXG4gICAgICAgICAgICBpZiAobmV3UmVjdGFuZ2xlLmhlaWdodCA8IDApIHtcclxuICAgICAgICAgICAgICBuZXdSZWN0YW5nbGUuc3RhcnRZID0gbmV3UmVjdGFuZ2xlLnN0YXJ0WSArIG5ld1JlY3RhbmdsZS5oZWlnaHQ7XHJcbiAgICAgICAgICAgICAgbmV3UmVjdGFuZ2xlLmhlaWdodCA9IE1hdGguYWJzKG5ld1JlY3RhbmdsZS5oZWlnaHQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChuZXdSZWN0YW5nbGUud2lkdGggPCAwKSB7XHJcbiAgICAgICAgICAgICAgbmV3UmVjdGFuZ2xlLnN0YXJ0WCA9IG5ld1JlY3RhbmdsZS5zdGFydFggKyBuZXdSZWN0YW5nbGUud2lkdGg7XHJcbiAgICAgICAgICAgICAgbmV3UmVjdGFuZ2xlLndpZHRoID0gTWF0aC5hYnMobmV3UmVjdGFuZ2xlLndpZHRoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0aGlzLnJlY3RhbmdsZXMucHVzaChuZXdSZWN0YW5nbGUpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdGhpcy5kcmF3UGVyc2lzdENhbnZhc1JlY3RhbmdsZXMoKTtcclxuICAgICAgICAgIHRoaXMuYXV0b0RyYXdSZWN0KG1vdXNlTW92ZSk7XHJcbiAgICAgICAgICB0aGlzLmlzRHJhd2luZ1JlY3QgPSBmYWxzZTtcclxuICAgICAgICB9KSxcclxuICAgICAgICB0YWtlVW50aWwobW91c2VVcCkpO1xyXG4gICAgfSkpO1xyXG5cclxuICAgIHRoaXMubWFudWFsbHlEcmF3UmVjdCQgPSBtb3VzZURyYWcuc3Vic2NyaWJlKFxyXG4gICAgICAocmVjKSA9PiB7XHJcbiAgICAgICAgdGhpcy5kcmF3UGVyc2lzdENhbnZhc1JlY3RhbmdsZXMoKTtcclxuICAgICAgICB0aGlzLmRyYXdSZWN0YW5nbGUocmVjKTtcclxuICAgICAgfVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXV0b0RyYXdSZWN0KG1vdXNlTW92ZTogT2JzZXJ2YWJsZTxFdmVudD4pOiB2b2lkIHtcclxuICAgIHRoaXMuYXV0b0RyYXdSZWN0JCA9IG1vdXNlTW92ZS5zdWJzY3JpYmUoe1xyXG4gICAgICBuZXh0OiAobW91c2VNb3ZlRXZlbnQ6IE1vdXNlRXZlbnQpID0+IHtcclxuICAgICAgICB0aGlzLmRyYXdQZXJzaXN0Q2FudmFzUmVjdGFuZ2xlcygpO1xyXG4gICAgICAgIHRoaXMuZHJhd1RlbXBDYW52YXNSZWN0YW5nbGUobW91c2VNb3ZlRXZlbnQpO1xyXG4gICAgICB9LFxyXG4gICAgICBlcnJvcjogZXJyID0+IGNvbnNvbGUuZXJyb3IoJ3NvbWV0aGluZyB3cm9uZyBvY2N1cnJlZDogJyArIGVyciksXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZHJhd1BlcnNpc3RDYW52YXNSZWN0YW5nbGVzKCkge1xyXG4gICAgdGhpcy5kcmF3Q29udGFpbmVyUmVjdCgpO1xyXG4gICAgdGhpcy5yZWN0YW5nbGVzLmZvckVhY2godG1wUmVjdCA9PiB7XHJcbiAgICAgIHRoaXMuZHJhd1JlY3RhbmdsZSh0bXBSZWN0KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBkcmF3VGVtcENhbnZhc1JlY3RhbmdsZShldmVudDogTW91c2VFdmVudCkge1xyXG4gICAgbGV0IHJlY3RhbmdsZTogUmVjdGFuZ2xlID0gbnVsbDtcclxuICAgIGNvbnN0IGNsaWVudFggPSBldmVudC5jbGllbnRYLFxyXG4gICAgICAgICAgY2xpZW50WSA9IGV2ZW50LmNsaWVudFksXHJcbiAgICAgICAgICBlbHMgPSBkb2N1bWVudC5lbGVtZW50c0Zyb21Qb2ludChjbGllbnRYLCBjbGllbnRZKSxcclxuICAgICAgICAgIGVsID0gZWxzWzJdO1xyXG4gICAgaWYgKCghdGhpcy5pc0V4Y2x1ZGVSZWN0KGVscykpICYmIGVsICYmIHRoaXMuZWxDb3VsZEJlSGlnaGxpZ2h0ZWQuaW5kZXhPZihlbC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSA+IC0xKSB7XHJcbiAgICAgIHJlY3RhbmdsZSA9IG5ldyBSZWN0YW5nbGUoKTtcclxuICAgICAgY29uc3QgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgICB0aGlzLmRyYXdDYW52YXMuc3R5bGUuY3Vyc29yID0gJ3BvaW50ZXInO1xyXG5cclxuICAgICAgT2JqZWN0LmFzc2lnbihyZWN0YW5nbGUsIHtcclxuICAgICAgICBzdGFydFg6IHJlY3QubGVmdCxcclxuICAgICAgICBzdGFydFk6IHJlY3QudG9wLFxyXG4gICAgICAgIHdpZHRoOiByZWN0LndpZHRoLFxyXG4gICAgICAgIGhlaWdodDogcmVjdC5oZWlnaHQsXHJcbiAgICAgICAgY29sb3I6IHRoaXMuZHJhd0NvbG9yXHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLmRyYXdSZWN0YW5nbGUocmVjdGFuZ2xlKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuZHJhd0NhbnZhcy5zdHlsZS5jdXJzb3IgPSAnY3Jvc3NoYWlyJztcclxuICAgIH1cclxuICAgIHJldHVybiByZWN0YW5nbGU7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY2xvc2VSZWN0KGluZGV4OiBudW1iZXIpIHtcclxuICAgIHRoaXMucmVjdGFuZ2xlcy5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgdGhpcy5kcmF3UGVyc2lzdENhbnZhc1JlY3RhbmdsZXMoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaXNFeGNsdWRlUmVjdChlbGVtZW50czogRWxlbWVudFtdKTogYm9vbGVhbiB7XHJcbiAgICBjb25zdCByZXN1bHQgPSBlbGVtZW50cy5zb21lKCBlbCA9PiB7XHJcbiAgICAgIHJldHVybiBlbC5nZXRBdHRyaWJ1dGUoJ2V4Y2x1ZGUtcmVjdCcpID09PSAndHJ1ZSc7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7ZnJvbUV2ZW50IGFzIG9ic2VydmFibGVGcm9tRXZlbnR9IGZyb20gJ3J4anMnO1xyXG5cclxuaW1wb3J0IHt0YWtlVW50aWwsIGZpbmFsaXplLCBtYXAsIG1lcmdlTWFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7Q29tcG9uZW50LCBFbGVtZW50UmVmLCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIEFmdGVyVmlld0luaXQsIFZpZXdDaGlsZCwgT25DaGFuZ2VzfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtGZWVkYmFja1NlcnZpY2V9IGZyb20gJy4uL2ZlZWRiYWNrLnNlcnZpY2UnO1xyXG5cclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnZmVlZGJhY2stdG9vbGJhcicsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2ZlZWRiYWNrLXRvb2xiYXIuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2ZlZWRiYWNrLXRvb2xiYXIuY29tcG9uZW50LmNzcyddXHJcbn0pXHJcblxyXG5leHBvcnQgY2xhc3MgRmVlZGJhY2tUb29sYmFyQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzIHtcclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBkcmF3Q29sb3I6IHN0cmluZztcclxuICBAT3V0cHV0KClcclxuICBwdWJsaWMgbWFuaXB1bGF0ZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG4gIHB1YmxpYyBkaXNhYmxlVG9vbGJhclRpcHMgPSBmYWxzZTtcclxuICBAVmlld0NoaWxkKCd0b2dnbGVNb3ZlJylcclxuICBwcml2YXRlIHRvZ2dsZU1vdmVCdG46IEVsZW1lbnRSZWY7XHJcbiAgcHVibGljIGlzU3dpdGNoID0gZmFsc2U7XHJcbiAgcHVibGljIGlzRHJhZ2dpbmcgPSBmYWxzZTtcclxuICBwdWJsaWMgdmFyczogb2JqZWN0ID0ge307XHJcblxyXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBlbDogRWxlbWVudFJlZiwgcHJpdmF0ZSBmZWVkYmFja1NlcnZpY2U6IEZlZWRiYWNrU2VydmljZSkge1xyXG4gICAgdGhpcy52YXJzID0gZmVlZGJhY2tTZXJ2aWNlLmluaXRpYWxWYXJpYWJsZXM7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgY29uc3QgZWxTdHlsZSA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC5zdHlsZTtcclxuICAgIGVsU3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xyXG4gICAgZWxTdHlsZS5sZWZ0ID0gJzQzJSc7XHJcbiAgICBlbFN0eWxlLnRvcCA9ICc2MCUnO1xyXG4gICAgdGhpcy5hZGREcmFnTGlzdGVuZXJPbk1vdmVCdG4oKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBuZ09uQ2hhbmdlcygpIHtcclxuICAgIHRoaXMuaXNTd2l0Y2ggPSB0aGlzLmRyYXdDb2xvciAhPT0gdGhpcy5mZWVkYmFja1NlcnZpY2UuaGlnaGxpZ2h0ZWRDb2xvcjtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBkb25lKCkge1xyXG4gICAgdGhpcy5tYW5pcHVsYXRlLmVtaXQoJ2RvbmUnKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyB0b2dnbGVIaWdobGlnaHQoKSB7XHJcbiAgICB0aGlzLmlzU3dpdGNoID0gZmFsc2U7XHJcbiAgICB0aGlzLm1hbmlwdWxhdGUuZW1pdCh0aGlzLmZlZWRiYWNrU2VydmljZS5oaWdobGlnaHRlZENvbG9yKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyB0b2dnbGVIaWRlKCkge1xyXG4gICAgdGhpcy5pc1N3aXRjaCA9IHRydWU7XHJcbiAgICB0aGlzLm1hbmlwdWxhdGUuZW1pdCh0aGlzLmZlZWRiYWNrU2VydmljZS5oaWRkZW5Db2xvcik7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYWRkRHJhZ0xpc3RlbmVyT25Nb3ZlQnRuKCkge1xyXG4gICAgY29uc3QgbW91c2VVcCA9IG9ic2VydmFibGVGcm9tRXZlbnQodGhpcy50b2dnbGVNb3ZlQnRuLm5hdGl2ZUVsZW1lbnQsICdtb3VzZXVwJyk7XHJcbiAgICBjb25zdCBtb3VzZU1vdmUgPSBvYnNlcnZhYmxlRnJvbUV2ZW50KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgJ21vdXNlbW92ZScpO1xyXG4gICAgY29uc3QgbW91c2VEb3duID0gb2JzZXJ2YWJsZUZyb21FdmVudCh0aGlzLnRvZ2dsZU1vdmVCdG4ubmF0aXZlRWxlbWVudCwgJ21vdXNlZG93bicpO1xyXG4gICAgY29uc3QgbW91c2VEcmFnID0gbW91c2VEb3duLnBpcGUobWVyZ2VNYXAoKG1kOiBNb3VzZUV2ZW50KSA9PiB7XHJcbiAgICAgIHRoaXMuZmVlZGJhY2tTZXJ2aWNlLnNldElzRHJhZ2dpbmdUb29sYmFyKHRydWUpO1xyXG4gICAgICBjb25zdCBzdGFydFggPSBtZC5vZmZzZXRYO1xyXG4gICAgICBjb25zdCBzdGFydFkgPSBtZC5vZmZzZXRZO1xyXG4gICAgICB0aGlzLmRpc2FibGVUb29sYmFyVGlwcyA9IHRydWU7XHJcbiAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IHRydWU7XHJcbiAgICAgIC8vIENhbGN1bGF0ZSBkaWYgd2l0aCBtb3VzZW1vdmUgdW50aWwgbW91c2V1cFxyXG4gICAgICByZXR1cm4gbW91c2VNb3ZlLnBpcGUoXHJcbiAgICAgICAgbWFwKChtbTogTW91c2VFdmVudCkgPT4ge1xyXG4gICAgICAgICAgbW0ucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIGxlZnQ6IG1tLmNsaWVudFggLSBzdGFydFgsXHJcbiAgICAgICAgICAgIHRvcDogbW0uY2xpZW50WSAtIHN0YXJ0WVxyXG4gICAgICAgICAgfTtcclxuICAgICAgICB9KSxcclxuICAgICAgICBmaW5hbGl6ZSgoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcclxuICAgICAgICAgIHRoaXMuZGlzYWJsZVRvb2xiYXJUaXBzID0gZmFsc2U7XHJcbiAgICAgICAgICB0aGlzLmZlZWRiYWNrU2VydmljZS5zZXRJc0RyYWdnaW5nVG9vbGJhcihmYWxzZSk7XHJcbiAgICAgICAgfSksXHJcbiAgICAgICAgdGFrZVVudGlsKG1vdXNlVXApKTtcclxuICAgIH0pKTtcclxuICAgIG1vdXNlRHJhZy5zdWJzY3JpYmUoXHJcbiAgICAgIChwb3MpID0+IHtcclxuICAgICAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuc3R5bGUubGVmdCA9IHBvcy5sZWZ0ICsgJ3B4JztcclxuICAgICAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuc3R5bGUudG9wID0gcG9zLnRvcCArICdweCc7XHJcbiAgICAgIH0pO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQge0NvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPdXRwdXR9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1JlY3RhbmdsZX0gZnJvbSAnLi4vZW50aXR5L3JlY3RhbmdsZSc7XHJcbmltcG9ydCB7RmVlZGJhY2tTZXJ2aWNlfSBmcm9tICcuLi9mZWVkYmFjay5zZXJ2aWNlJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnZmVlZGJhY2stcmVjdGFuZ2xlJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vZmVlZGJhY2stcmVjdGFuZ2xlLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9mZWVkYmFjay1yZWN0YW5nbGUuY29tcG9uZW50LmNzcyddXHJcbn0pXHJcblxyXG5leHBvcnQgY2xhc3MgRmVlZGJhY2tSZWN0YW5nbGVDb21wb25lbnQge1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIHJlY3RhbmdsZTogUmVjdGFuZ2xlO1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIG5vSG92ZXI6IGJvb2xlYW47XHJcbiAgQE91dHB1dCgpXHJcbiAgcHVibGljIGNsb3NlID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xyXG4gIHB1YmxpYyBzaG93Q2xvc2VUYWc6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgY29uc3RydWN0b3IocHVibGljIGZlZWRiYWNrU2VydmljZTogRmVlZGJhY2tTZXJ2aWNlKSB7XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCdtb3VzZWVudGVyJylcclxuICBwdWJsaWMgb25Nb3VzZUVudGVyKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zaG93Q2xvc2VUYWcgPSB0aGlzLm5vSG92ZXIgPT09IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignbW91c2VsZWF2ZScpXHJcbiAgcHVibGljIG9uTW91c2VMZWF2ZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuc2hvd0Nsb3NlVGFnID0gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25DbG9zZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2xvc2UuZW1pdCgpO1xyXG4gIH1cclxuXHJcblxyXG59XHJcbiIsImltcG9ydCB7RGlyZWN0aXZlLCBIb3N0TGlzdGVuZXIsIEV2ZW50RW1pdHRlciwgT3V0cHV0LCBJbnB1dCwgT25Jbml0fSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtNYXREaWFsb2d9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsJztcclxuaW1wb3J0IHtGZWVkYmFja0RpYWxvZ0NvbXBvbmVudH0gZnJvbSAnLi9mZWVkYmFjay1kaWFsb2cvZmVlZGJhY2stZGlhbG9nLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7RmVlZGJhY2tTZXJ2aWNlfSBmcm9tICcuL2ZlZWRiYWNrLnNlcnZpY2UnO1xyXG5pbXBvcnQge092ZXJsYXl9IGZyb20gJ0Bhbmd1bGFyL2Nkay9vdmVybGF5JztcclxuXHJcbkBEaXJlY3RpdmUoe3NlbGVjdG9yOiAnW2ZlZWRiYWNrXSd9KVxyXG5leHBvcnQgY2xhc3MgRmVlZGJhY2tEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQge1xyXG4gIHByaXZhdGUgb3ZlcmxheTogT3ZlcmxheTtcclxuICBASW5wdXQoKSB0aXRsZTogc3RyaW5nID0gJ1NlbmQgZmVlZGJhY2snO1xyXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyOiBzdHJpbmcgPSAnRGVzY3JpYmUgeW91ciBpc3N1ZSBvciBzaGFyZSB5b3VyIGlkZWFzJztcclxuICBASW5wdXQoKSBlZGl0VGlwID0gJ0NsaWNrIHRvIGhpZ2hsaWdodCBvciBoaWRlIGluZm8nO1xyXG4gIEBJbnB1dCgpIGNoZWNrYm94TGFiZWwgPSAnSW5jbHVkZSBzY3JlZW5zaG90JztcclxuICBASW5wdXQoKSBjYW5jZWxMYWJlbCA9ICdDQU5DRUwnO1xyXG4gIEBJbnB1dCgpIHNlbmRMYWJlbCA9ICdTRU5EJztcclxuICBASW5wdXQoKSBtb3ZlVG9vbGJhclRpcCA9ICdtb3ZlIHRvb2xiYXInO1xyXG4gIEBJbnB1dCgpIGRyYXdSZWN0VGlwID0gJ0RyYXcgdXNpbmcgeWVsbG93IHRvIGhpZ2hsaWdodCBpc3N1ZXMgb3IgYmxhY2sgdG8gaGlkZSBzZW5zaXRpdmUgaW5mbyc7XHJcbiAgQElucHV0KCkgaGlnaGxpZ2h0VGlwID0gJ2hpZ2hsaWdodCBpc3N1ZXMnO1xyXG4gIEBJbnB1dCgpIGhpZGVUaXAgPSAnaGlkZSBzZW5zaXRpdmUgaW5mbyc7XHJcbiAgQElucHV0KCkgZWRpdERvbmVMYWJlbCA9ICdET05FJztcclxuICBAT3V0cHV0KCkgcHVibGljIHNlbmQgPSBuZXcgRXZlbnRFbWl0dGVyPG9iamVjdD4oKTtcclxuXHJcbiAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgZGlhbG9nUmVmOiBNYXREaWFsb2csIHByaXZhdGUgZmVlZGJhY2tTZXJ2aWNlOiBGZWVkYmFja1NlcnZpY2UsIG92ZXJsYXk6IE92ZXJsYXkpIHtcclxuICAgIHRoaXMuZmVlZGJhY2tTZXJ2aWNlLmZlZWRiYWNrJC5zdWJzY3JpYmUoXHJcbiAgICAgIChmZWVkYmFjaykgPT4ge1xyXG4gICAgICAgIHRoaXMuc2VuZC5lbWl0KGZlZWRiYWNrKTtcclxuICAgICAgfVxyXG4gICAgKTtcclxuICAgIHRoaXMub3ZlcmxheSA9IG92ZXJsYXk7XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCdjbGljaycpXHJcbiAgcHVibGljIG9uQ2xpY2soKSB7XHJcbiAgICB0aGlzLm9wZW5GZWVkYmFja0RpYWxvZygpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG9wZW5GZWVkYmFja0RpYWxvZygpIHtcclxuICAgIHRoaXMuZmVlZGJhY2tTZXJ2aWNlLmluaXRTY3JlZW5zaG90Q2FudmFzKCk7XHJcbiAgICBjb25zdCBkaWFsb2dSZWYgPSB0aGlzLmRpYWxvZ1JlZi5vcGVuKEZlZWRiYWNrRGlhbG9nQ29tcG9uZW50LCB7XHJcbiAgICAgIHBhbmVsQ2xhc3M6ICdmZWVkYmFja0RpYWxvZycsXHJcbiAgICAgIGJhY2tkcm9wQ2xhc3M6ICdkaWFsb2dCYWNrRHJvcCcsXHJcbiAgICAgIGRpc2FibGVDbG9zZTogdHJ1ZSxcclxuICAgICAgaGVpZ2h0OiAnYXV0bycsXHJcbiAgICAgIHdpZHRoOiAnYXV0bycsXHJcbiAgICAgIHNjcm9sbFN0cmF0ZWd5OiB0aGlzLm92ZXJsYXkuc2Nyb2xsU3RyYXRlZ2llcy5yZXBvc2l0aW9uKClcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLmZlZWRiYWNrU2VydmljZS5pbml0aWFsVmFyaWFibGVzID0ge1xyXG4gICAgICB0aXRsZTogdGhpcy50aXRsZSxcclxuICAgICAgcGxhY2Vob2xkZXI6IHRoaXMucGxhY2Vob2xkZXIsXHJcbiAgICAgIGVkaXRUaXA6IHRoaXMuZWRpdFRpcCxcclxuICAgICAgY2hlY2tib3hMYWJlbDogdGhpcy5jaGVja2JveExhYmVsLFxyXG4gICAgICBjYW5jZWxMYWJlbDogdGhpcy5jYW5jZWxMYWJlbCxcclxuICAgICAgc2VuZExhYmVsOiB0aGlzLnNlbmRMYWJlbCxcclxuICAgICAgbW92ZVRvb2xiYXJUaXA6IHRoaXMubW92ZVRvb2xiYXJUaXAsXHJcbiAgICAgIGRyYXdSZWN0VGlwOiB0aGlzLmRyYXdSZWN0VGlwLFxyXG4gICAgICBoaWdobGlnaHRUaXA6IHRoaXMuaGlnaGxpZ2h0VGlwLFxyXG4gICAgICBoaWRlVGlwOiB0aGlzLmhpZGVUaXAsXHJcbiAgICAgIGVkaXREb25lTGFiZWw6IHRoaXMuZWRpdERvbmVMYWJlbFxyXG4gICAgfTtcclxuICB9XHJcblxyXG59XHJcbiIsImltcG9ydCB7TmdNb2R1bGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge0NvbW1vbk1vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHtGb3Jtc01vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQge0ZlZWRiYWNrRGlhbG9nQ29tcG9uZW50fSBmcm9tICcuL2ZlZWRiYWNrLWRpYWxvZy9mZWVkYmFjay1kaWFsb2cuY29tcG9uZW50JztcclxuaW1wb3J0IHtGZWVkYmFja1Rvb2xiYXJDb21wb25lbnR9IGZyb20gJy4vZmVlZGJhY2stdG9vbGJhci9mZWVkYmFjay10b29sYmFyLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7RmVlZGJhY2tSZWN0YW5nbGVDb21wb25lbnR9IGZyb20gJy4vZmVlZGJhY2stcmVjdGFuZ2xlL2ZlZWRiYWNrLXJlY3RhbmdsZS5jb21wb25lbnQnO1xyXG5pbXBvcnQge1xyXG4gIE1hdERpYWxvZ01vZHVsZSxcclxuICBNYXRCdXR0b25Nb2R1bGUsXHJcbiAgTWF0SWNvbk1vZHVsZSxcclxuICBNYXRJbnB1dE1vZHVsZSxcclxuICBNYXRUb29sdGlwTW9kdWxlLFxyXG4gIE1hdENoZWNrYm94TW9kdWxlLFxyXG4gIE1hdFByb2dyZXNzU3Bpbm5lck1vZHVsZVxyXG59IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsJztcclxuaW1wb3J0IHtGZWVkYmFja1NlcnZpY2V9IGZyb20gJy4vZmVlZGJhY2suc2VydmljZSc7XHJcbmltcG9ydCB7RmVlZGJhY2tEaXJlY3RpdmV9IGZyb20gJy4vZmVlZGJhY2suZGlyZWN0aXZlJztcclxuXHJcbkBOZ01vZHVsZSh7XHJcbiAgZGVjbGFyYXRpb25zOiBbXHJcbiAgICBGZWVkYmFja0RpYWxvZ0NvbXBvbmVudCxcclxuICAgIEZlZWRiYWNrVG9vbGJhckNvbXBvbmVudCxcclxuICAgIEZlZWRiYWNrUmVjdGFuZ2xlQ29tcG9uZW50LFxyXG4gICAgRmVlZGJhY2tEaXJlY3RpdmVcclxuICBdLFxyXG4gIGltcG9ydHM6IFtcclxuICAgIE1hdERpYWxvZ01vZHVsZSxcclxuICAgIE1hdEJ1dHRvbk1vZHVsZSxcclxuICAgIE1hdEljb25Nb2R1bGUsXHJcbiAgICBNYXRJbnB1dE1vZHVsZSxcclxuICAgIE1hdFRvb2x0aXBNb2R1bGUsXHJcbiAgICBDb21tb25Nb2R1bGUsXHJcbiAgICBGb3Jtc01vZHVsZSxcclxuICAgIE1hdENoZWNrYm94TW9kdWxlLFxyXG4gICAgTWF0UHJvZ3Jlc3NTcGlubmVyTW9kdWxlXHJcbiAgXSxcclxuICBleHBvcnRzOiBbXHJcbiAgICBGZWVkYmFja0RpcmVjdGl2ZVxyXG4gIF0sXHJcbiAgZW50cnlDb21wb25lbnRzOiBbXHJcbiAgICBGZWVkYmFja0RpYWxvZ0NvbXBvbmVudFxyXG4gIF0sXHJcbiAgcHJvdmlkZXJzOiBbXHJcbiAgICBGZWVkYmFja1NlcnZpY2VcclxuICBdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBGZWVkYmFja01vZHVsZSB7XHJcbn1cclxuIl0sIm5hbWVzIjpbIm9ic2VydmFibGVGcm9tRXZlbnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFBQSxJQUFBOzs7bUJBQUE7SUFHQyxDQUFBOzs7Ozs7QUNIRDs7Z0NBT29DLEVBQUU7Z0NBQ1YsUUFBUTsyQkFDYixPQUFPO3NDQUNLLElBQUksT0FBTyxFQUFxQjtpQ0FDUCxJQUFJLENBQUMsc0JBQXNCLENBQUMsWUFBWSxFQUFFOzhCQUUzRSxJQUFJLE9BQU8sRUFBWTt5QkFDUCxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksRUFBRTt1Q0FFekMsSUFBSSxPQUFPLEVBQVc7a0NBQ1AsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFlBQVksRUFBRTs7Ozs7SUFHckYsOENBQW9COzs7Ozs7UUFFekIsSUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQztRQUMzQixXQUFXLENBQUMsSUFBSSxFQUFFO1lBQ2hCLE9BQU8sRUFBRSxLQUFLO1lBQ2QsS0FBSyxFQUFFLFFBQVEsQ0FBQyxlQUFlLENBQUMsV0FBVztZQUMzQyxNQUFNLEVBQUUsUUFBUSxDQUFDLGVBQWUsQ0FBQyxZQUFZO1lBQzdDLENBQUMsRUFBRSxRQUFRLENBQUMsZUFBZSxDQUFDLFVBQVU7WUFDdEMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxlQUFlLENBQUMsU0FBUztZQUNyQyxVQUFVLEVBQUcsSUFBSTtTQUNsQixDQUFDLENBQUMsSUFBSSxDQUFDLFVBQUEsVUFBVTtZQUNoQixLQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1NBQzlDLENBQUMsQ0FBQzs7Ozs7O0lBR0UsbUNBQVM7Ozs7Y0FBQyxNQUF5QjtRQUN4QyxJQUFJ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