UNPKG

@scicom-esolutions/ng-image-viewer

Version:

[![npm (scoped)](https://img.shields.io/npm/v/@bamblehorse/tiny.svg)](https://www.npmjs.com/package/@haseeamarathunga/ng-image-viewer) [![npm bundle size (minified)](https://img.shields.io/bundlephobia/min/@bamblehorse/tiny.svg)](https://www.npmjs.com/pac

382 lines (377 loc) 31.8 kB
/** * @fileoverview added by tsickle * Generated from: lib/ng-image-viewer.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, EventEmitter, HostListener, Inject, Input, Optional, Output } from '@angular/core'; import { CustomImageEvent } from './model/custom-image-event-model'; /** @type {?} */ const DEFAULT_CONFIG = { btnClass: 'default', zoomFactor: 0.1, containerBackgroundColor: '#ccc', wheelZoom: true, allowFullscreen: true, allowKeyboardNavigation: true, btnShow: { zoomIn: true, zoomOut: true, rotateClockwise: true, rotateCounterClockwise: true, }, btnIcons: { zoomIn: 'fa fa-plus', zoomOut: 'fa fa-minus', rotateClockwise: 'fa fa-repeat', rotateCounterClockwise: 'fa fa-undo', fullscreen: 'fa fa-refresh', } }; export class NgImageViewerComponent { /** * @param {?} moduleConfig */ constructor(moduleConfig) { this.moduleConfig = moduleConfig; this.index = 0; this.indexChange = new EventEmitter(); this.configChange = new EventEmitter(); this.customImageEvent = new EventEmitter(); this.style = { transform: '', msTransform: '', oTransform: '', webkitTransform: '', cursor: 'pointer' }; this.fullscreen = false; this.loading = true; this.scale = 1; this.rotation = 0; this.translateX = 0; this.translateY = 0; this.hovered = false; } /** * @return {?} */ ngOnInit() { /** @type {?} */ const merged = this.mergeConfig(DEFAULT_CONFIG, this.moduleConfig); this.config = this.mergeConfig(merged, this.config); this.triggerConfigBinding(); } /** * @param {?} event * @return {?} */ nextImage(event) { if (this.canNavigate(event) && this.index < this.src.length - 1) { this.loading = true; this.index++; this.triggerIndexBinding(); this.reset(); } } /** * @param {?} event * @return {?} */ prevImage(event) { if (this.canNavigate(event) && this.index > 0) { this.loading = true; this.index--; this.triggerIndexBinding(); this.reset(); } } /** * @return {?} */ zoomIn() { this.scale *= (1 + this.config.zoomFactor); this.updateStyle(); } /** * @return {?} */ zoomOut() { if (this.scale > this.config.zoomFactor) { this.scale /= (1 + this.config.zoomFactor); } this.updateStyle(); } /** * @param {?} evt * @return {?} */ scrollZoom(evt) { if (this.config.wheelZoom) { evt.deltaY > 0 ? this.zoomOut() : this.zoomIn(); return false; } } /** * @return {?} */ rotateClockwise() { this.rotation += 90; this.updateStyle(); } /** * @return {?} */ rotateCounterClockwise() { this.rotation -= 90; this.updateStyle(); } /** * @return {?} */ onLoad() { this.loading = false; } /** * @return {?} */ onLoadStart() { this.loading = true; } /** * @param {?} evt * @return {?} */ onDragOver(evt) { this.translateX += (evt.clientX - this.prevX); this.translateY += (evt.clientY - this.prevY); this.prevX = evt.clientX; this.prevY = evt.clientY; this.updateStyle(); } /** * @param {?} evt * @return {?} */ onDragStart(evt) { this.prevX = evt.clientX; this.prevY = evt.clientY; } /** * @return {?} */ toggleFullscreen() { // this.fullscreen = !this.fullscreen; // if (!this.fullscreen) { // this.reset(); // } this.translateX = 0; this.translateY = 0; this.scale = 1; this.rotation = 0; this.translateX = 0; this.translateY = 0; this.zoomIn(); this.zoomOut(); } /** * @return {?} */ triggerIndexBinding() { this.indexChange.emit(this.index); } /** * @return {?} */ triggerConfigBinding() { this.configChange.next(this.config); } /** * @param {?} name * @param {?} imageIndex * @return {?} */ fireCustomEvent(name, imageIndex) { this.customImageEvent.emit(new CustomImageEvent(name, imageIndex)); } /** * @return {?} */ reset() { this.scale = 1; this.rotation = 0; this.translateX = 0; this.translateY = 0; this.updateStyle(); } /** * @return {?} */ onMouseOver() { this.hovered = true; } /** * @return {?} */ onMouseLeave() { this.hovered = false; } /** * @private * @param {?} event * @return {?} */ canNavigate(event) { return event == null || (this.config.allowKeyboardNavigation && this.hovered); } /** * @private * @return {?} */ updateStyle() { this.style.transform = `translate(${this.translateX}px, ${this.translateY}px) rotate(${this.rotation}deg) scale(${this.scale})`; this.style.msTransform = this.style.transform; this.style.webkitTransform = this.style.transform; this.style.oTransform = this.style.transform; } /** * @private * @param {?} defaultValues * @param {?} overrideValues * @return {?} */ mergeConfig(defaultValues, overrideValues) { /** @type {?} */ let result = Object.assign({}, defaultValues); if (overrideValues) { result = Object.assign({}, defaultValues, overrideValues); if (overrideValues.btnIcons) { result.btnIcons = Object.assign({}, defaultValues.btnIcons, overrideValues.btnIcons); } } return result; } } NgImageViewerComponent.decorators = [ { type: Component, args: [{ // tslint:disable-next-line:component-selector selector: 'ng-image-viewer', template: ` <div class="img-container" [style.backgroundColor]="config.containerBackgroundColor" (wheel)="scrollZoom($event)" (dragover)="onDragOver($event)"> <div [ngStyle]="{width: width+'px',height: height+'px'}"> <img [src]="src[index]" [ngStyle]="style" alt="Image not found..." (dragstart)="onDragStart($event)" (load)="onLoad()" (loadstart)="onLoadStart()" /> <!-- Div below will be used to hide the 'ghost' image when dragging --> </div> <div></div> <div class="spinner-container" *ngIf="loading"> <div class="spinner"></div> </div> <button type="button" [class]="config.btnClass" *ngIf="config.btnShow.rotateCounterClockwise" (click)="rotateCounterClockwise()"> <span [class]="config.btnIcons.rotateCounterClockwise"></span> </button> <button type="button" [class]="config.btnClass" *ngIf="config.btnShow.rotateClockwise" (click)="rotateClockwise()"> <span [class]="config.btnIcons.rotateClockwise"></span> </button> <button type="button" [class]="config.btnClass" *ngIf="config.btnShow.zoomOut" (click)="zoomOut()"> <span [class]="config.btnIcons.zoomOut"></span> </button> <button type="button" [class]="config.btnClass" *ngIf="config.btnShow.zoomIn" (click)="zoomIn()"> <span [class]="config.btnIcons.zoomIn"></span> </button> <!-- <button type="button" [class]="config.btnClass" *ngFor="let cBtn of config.customBtns"--> <!-- (click)="fireCustomEvent(cBtn.name, index)">--> <!-- <span [class]="cBtn.icon"></span>--> <!-- </button>--> <button type="button" [class]="config.btnClass" (click)="toggleFullscreen()" *ngIf="config.allowFullscreen"> <span [class]="config.btnIcons.fullscreen"></span> </button> <!-- <div class="nav-button-container" *ngIf="src.length > 1">--> <!-- <button type="button" [class]="config.btnClass" (click)="prevImage($event)" [disabled]="index === 0">--> <!-- <span [class]="config.btnIcons.prev"></span>--> <!-- </button>--> <!-- <button type="button" [class]="config.btnClass" (click)="nextImage($event)" [disabled]="index === src.length - 1">--> <!-- <span [class]="config.btnIcons.next"></span>--> <!-- </button>--> <!-- </div>--> </div> `, styles: [".img-container{height:100%;width:100%;overflow:hidden;position:relative}.img-container img{z-index:2;margin:0 auto;display:block;max-width:100%;max-height:100%;width:100%}.img-container button{z-index:99;position:absolute;right:15px}.img-container button:not(:disabled){cursor:pointer}.img-container>button:nth-of-type(1):not(#ngx-fs-btn){bottom:15px}.img-container>button:nth-of-type(2):not(#ngx-fs-btn){bottom:65px}.img-container>button:nth-of-type(3):not(#ngx-fs-btn){bottom:115px}.img-container>button:nth-of-type(4):not(#ngx-fs-btn){bottom:165px}.img-container>button:nth-of-type(5):not(#ngx-fs-btn){bottom:215px}.img-container>button:nth-of-type(6):not(#ngx-fs-btn){bottom:265px}.img-container>button:nth-of-type(7):not(#ngx-fs-btn){bottom:315px}#ngx-fs-btn{top:15px}button.default{height:40px;width:40px;border:1px solid #555;border-radius:50%;background-color:#fff;opacity:.7;transition:opacity .2s}button.default:hover{opacity:1}button.default:disabled{opacity:.25}.nav-button-container>button{position:relative;right:0;margin:0 10px}.nav-button-container{text-align:center;position:absolute;z-index:98;bottom:10px;left:0;right:0}.spinner-container{position:absolute;left:0;right:0;top:0;bottom:0;width:60px;height:60px;margin:auto;padding:10px;background-color:rgba(0,0,0,.4);border-radius:25%}.spinner{border-width:7px;border-style:solid;border-color:#ccc #ccc #222;border-radius:50%;height:100%;width:100%;box-sizing:border-box;-webkit-animation:2s linear infinite rotation;animation:2s linear infinite rotation}@keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(359deg)}}@-webkit-keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(359deg)}}"] }] } ]; /** @nocollapse */ NgImageViewerComponent.ctorParameters = () => [ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: ['config',] }] } ]; NgImageViewerComponent.propDecorators = { src: [{ type: Input }], width: [{ type: Input }], height: [{ type: Input }], index: [{ type: Input }], config: [{ type: Input }], indexChange: [{ type: Output }], configChange: [{ type: Output }], customImageEvent: [{ type: Output }], nextImage: [{ type: HostListener, args: ['window:keyup.ArrowRight', ['$event'],] }], prevImage: [{ type: HostListener, args: ['window:keyup.ArrowLeft', ['$event'],] }], onMouseOver: [{ type: HostListener, args: ['mouseover',] }], onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }] }; if (false) { /** @type {?} */ NgImageViewerComponent.prototype.src; /** @type {?} */ NgImageViewerComponent.prototype.width; /** @type {?} */ NgImageViewerComponent.prototype.height; /** @type {?} */ NgImageViewerComponent.prototype.index; /** @type {?} */ NgImageViewerComponent.prototype.config; /** @type {?} */ NgImageViewerComponent.prototype.indexChange; /** @type {?} */ NgImageViewerComponent.prototype.configChange; /** @type {?} */ NgImageViewerComponent.prototype.customImageEvent; /** @type {?} */ NgImageViewerComponent.prototype.style; /** @type {?} */ NgImageViewerComponent.prototype.fullscreen; /** @type {?} */ NgImageViewerComponent.prototype.loading; /** * @type {?} * @private */ NgImageViewerComponent.prototype.scale; /** * @type {?} * @private */ NgImageViewerComponent.prototype.rotation; /** * @type {?} * @private */ NgImageViewerComponent.prototype.translateX; /** * @type {?} * @private */ NgImageViewerComponent.prototype.translateY; /** * @type {?} * @private */ NgImageViewerComponent.prototype.prevX; /** * @type {?} * @private */ NgImageViewerComponent.prototype.prevY; /** * @type {?} * @private */ NgImageViewerComponent.prototype.hovered; /** @type {?} */ NgImageViewerComponent.prototype.moduleConfig; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctaW1hZ2Utdmlld2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BzY2ljb20tZXNvbHV0aW9ucy9uZy1pbWFnZS12aWV3ZXIvIiwic291cmNlcyI6WyJsaWIvbmctaW1hZ2Utdmlld2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE9BQU8sRUFBQyxTQUFTLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFVLFFBQVEsRUFBRSxNQUFNLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFFN0csT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sa0NBQWtDLENBQUM7O01BRTVELGNBQWMsR0FBc0I7SUFDeEMsUUFBUSxFQUFFLFNBQVM7SUFDbkIsVUFBVSxFQUFFLEdBQUc7SUFDZix3QkFBd0IsRUFBRSxNQUFNO0lBQ2hDLFNBQVMsRUFBRSxJQUFJO0lBQ2YsZUFBZSxFQUFFLElBQUk7SUFDckIsdUJBQXVCLEVBQUUsSUFBSTtJQUM3QixPQUFPLEVBQUU7UUFDUCxNQUFNLEVBQUUsSUFBSTtRQUNaLE9BQU8sRUFBRSxJQUFJO1FBQ2IsZUFBZSxFQUFFLElBQUk7UUFDckIsc0JBQXNCLEVBQUUsSUFBSTtLQUM3QjtJQUNELFFBQVEsRUFBRTtRQUNSLE1BQU0sRUFBRSxZQUFZO1FBQ3BCLE9BQU8sRUFBRSxhQUFhO1FBQ3RCLGVBQWUsRUFBRSxjQUFjO1FBQy9CLHNCQUFzQixFQUFFLFlBQVk7UUFDcEMsVUFBVSxFQUFFLGVBQWU7S0FDNUI7Q0FDRjtBQXVERCxNQUFNLE9BQU8sc0JBQXNCOzs7O0lBcUNqQyxZQUFpRCxZQUErQjtRQUEvQixpQkFBWSxHQUFaLFlBQVksQ0FBbUI7UUF6QmhGLFVBQUssR0FBRyxDQUFDLENBQUM7UUFNVixnQkFBVyxHQUF5QixJQUFJLFlBQVksRUFBRSxDQUFDO1FBR3ZELGlCQUFZLEdBQW9DLElBQUksWUFBWSxFQUFFLENBQUM7UUFHbkUscUJBQWdCLEdBQW1DLElBQUksWUFBWSxFQUFFLENBQUM7UUFFL0QsVUFBSyxHQUFHLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsZUFBZSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUM7UUFDbkcsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUNuQixZQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ2QsVUFBSyxHQUFHLENBQUMsQ0FBQztRQUNWLGFBQVEsR0FBRyxDQUFDLENBQUM7UUFDYixlQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ2YsZUFBVSxHQUFHLENBQUMsQ0FBQztRQUdmLFlBQU8sR0FBRyxLQUFLLENBQUM7SUFFNEQsQ0FBQzs7OztJQUVyRixRQUFROztjQUNBLE1BQU0sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ2xFLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO0lBQzlCLENBQUM7Ozs7O0lBR0QsU0FBUyxDQUFDLEtBQUs7UUFDYixJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDL0QsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7WUFDcEIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2IsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7WUFDM0IsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ2Q7SUFDSCxDQUFDOzs7OztJQUdELFNBQVMsQ0FBQyxLQUFLO1FBQ2IsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFO1lBQzdDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQzNCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztTQUNkO0lBQ0gsQ0FBQzs7OztJQUVELE1BQU07UUFDSixJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7Ozs7SUFFRCxPQUFPO1FBQ0wsSUFBSSxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFO1lBQ3ZDLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUM1QztRQUNELElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyQixDQUFDOzs7OztJQUVELFVBQVUsQ0FBQyxHQUFHO1FBQ1osSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRTtZQUN6QixHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDaEQsT0FBTyxLQUFLLENBQUM7U0FDZDtJQUNILENBQUM7Ozs7SUFFRCxlQUFlO1FBQ2IsSUFBSSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7Ozs7SUFFRCxzQkFBc0I7UUFDcEIsSUFBSSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7Ozs7SUFFRCxNQUFNO1FBQ0osSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDdkIsQ0FBQzs7OztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztJQUN0QixDQUFDOzs7OztJQUVELFVBQVUsQ0FBQyxHQUFHO1FBQ1osSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5QyxJQUFJLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUM7UUFDekIsSUFBSSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyQixDQUFDOzs7OztJQUVELFdBQVcsQ0FBQyxHQUFHO1FBQ2IsSUFBSSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQztJQUMzQixDQUFDOzs7O0lBRUQsZ0JBQWdCO1FBQ2Qsc0NBQXNDO1FBQ3RDLDBCQUEwQjtRQUMxQixrQkFBa0I7UUFDbEIsSUFBSTtRQUNKLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUM7UUFDbEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUM7UUFDcEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUM7UUFDcEIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2QsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2pCLENBQUM7Ozs7SUFFRCxtQkFBbUI7UUFDakIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3BDLENBQUM7Ozs7SUFFRCxvQkFBb0I7UUFDbEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3RDLENBQUM7Ozs7OztJQUVELGVBQWUsQ0FBQyxJQUFJLEVBQUUsVUFBVTtRQUM5QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksZ0JBQWdCLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDckUsQ0FBQzs7OztJQUVELEtBQUs7UUFDSCxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQ2xCLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyQixDQUFDOzs7O0lBR0QsV0FBVztRQUNULElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO0lBQ3RCLENBQUM7Ozs7SUFHRCxZQUFZO1FBQ1YsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDdkIsQ0FBQzs7Ozs7O0lBRU8sV0FBVyxDQUFDLEtBQVU7UUFDNUIsT0FBTyxLQUFLLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDaEYsQ0FBQzs7Ozs7SUFFTyxXQUFXO1FBQ2pCLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLGFBQWEsSUFBSSxDQUFDLFVBQVUsT0FBTyxJQUFJLENBQUMsVUFBVSxjQUFjLElBQUksQ0FBQyxRQUFRLGNBQWMsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDO1FBQ2hJLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBQzlDLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBQ2xELElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO0lBQy9DLENBQUM7Ozs7Ozs7SUFFTyxXQUFXLENBQUMsYUFBZ0MsRUFBRSxjQUFpQzs7WUFDakYsTUFBTSxxQkFBMkIsYUFBYSxDQUFFO1FBQ3BELElBQUksY0FBYyxFQUFFO1lBQ2xCLE1BQU0scUJBQVEsYUFBYSxFQUFLLGNBQWMsQ0FBRSxDQUFDO1lBRWpELElBQUksY0FBYyxDQUFDLFFBQVEsRUFBRTtnQkFDM0IsTUFBTSxDQUFDLFFBQVEscUJBQVEsYUFBYSxDQUFDLFFBQVEsRUFBSyxjQUFjLENBQUMsUUFBUSxDQUFFLENBQUM7YUFDN0U7U0FDRjtRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7OztZQTFPRixTQUFTLFNBQUM7O2dCQUVULFFBQVEsRUFBRSxpQkFBaUI7Z0JBQzNCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0ErQ1Q7O2FBRUY7Ozs7NENBc0NjLFFBQVEsWUFBSSxNQUFNLFNBQUMsUUFBUTs7O2tCQW5DdkMsS0FBSztvQkFHTCxLQUFLO3FCQUdMLEtBQUs7b0JBR0wsS0FBSztxQkFHTCxLQUFLOzBCQUdMLE1BQU07MkJBR04sTUFBTTsrQkFHTixNQUFNO3dCQXNCTixZQUFZLFNBQUMseUJBQXlCLEVBQUUsQ0FBQyxRQUFRLENBQUM7d0JBVWxELFlBQVksU0FBQyx3QkFBd0IsRUFBRSxDQUFDLFFBQVEsQ0FBQzswQkErRmpELFlBQVksU0FBQyxXQUFXOzJCQUt4QixZQUFZLFNBQUMsWUFBWTs7OztJQXpKMUIscUNBQ2M7O0lBRWQsdUNBQ2M7O0lBRWQsd0NBQ2U7O0lBRWYsdUNBQ1U7O0lBRVYsd0NBQzBCOztJQUUxQiw2Q0FDdUQ7O0lBRXZELDhDQUNtRTs7SUFFbkUsa0RBQ3NFOztJQUV0RSx1Q0FBMEc7O0lBQzFHLDRDQUEwQjs7SUFDMUIseUNBQXNCOzs7OztJQUN0Qix1Q0FBa0I7Ozs7O0lBQ2xCLDBDQUFxQjs7Ozs7SUFDckIsNENBQXVCOzs7OztJQUN2Qiw0Q0FBdUI7Ozs7O0lBQ3ZCLHVDQUFzQjs7Ozs7SUFDdEIsdUNBQXNCOzs7OztJQUN0Qix5Q0FBd0I7O0lBRVosOENBQW9FIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyLCBJbmplY3QsIElucHV0LCBPbkluaXQsIE9wdGlvbmFsLCBPdXRwdXR9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtJbWFnZVZpZXdlckNvbmZpZ30gZnJvbSAnLi9tb2RlbC9pbWFnZS12aWV3ZXItY29uZmlnLm1vZGVsJztcbmltcG9ydCB7Q3VzdG9tSW1hZ2VFdmVudH0gZnJvbSAnLi9tb2RlbC9jdXN0b20taW1hZ2UtZXZlbnQtbW9kZWwnO1xuXG5jb25zdCBERUZBVUxUX0NPTkZJRzogSW1hZ2VWaWV3ZXJDb25maWcgPSB7XG4gIGJ0bkNsYXNzOiAnZGVmYXVsdCcsXG4gIHpvb21GYWN0b3I6IDAuMSxcbiAgY29udGFpbmVyQmFja2dyb3VuZENvbG9yOiAnI2NjYycsXG4gIHdoZWVsWm9vbTogdHJ1ZSxcbiAgYWxsb3dGdWxsc2NyZWVuOiB0cnVlLFxuICBhbGxvd0tleWJvYXJkTmF2aWdhdGlvbjogdHJ1ZSxcbiAgYnRuU2hvdzoge1xuICAgIHpvb21JbjogdHJ1ZSxcbiAgICB6b29tT3V0OiB0cnVlLFxuICAgIHJvdGF0ZUNsb2Nrd2lzZTogdHJ1ZSxcbiAgICByb3RhdGVDb3VudGVyQ2xvY2t3aXNlOiB0cnVlLFxuICB9LFxuICBidG5JY29uczoge1xuICAgIHpvb21JbjogJ2ZhIGZhLXBsdXMnLFxuICAgIHpvb21PdXQ6ICdmYSBmYS1taW51cycsXG4gICAgcm90YXRlQ2xvY2t3aXNlOiAnZmEgZmEtcmVwZWF0JyxcbiAgICByb3RhdGVDb3VudGVyQ2xvY2t3aXNlOiAnZmEgZmEtdW5kbycsXG4gICAgZnVsbHNjcmVlbjogJ2ZhIGZhLXJlZnJlc2gnLFxuICB9XG59O1xuXG5AQ29tcG9uZW50KHtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxuICBzZWxlY3RvcjogJ25nLWltYWdlLXZpZXdlcicsXG4gIHRlbXBsYXRlOiBgXG4gICAgICA8ZGl2IGNsYXNzPVwiaW1nLWNvbnRhaW5lclwiIFtzdHlsZS5iYWNrZ3JvdW5kQ29sb3JdPVwiY29uZmlnLmNvbnRhaW5lckJhY2tncm91bmRDb2xvclwiXG4gICAgICAgICAgICh3aGVlbCk9XCJzY3JvbGxab29tKCRldmVudClcIiAoZHJhZ292ZXIpPVwib25EcmFnT3ZlcigkZXZlbnQpXCI+XG4gICAgICAgICAgPGRpdiBbbmdTdHlsZV09XCJ7d2lkdGg6IHdpZHRoKydweCcsaGVpZ2h0OiBoZWlnaHQrJ3B4J31cIj5cbiAgICAgICAgICAgICAgPGltZyBbc3JjXT1cInNyY1tpbmRleF1cIiAgW25nU3R5bGVdPVwic3R5bGVcIiBhbHQ9XCJJbWFnZSBub3QgZm91bmQuLi5cIiAoZHJhZ3N0YXJ0KT1cIm9uRHJhZ1N0YXJ0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgIChsb2FkKT1cIm9uTG9hZCgpXCIgKGxvYWRzdGFydCk9XCJvbkxvYWRTdGFydCgpXCIgLz5cbiAgICAgICAgICAgICAgPCEtLSBEaXYgYmVsb3cgd2lsbCBiZSB1c2VkIHRvIGhpZGUgdGhlICdnaG9zdCcgaW1hZ2Ugd2hlbiBkcmFnZ2luZyAtLT5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2PjwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcGlubmVyLWNvbnRhaW5lclwiICpuZ0lmPVwibG9hZGluZ1wiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Bpbm5lclwiPjwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgW2NsYXNzXT1cImNvbmZpZy5idG5DbGFzc1wiICpuZ0lmPVwiY29uZmlnLmJ0blNob3cucm90YXRlQ291bnRlckNsb2Nrd2lzZVwiXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwicm90YXRlQ291bnRlckNsb2Nrd2lzZSgpXCI+XG4gICAgICAgICAgICAgIDxzcGFuIFtjbGFzc109XCJjb25maWcuYnRuSWNvbnMucm90YXRlQ291bnRlckNsb2Nrd2lzZVwiPjwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBbY2xhc3NdPVwiY29uZmlnLmJ0bkNsYXNzXCIgKm5nSWY9XCJjb25maWcuYnRuU2hvdy5yb3RhdGVDbG9ja3dpc2VcIiAoY2xpY2spPVwicm90YXRlQ2xvY2t3aXNlKClcIj5cbiAgICAgICAgICAgICAgPHNwYW4gW2NsYXNzXT1cImNvbmZpZy5idG5JY29ucy5yb3RhdGVDbG9ja3dpc2VcIj48L3NwYW4+XG4gICAgICAgICAgPC9idXR0b24+XG5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBbY2xhc3NdPVwiY29uZmlnLmJ0bkNsYXNzXCIgKm5nSWY9XCJjb25maWcuYnRuU2hvdy56b29tT3V0XCIgKGNsaWNrKT1cInpvb21PdXQoKVwiPlxuICAgICAgICAgICAgICA8c3BhbiBbY2xhc3NdPVwiY29uZmlnLmJ0bkljb25zLnpvb21PdXRcIj48L3NwYW4+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgW2NsYXNzXT1cImNvbmZpZy5idG5DbGFzc1wiICpuZ0lmPVwiY29uZmlnLmJ0blNob3cuem9vbUluXCIgKGNsaWNrKT1cInpvb21JbigpXCI+XG4gICAgICAgICAgICAgIDxzcGFuIFtjbGFzc109XCJjb25maWcuYnRuSWNvbnMuem9vbUluXCI+PC9zcGFuPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgPCEtLSAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBbY2xhc3NdPVwiY29uZmlnLmJ0bkNsYXNzXCIgKm5nRm9yPVwibGV0IGNCdG4gb2YgY29uZmlnLmN1c3RvbUJ0bnNcIi0tPlxuICAgICAgICAgIDwhLS0gICAgICAgIChjbGljayk9XCJmaXJlQ3VzdG9tRXZlbnQoY0J0bi5uYW1lLCBpbmRleClcIj4tLT5cbiAgICAgICAgICA8IS0tICAgICAgICA8c3BhbiBbY2xhc3NdPVwiY0J0bi5pY29uXCI+PC9zcGFuPi0tPlxuICAgICAgICAgIDwhLS0gICAgPC9idXR0b24+LS0+XG5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBbY2xhc3NdPVwiY29uZmlnLmJ0bkNsYXNzXCIgKGNsaWNrKT1cInRvZ2dsZUZ1bGxzY3JlZW4oKVwiXG4gICAgICAgICAgICAgICAgICAqbmdJZj1cImNvbmZpZy5hbGxvd0Z1bGxzY3JlZW5cIj5cbiAgICAgICAgICAgICAgPHNwYW4gW2NsYXNzXT1cImNvbmZpZy5idG5JY29ucy5mdWxsc2NyZWVuXCI+PC9zcGFuPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgPCEtLSAgICA8ZGl2IGNsYXNzPVwibmF2LWJ1dHRvbi1jb250YWluZXJcIiAqbmdJZj1cInNyYy5sZW5ndGggPiAxXCI+LS0+XG4gICAgICAgICAgPCEtLSAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgW2NsYXNzXT1cImNvbmZpZy5idG5DbGFzc1wiIChjbGljayk9XCJwcmV2SW1hZ2UoJGV2ZW50KVwiIFtkaXNhYmxlZF09XCJpbmRleCA9PT0gMFwiPi0tPlxuICAgICAgICAgIDwhLS0gICAgICAgICAgICA8c3BhbiBbY2xhc3NdPVwiY29uZmlnLmJ0bkljb25zLnByZXZcIj48L3NwYW4+LS0+XG4gICAgICAgICAgPCEtLSAgICAgICAgPC9idXR0b24+LS0+XG4gICAgICAgICAgPCEtLSAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgW2NsYXNzXT1cImNvbmZpZy5idG5DbGFzc1wiIChjbGljayk9XCJuZXh0SW1hZ2UoJGV2ZW50KVwiIFtkaXNhYmxlZF09XCJpbmRleCA9PT0gc3JjLmxlbmd0aCAtIDFcIj4tLT5cbiAgICAgICAgICA8IS0tICAgICAgICAgICAgPHNwYW4gW2NsYXNzXT1cImNvbmZpZy5idG5JY29ucy5uZXh0XCI+PC9zcGFuPi0tPlxuICAgICAgICAgIDwhLS0gICAgICAgIDwvYnV0dG9uPi0tPlxuICAgICAgICAgIDwhLS0gICAgPC9kaXY+LS0+XG4gICAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVVcmxzOiBbJy4vbmctaW1hZ2Utdmlld2VyLmNvbXBvbmVudC5zY3NzJyBdXG59KVxuZXhwb3J0IGNsYXNzIE5nSW1hZ2VWaWV3ZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuXG4gIEBJbnB1dCgpXG4gIHNyYzogc3RyaW5nW107XG5cbiAgQElucHV0KClcbiAgd2lkdGg6IHN0cmluZztcblxuICBASW5wdXQoKVxuICBoZWlnaHQ6IHN0cmluZztcblxuICBASW5wdXQoKVxuICBpbmRleCA9IDA7XG5cbiAgQElucHV0KClcbiAgY29uZmlnOiBJbWFnZVZpZXdlckNvbmZpZztcblxuICBAT3V0cHV0KClcbiAgaW5kZXhDaGFuZ2U6IEV2ZW50RW1pdHRlcjxudW1iZXI+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoKVxuICBjb25maWdDaGFuZ2U6IEV2ZW50RW1pdHRlcjxJbWFnZVZpZXdlckNvbmZpZz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpXG4gIGN1c3RvbUltYWdlRXZlbnQ6IEV2ZW50RW1pdHRlcjxDdXN0b21JbWFnZUV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBwdWJsaWMgc3R5bGUgPSB7IHRyYW5zZm9ybTogJycsIG1zVHJhbnNmb3JtOiAnJywgb1RyYW5zZm9ybTogJycsIHdlYmtpdFRyYW5zZm9ybTogJycsIGN1cnNvcjogJ3BvaW50ZXInIH07XG4gIHB1YmxpYyBmdWxsc2NyZWVuID0gZmFsc2U7XG4gIHB1YmxpYyBsb2FkaW5nID0gdHJ1ZTtcbiAgcHJpdmF0ZSBzY2FsZSA9IDE7XG4gIHByaXZhdGUgcm90YXRpb24gPSAwO1xuICBwcml2YXRlIHRyYW5zbGF0ZVggPSAwO1xuICBwcml2YXRlIHRyYW5zbGF0ZVkgPSAwO1xuICBwcml2YXRlIHByZXZYOiBudW1iZXI7XG4gIHByaXZhdGUgcHJldlk6IG51bWJlcjtcbiAgcHJpdmF0ZSBob3ZlcmVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoQE9wdGlvbmFsKCkgQEluamVjdCgnY29uZmlnJykgcHVibGljIG1vZHVsZUNvbmZpZzogSW1hZ2VWaWV3ZXJDb25maWcpIHsgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIGNvbnN0IG1lcmdlZCA9IHRoaXMubWVyZ2VDb25maWcoREVGQVVMVF9DT05GSUcsIHRoaXMubW9kdWxlQ29uZmlnKTtcbiAgICB0aGlzLmNvbmZpZyA9IHRoaXMubWVyZ2VDb25maWcobWVyZ2VkLCB0aGlzLmNvbmZpZyk7XG4gICAgdGhpcy50cmlnZ2VyQ29uZmlnQmluZGluZygpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleXVwLkFycm93UmlnaHQnLCBbJyRldmVudCddKVxuICBuZXh0SW1hZ2UoZXZlbnQpIHtcbiAgICBpZiAodGhpcy5jYW5OYXZpZ2F0ZShldmVudCkgJiYgdGhpcy5pbmRleCA8IHRoaXMuc3JjLmxlbmd0aCAtIDEpIHtcbiAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XG4gICAgICB0aGlzLmluZGV4Kys7XG4gICAgICB0aGlzLnRyaWdnZXJJbmRleEJpbmRpbmcoKTtcbiAgICAgIHRoaXMucmVzZXQoKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5dXAuQXJyb3dMZWZ0JywgWyckZXZlbnQnXSlcbiAgcHJldkltYWdlKGV2ZW50KSB7XG4gICAgaWYgKHRoaXMuY2FuTmF2aWdhdGUoZXZlbnQpICYmIHRoaXMuaW5kZXggPiAwKSB7XG4gICAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xuICAgICAgdGhpcy5pbmRleC0tO1xuICAgICAgdGhpcy50cmlnZ2VySW5kZXhCaW5kaW5nKCk7XG4gICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfVxuICB9XG5cbiAgem9vbUluKCkge1xuICAgIHRoaXMuc2NhbGUgKj0gKDEgKyB0aGlzLmNvbmZpZy56b29tRmFjdG9yKTtcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICB6b29tT3V0KCkge1xuICAgIGlmICh0aGlzLnNjYWxlID4gdGhpcy5jb25maWcuem9vbUZhY3Rvcikge1xuICAgICAgdGhpcy5zY2FsZSAvPSAoMSArIHRoaXMuY29uZmlnLnpvb21GYWN0b3IpO1xuICAgIH1cbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICBzY3JvbGxab29tKGV2dCkge1xuICAgIGlmICh0aGlzLmNvbmZpZy53aGVlbFpvb20pIHtcbiAgICAgIGV2dC5kZWx0YVkgPiAwID8gdGhpcy56b29tT3V0KCkgOiB0aGlzLnpvb21JbigpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJvdGF0ZUNsb2Nrd2lzZSgpIHtcbiAgICB0aGlzLnJvdGF0aW9uICs9IDkwO1xuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgfVxuXG4gIHJvdGF0ZUNvdW50ZXJDbG9ja3dpc2UoKSB7XG4gICAgdGhpcy5yb3RhdGlvbiAtPSA5MDtcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICBvbkxvYWQoKSB7XG4gICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gIH1cblxuICBvbkxvYWRTdGFydCgpIHtcbiAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xuICB9XG5cbiAgb25EcmFnT3ZlcihldnQpIHtcbiAgICB0aGlzLnRyYW5zbGF0ZVggKz0gKGV2dC5jbGllbnRYIC0gdGhpcy5wcmV2WCk7XG4gICAgdGhpcy50cmFuc2xhdGVZICs9IChldnQuY2xpZW50WSAtIHRoaXMucHJldlkpO1xuICAgIHRoaXMucHJldlggPSBldnQuY2xpZW50WDtcbiAgICB0aGlzLnByZXZZID0gZXZ0LmNsaWVudFk7XG4gICAgdGhpcy51cGRhdGVTdHlsZSgpO1xuICB9XG5cbiAgb25EcmFnU3RhcnQoZXZ0KSB7XG4gICAgdGhpcy5wcmV2WCA9IGV2dC5jbGllbnRYO1xuICAgIHRoaXMucHJldlkgPSBldnQuY2xpZW50WTtcbiAgfVxuXG4gIHRvZ2dsZUZ1bGxzY3JlZW4oKSB7XG4gICAgLy8gdGhpcy5mdWxsc2NyZWVuID0gIXRoaXMuZnVsbHNjcmVlbjtcbiAgICAvLyBpZiAoIXRoaXMuZnVsbHNjcmVlbikge1xuICAgIC8vICAgdGhpcy5yZXNldCgpO1xuICAgIC8vIH1cbiAgICB0aGlzLnRyYW5zbGF0ZVggPSAwO1xuICAgIHRoaXMudHJhbnNsYXRlWSA9IDA7XG4gICAgdGhpcy5zY2FsZSA9IDE7XG4gICAgdGhpcy5yb3RhdGlvbiA9IDA7XG4gICAgdGhpcy50cmFuc2xhdGVYID0gMDtcbiAgICB0aGlzLnRyYW5zbGF0ZVkgPSAwO1xuICAgIHRoaXMuem9vbUluKCk7XG4gICAgdGhpcy56b29tT3V0KCk7XG4gIH1cblxuICB0cmlnZ2VySW5kZXhCaW5kaW5nKCkge1xuICAgIHRoaXMuaW5kZXhDaGFuZ2UuZW1pdCh0aGlzLmluZGV4KTtcbiAgfVxuXG4gIHRyaWdnZXJDb25maWdCaW5kaW5nKCkge1xuICAgIHRoaXMuY29uZmlnQ2hhbmdlLm5leHQodGhpcy5jb25maWcpO1xuICB9XG5cbiAgZmlyZUN1c3RvbUV2ZW50KG5hbWUsIGltYWdlSW5kZXgpIHtcbiAgICB0aGlzLmN1c3RvbUltYWdlRXZlbnQuZW1pdChuZXcgQ3VzdG9tSW1hZ2VFdmVudChuYW1lLCBpbWFnZUluZGV4KSk7XG4gIH1cblxuICByZXNldCgpIHtcbiAgICB0aGlzLnNjYWxlID0gMTtcbiAgICB0aGlzLnJvdGF0aW9uID0gMDtcbiAgICB0aGlzLnRyYW5zbGF0ZVggPSAwO1xuICAgIHRoaXMudHJhbnNsYXRlWSA9IDA7XG4gICAgdGhpcy51cGRhdGVTdHlsZSgpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2VvdmVyJylcbiAgb25Nb3VzZU92ZXIoKSB7XG4gICAgdGhpcy5ob3ZlcmVkID0gdHJ1ZTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlbGVhdmUnKVxuICBvbk1vdXNlTGVhdmUoKSB7XG4gICAgdGhpcy5ob3ZlcmVkID0gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGNhbk5hdmlnYXRlKGV2ZW50OiBhbnkpIHtcbiAgICByZXR1cm4gZXZlbnQgPT0gbnVsbCB8fCAodGhpcy5jb25maWcuYWxsb3dLZXlib2FyZE5hdmlnYXRpb24gJiYgdGhpcy5ob3ZlcmVkKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlU3R5bGUoKSB7XG4gICAgdGhpcy5zdHlsZS50cmFuc2Zvcm0gPSBgdHJhbnNsYXRlKCR7dGhpcy50cmFuc2xhdGVYfXB4LCAke3RoaXMudHJhbnNsYXRlWX1weCkgcm90YXRlKCR7dGhpcy5yb3RhdGlvbn1kZWcpIHNjYWxlKCR7dGhpcy5zY2FsZX0pYDtcbiAgICB0aGlzLnN0eWxlLm1zVHJhbnNmb3JtID0gdGhpcy5zdHlsZS50cmFuc2Zvcm07XG4gICAgdGhpcy5zdHlsZS53ZWJraXRUcmFuc2Zvcm0gPSB0aGlzLnN0eWxlLnRyYW5zZm9ybTtcbiAgICB0aGlzLnN0eWxlLm9UcmFuc2Zvcm0gPSB0aGlzLnN0eWxlLnRyYW5zZm9ybTtcbiAgfVxuXG4gIHByaXZhdGUgbWVyZ2VDb25maWcoZGVmYXVsdFZhbHVlczogSW1hZ2VWaWV3ZXJDb25maWcsIG92ZXJyaWRlVmFsdWVzOiBJbWFnZVZpZXdlckNvbmZpZyk6IEltYWdlVmlld2VyQ29uZmlnIHtcbiAgICBsZXQgcmVzdWx0OiBJbWFnZVZpZXdlckNvbmZpZyA9IHsgLi4uZGVmYXVsdFZhbHVlcyB9O1xuICAgIGlmIChvdmVycmlkZVZhbHVlcykge1xuICAgICAgcmVzdWx0ID0geyAuLi5kZWZhdWx0VmFsdWVzLCAuLi5vdmVycmlkZVZhbHVlcyB9O1xuXG4gICAgICBpZiAob3ZlcnJpZGVWYWx1ZXMuYnRuSWNvbnMpIHtcbiAgICAgICAgcmVzdWx0LmJ0bkljb25zID0geyAuLi5kZWZhdWx0VmFsdWVzLmJ0bkljb25zLCAuLi5vdmVycmlkZVZhbHVlcy5idG5JY29ucyB9O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG4iXX0=