UNPKG

ng-image-slider-v16

Version:

Angular Image slider with lightbox. An Angular responsive image slider with lightbox popup. Also support youtube url, image base64 string and mp4 video urls and base64 string.

240 lines 40.7 kB
import { Component, Inject, Input, Output, EventEmitter, ViewChild, HostListener } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import * as i0 from "@angular/core"; import * as i1 from "@angular/platform-browser"; import * as i2 from "@angular/common"; import * as i3 from "../slider-custom-image/slider-custom-image.component"; const LIGHTBOX_NEXT_ARROW_CLICK_MESSAGE = 'lightbox next', LIGHTBOX_PREV_ARROW_CLICK_MESSAGE = 'lightbox previous'; export class SliderLightboxComponent { set imageIndex(index) { if (index !== undefined && index > -1 && index < this.images.length) { this.currentImageIndex = index; } this.nextPrevDisable(); } set show(visiableFlag) { this.imageFullscreenView = visiableFlag; this.elRef.nativeElement.ownerDocument.body.style.overflow = ''; if (visiableFlag === true) { this.elRef.nativeElement.ownerDocument.body.style.overflow = 'hidden'; // this.getImageData(); this.setPopupSliderWidth(); } } set animationSpeed(data) { if (data && typeof (data) === 'number' && data >= 0.1 && data <= 5) { this.speed = data; } } onResize(event) { this.effectStyle = 'none'; this.setPopupSliderWidth(); } handleKeyboardEvent(event) { if (event && event.key && this.arrowKeyMove) { if (event.key.toLowerCase() === 'arrowright') { this.nextImageLightbox(); } if (event.key.toLowerCase() === 'arrowleft') { this.prevImageLightbox(); } if (event.key.toLowerCase() === 'escape') { this.closeLightbox(); } } } constructor(cdRef, sanitizer, elRef, document) { this.cdRef = cdRef; this.sanitizer = sanitizer; this.elRef = elRef; this.document = document; this.totalImages = 0; this.nextImageIndex = -1; this.popupWidth = 1200; this.marginLeft = 0; this.imageFullscreenView = false; this.lightboxPrevDisable = false; this.lightboxNextDisable = false; this.showLoading = true; this.effectStyle = 'none'; this.speed = 1; // default speed in second this.title = ''; this.currentImageIndex = 0; // @Inputs this.images = []; this.videoAutoPlay = false; this.direction = 'ltr'; this.paginationShow = false; this.infinite = false; this.arrowKeyMove = true; this.showVideoControls = true; // @Output this.close = new EventEmitter(); this.prevImage = new EventEmitter(); this.nextImage = new EventEmitter(); } ngOnInit() { } ngAfterViewInit() { } ngOnDestroy() { this.resetState(); } setPopupSliderWidth() { if (window && window.innerWidth) { this.popupWidth = window.innerWidth; this.totalImages = this.images.length; if (typeof (this.currentImageIndex) === 'number' && this.currentImageIndex !== undefined) { this.marginLeft = -1 * this.popupWidth * this.currentImageIndex; this.getImageData(); this.nextPrevDisable(); setTimeout(() => { this.showLoading = false; }, 500); } } } closeLightbox() { this.close.emit(); } prevImageLightbox() { this.effectStyle = `all ${this.speed}s ease-in-out`; if (this.currentImageIndex > 0 && !this.lightboxPrevDisable) { this.currentImageIndex--; this.prevImage.emit(LIGHTBOX_PREV_ARROW_CLICK_MESSAGE); this.marginLeft = -1 * this.popupWidth * this.currentImageIndex; this.getImageData(); this.nextPrevDisable(); } } nextImageLightbox() { this.effectStyle = `all ${this.speed}s ease-in-out`; if (this.currentImageIndex < this.images.length - 1 && !this.lightboxNextDisable) { this.currentImageIndex++; this.nextImage.emit(LIGHTBOX_NEXT_ARROW_CLICK_MESSAGE); this.marginLeft = -1 * this.popupWidth * this.currentImageIndex; this.getImageData(); this.nextPrevDisable(); } } nextPrevDisable() { this.lightboxNextDisable = true; this.lightboxPrevDisable = true; setTimeout(() => { this.applyButtonDisableCondition(); }, this.speed * 1000); } applyButtonDisableCondition() { this.lightboxNextDisable = false; this.lightboxPrevDisable = false; if (!this.infinite && this.currentImageIndex >= this.images.length - 1) { this.lightboxNextDisable = true; } if (!this.infinite && this.currentImageIndex <= 0) { this.lightboxPrevDisable = true; } } getImageData() { if (this.images && this.images.length && typeof (this.currentImageIndex) === 'number' && this.currentImageIndex !== undefined && this.images[this.currentImageIndex] && (this.images[this.currentImageIndex]['image'] || this.images[this.currentImageIndex]['video'])) { this.title = this.images[this.currentImageIndex]['title'] || ''; this.totalImages = this.images.length; for (const iframeI in this.document.getElementsByTagName('iframe')) { if (this.document.getElementsByTagName('iframe')[iframeI] && this.document.getElementsByTagName('iframe')[iframeI].contentWindow && this.document.getElementsByTagName('iframe')[iframeI].contentWindow.postMessage) { this.document.getElementsByTagName('iframe')[iframeI].contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*'); } } for (const videoI in this.document.getElementsByTagName('video')) { if (this.document.getElementsByTagName('video')[videoI] && this.document.getElementsByTagName('video')[videoI].pause) { this.document.getElementsByTagName('video')[videoI].pause(); } } } } resetState() { this.images = []; } /** * Swipe event handler * Reference from https://stackoverflow.com/a/44511007/2067646 */ swipeLightboxImg(e, when) { const coord = [e.changedTouches[0].pageX, e.changedTouches[0].pageY]; const time = new Date().getTime(); if (when === 'start') { this.swipeLightboxImgCoord = coord; this.swipeLightboxImgTime = time; } else if (when === 'end') { const direction = [coord[0] - this.swipeLightboxImgCoord[0], coord[1] - this.swipeLightboxImgCoord[1]]; const duration = time - this.swipeLightboxImgTime; if (duration < 1000 // && Math.abs(direction[0]) > 30 // Long enough && Math.abs(direction[0]) > Math.abs(direction[1] * 3)) { // Horizontal enough if (direction[0] < 0) { this.nextImageLightbox(); } else { this.prevImageLightbox(); } } } } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: SliderLightboxComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.DomSanitizer }, { token: i0.ElementRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); } /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.5", type: SliderLightboxComponent, selector: "slider-lightbox", inputs: { images: "images", imageIndex: "imageIndex", show: "show", videoAutoPlay: "videoAutoPlay", direction: "direction", paginationShow: "paginationShow", animationSpeed: "animationSpeed", infinite: "infinite", arrowKeyMove: "arrowKeyMove", showVideoControls: "showVideoControls" }, outputs: { close: "close", prevImage: "prevImage", nextImage: "nextImage" }, host: { listeners: { "window:resize": "onResize($event)", "document:keyup": "handleKeyboardEvent($event)" } }, viewQueries: [{ propertyName: "lightboxDiv", first: true, predicate: ["lightboxDiv"], descendants: true }, { propertyName: "lightboxImageDiv", first: true, predicate: ["lightboxImageDiv"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"imageFullscreenView\" class=\"ng-image-fullscreen-view\">\n <div class=\"lightbox-wrapper\">\n <a class=\"close\" (click)=\"closeLightbox()\"></a>\n <div class=\"lightbox-div\" #lightboxDiv>\n <div *ngIf=\"showLoading\" class=\"pre-loader\">\n <div class=\"mnml-spinner\"></div>\n </div>\n <div class=\"lightbox-image-main\"\n [ngStyle]=\"{'margin-left': marginLeft + 'px', 'grid-template-columns': 'repeat('+images.length+',1fr)', 'transition': effectStyle}\">\n <div class=\"lightbox-image\"\n [ngStyle]=\"{'width': popupWidth + 'px'}\"\n *ngFor=\"let img of images; let i = index\"\n [attr.id]=\"'ng-lightbox-image-' + i\"\n (touchstart)=\"swipeLightboxImg($event, 'start')\"\n (touchend)=\"swipeLightboxImg($event, 'end')\"\n #lightboxImageDiv>\n <div class=\"close-outside\" (click)=\"!img?.video && closeLightbox()\"></div>\n <custom-img\n [imageUrl]=\"img?.image || img?.video\"\n [isVideo]=\"!!(img?.posterImage || img?.video)\"\n [currentImageIndex]=\"currentImageIndex\"\n [imageIndex]=\"i\"\n [speed]=\"speed\"\n [videoAutoPlay]=\"videoAutoPlay && i == currentImageIndex\"\n [showVideoControls]=\"showVideoControls ? 1 : 0\"\n [alt]=\"img?.alt || img?.title || ''\"\n [title]=\"img?.title || img?.alt || ''\"\n [showVideo]=\"true\"\n [direction]=\"direction\">\n </custom-img>\n </div>\n </div>\n <div [dir]=\"direction\" [ngClass]=\"{'show': title, 'hide': !title}\" class=\"caption\">{{ title }}</div>\n <a *ngIf=\"images.length > 1\" [ngClass]=\"{'disable': lightboxPrevDisable}\" class=\"prev icons prev-icon\" (click)=\"prevImageLightbox()\">&lsaquo;</a>\n <a *ngIf=\"images.length > 1\" [ngClass]=\"{'disable': lightboxNextDisable}\" class=\"next icons next-icon\" (click)=\"nextImageLightbox()\">&rsaquo;</a>\n </div>\n </div>\n <div *ngIf=\"paginationShow\" class=\"popup-pagination\">{{currentImageIndex + 1}} of {{totalImages}}</div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3.SliderCustomImageComponent, selector: "custom-img", inputs: ["showVideo", "videoAutoPlay", "showVideoControls", "currentImageIndex", "imageIndex", "speed", "imageUrl", "isVideo", "alt", "title", "direction", "ratio", "lazy"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: SliderLightboxComponent, decorators: [{ type: Component, args: [{ selector: 'slider-lightbox', template: "<div *ngIf=\"imageFullscreenView\" class=\"ng-image-fullscreen-view\">\n <div class=\"lightbox-wrapper\">\n <a class=\"close\" (click)=\"closeLightbox()\"></a>\n <div class=\"lightbox-div\" #lightboxDiv>\n <div *ngIf=\"showLoading\" class=\"pre-loader\">\n <div class=\"mnml-spinner\"></div>\n </div>\n <div class=\"lightbox-image-main\"\n [ngStyle]=\"{'margin-left': marginLeft + 'px', 'grid-template-columns': 'repeat('+images.length+',1fr)', 'transition': effectStyle}\">\n <div class=\"lightbox-image\"\n [ngStyle]=\"{'width': popupWidth + 'px'}\"\n *ngFor=\"let img of images; let i = index\"\n [attr.id]=\"'ng-lightbox-image-' + i\"\n (touchstart)=\"swipeLightboxImg($event, 'start')\"\n (touchend)=\"swipeLightboxImg($event, 'end')\"\n #lightboxImageDiv>\n <div class=\"close-outside\" (click)=\"!img?.video && closeLightbox()\"></div>\n <custom-img\n [imageUrl]=\"img?.image || img?.video\"\n [isVideo]=\"!!(img?.posterImage || img?.video)\"\n [currentImageIndex]=\"currentImageIndex\"\n [imageIndex]=\"i\"\n [speed]=\"speed\"\n [videoAutoPlay]=\"videoAutoPlay && i == currentImageIndex\"\n [showVideoControls]=\"showVideoControls ? 1 : 0\"\n [alt]=\"img?.alt || img?.title || ''\"\n [title]=\"img?.title || img?.alt || ''\"\n [showVideo]=\"true\"\n [direction]=\"direction\">\n </custom-img>\n </div>\n </div>\n <div [dir]=\"direction\" [ngClass]=\"{'show': title, 'hide': !title}\" class=\"caption\">{{ title }}</div>\n <a *ngIf=\"images.length > 1\" [ngClass]=\"{'disable': lightboxPrevDisable}\" class=\"prev icons prev-icon\" (click)=\"prevImageLightbox()\">&lsaquo;</a>\n <a *ngIf=\"images.length > 1\" [ngClass]=\"{'disable': lightboxNextDisable}\" class=\"next icons next-icon\" (click)=\"nextImageLightbox()\">&rsaquo;</a>\n </div>\n </div>\n <div *ngIf=\"paginationShow\" class=\"popup-pagination\">{{currentImageIndex + 1}} of {{totalImages}}</div>\n</div>\n" }] }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.DomSanitizer }, { type: i0.ElementRef }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }]; }, propDecorators: { lightboxDiv: [{ type: ViewChild, args: ['lightboxDiv', { static: false }] }], lightboxImageDiv: [{ type: ViewChild, args: ['lightboxImageDiv', { static: false }] }], images: [{ type: Input }], imageIndex: [{ type: Input }], show: [{ type: Input }], videoAutoPlay: [{ type: Input }], direction: [{ type: Input }], paginationShow: [{ type: Input }], animationSpeed: [{ type: Input }], infinite: [{ type: Input }], arrowKeyMove: [{ type: Input }], showVideoControls: [{ type: Input }], close: [{ type: Output }], prevImage: [{ type: Output }], nextImage: [{ type: Output }], onResize: [{ type: HostListener, args: ['window:resize', ['$event']] }], handleKeyboardEvent: [{ type: HostListener, args: ['document:keyup', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xpZGVyLWxpZ2h0Ym94LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWltYWdlLXNsaWRlci9zcmMvbGliL3NsaWRlci1saWdodGJveC9zbGlkZXItbGlnaHRib3guY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctaW1hZ2Utc2xpZGVyL3NyYy9saWIvc2xpZGVyLWxpZ2h0Ym94L3NsaWRlci1saWdodGJveC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUgsU0FBUyxFQUlULE1BQU0sRUFHTixLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFDWixTQUFTLEVBQ1QsWUFBWSxFQUVmLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7QUFHM0MsTUFBTSxpQ0FBaUMsR0FBRyxlQUFlLEVBQ3JELGlDQUFpQyxHQUFHLG1CQUFtQixDQUFBO0FBTTNELE1BQU0sT0FBTyx1QkFBdUI7SUF1QmhDLElBQ0ksVUFBVSxDQUFDLEtBQWE7UUFDeEIsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUU7WUFDakUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQztTQUNsQztRQUNELElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBQ0QsSUFDSSxJQUFJLENBQUMsWUFBcUI7UUFDMUIsSUFBSSxDQUFDLG1CQUFtQixHQUFHLFlBQVksQ0FBQztRQUN4QyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO1FBQ2hFLElBQUksWUFBWSxLQUFL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O3NCQUF0QixLQUFLO2dCQUVGLGNBQWM7c0JBRGpCLEtBQUs7Z0JBU0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFHSSxLQUFLO3NCQUFkLE1BQU07Z0JBQ0csU0FBUztzQkFBbEIsTUFBTTtnQkFDRyxTQUFTO3NCQUFsQixNQUFNO2dCQUdQLFFBQVE7c0JBRFAsWUFBWTt1QkFBQyxlQUFlLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBTXpDLG1CQUFtQjtzQkFEbEIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQ29tcG9uZW50LFxuICAgIE9uSW5pdCxcbiAgICBPbkNoYW5nZXMsXG4gICAgU2ltcGxlQ2hhbmdlcyxcbiAgICBJbmplY3QsXG4gICAgQWZ0ZXJWaWV3SW5pdCxcbiAgICBPbkRlc3Ryb3ksXG4gICAgSW5wdXQsXG4gICAgT3V0cHV0LFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBWaWV3Q2hpbGQsXG4gICAgSG9zdExpc3RlbmVyLFxuICAgIEVsZW1lbnRSZWZcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBEb21TYW5pdGl6ZXIgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcblxuY29uc3QgTElHSFRCT1hfTkVYVF9BUlJPV19DTElDS19NRVNTQUdFID0gJ2xpZ2h0Ym94IG5leHQnLFx0XG4gICAgTElHSFRCT1hfUFJFVl9BUlJPV19DTElDS19NRVNTQUdFID0gJ2xpZ2h0Ym94IHByZXZpb3VzJ1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3NsaWRlci1saWdodGJveCcsXG4gICAgdGVtcGxhdGVVcmw6ICcuL3NsaWRlci1saWdodGJveC5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgU2xpZGVyTGlnaHRib3hDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gICAgdG90YWxJbWFnZXM6IG51bWJlciA9IDA7XG4gICAgbmV4dEltYWdlSW5kZXg6IG51bWJlciA9IC0xO1xuICAgIHBvcHVwV2lkdGg6IG51bWJlciA9IDEyMDA7XG4gICAgbWFyZ2luTGVmdDogbnVtYmVyID0gMDtcbiAgICBpbWFnZUZ1bGxzY3JlZW5WaWV3OiBib29sZWFuID0gZmFsc2U7XG4gICAgbGlnaHRib3hQcmV2RGlzYWJsZTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIGxpZ2h0Ym94TmV4dERpc2FibGU6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBzaG93TG9hZGluZzogYm9vbGVhbiA9IHRydWU7XG4gICAgZWZmZWN0U3R5bGU6IHN0cmluZyA9ICdub25lJztcbiAgICBzcGVlZDogbnVtYmVyID0gMTsgLy8gZGVmYXVsdCBzcGVlZCBpbiBzZWNvbmRcbiAgICB0aXRsZTogc3RyaW5nID0gJyc7XG4gICAgY3VycmVudEltYWdlSW5kZXg6IG51bWJlciA9IDA7XG5cbiAgICAvLyBmb3Igc3dpcGUgZXZlbnRcbiAgICBwcml2YXRlIHN3aXBlTGlnaHRib3hJbWdDb29yZD86IFtudW1iZXIsIG51bWJlcl07XG4gICAgcHJpdmF0ZSBzd2lwZUxpZ2h0Ym94SW1nVGltZT86IG51bWJlcjtcblxuICAgIEBWaWV3Q2hpbGQoJ2xpZ2h0Ym94RGl2JywgeyBzdGF0aWM6IGZhbHNlIH0pIGxpZ2h0Ym94RGl2O1xuICAgIEBWaWV3Q2hpbGQoJ2xpZ2h0Ym94SW1hZ2VEaXYnLCB7IHN0YXRpYzogZmFsc2UgfSkgbGlnaHRib3hJbWFnZURpdjtcblxuICAgIC8vIEBJbnB1dHNcbiAgICBASW5wdXQoKSBpbWFnZXM6IEFycmF5PG9iamVjdD4gPSBbXTtcbiAgICBASW5wdXQoKVxuICAgIHNldCBpbWFnZUluZGV4KGluZGV4OiBudW1iZXIpIHtcbiAgICAgICAgaWYgKGluZGV4ICE9PSB1bmRlZmluZWQgJiYgaW5kZXggPiAtMSAmJiBpbmRleCA8IHRoaXMuaW1hZ2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50SW1hZ2VJbmRleCA9IGluZGV4O1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubmV4dFByZXZEaXNhYmxlKCk7XG4gICAgfVxuICAgIEBJbnB1dCgpXG4gICAgc2V0IHNob3codmlzaWFibGVGbGFnOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuaW1hZ2VGdWxsc2NyZWVuVmlldyA9IHZpc2lhYmxlRmxhZztcbiAgICAgICAgdGhpcy5lbFJlZi5uYXRpdmVFbGVtZW50Lm93bmVyRG9jdW1lbnQuYm9keS5zdHlsZS5vdmVyZmxvdyA9ICcnO1xuICAgICAgICBpZiAodmlzaWFibGVGbGFnID09PSB0cnVlKSB7XG4gICAgICAgICAgICB0aGlzLmVsUmVmLm5hdGl2ZUVsZW1lbnQub3duZXJEb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbic7XG4gICAgICAgICAgICAvLyB0aGlzLmdldEltYWdlRGF0YSgpO1xuICAgICAgICAgICAgdGhpcy5zZXRQb3B1cFNsaWRlcldpZHRoKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQElucHV0KCkgdmlkZW9BdXRvUGxheTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIEBJbnB1dCgpIGRpcmVjdGlvbjogc3RyaW5nID0gJ2x0cic7XG4gICAgQElucHV0KCkgcGFnaW5hdGlvblNob3c6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBASW5wdXQoKVxuICAgIHNldCBhbmltYXRpb25TcGVlZChkYXRhOiBudW1iZXIpIHtcbiAgICAgICAgaWYgKGRhdGFcbiAgICAgICAgICAgICYmIHR5cGVvZiAoZGF0YSkgPT09ICdudW1iZXInXG4gICAgICAgICAgICAmJiBkYXRhID49IDAuMVxuICAgICAgICAgICAgJiYgZGF0YSA8PSA1KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVkID0gZGF0YTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBASW5wdXQoKSBpbmZpbml0ZTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIEBJbnB1dCgpIGFycm93S2V5TW92ZTogYm9vbGVhbiA9IHRydWU7XG4gICAgQElucHV0KCkgc2hvd1ZpZGVvQ29udHJvbHM6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLy8gQE91dHB1dFxuICAgIEBPdXRwdXQoKSBjbG9zZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICAgIEBPdXRwdXQoKSBwcmV2SW1hZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgICBAT3V0cHV0KCkgbmV4dEltYWdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJywgWyckZXZlbnQnXSlcbiAgICBvblJlc2l6ZShldmVudCkge1xuICAgICAgICB0aGlzLmVmZmVjdFN0eWxlID0gJ25vbmUnO1xuICAgICAgICB0aGlzLnNldFBvcHVwU2xpZGVyV2lkdGgoKTtcbiAgICB9XG4gICAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6a2V5dXAnLCBbJyRldmVudCddKVxuICAgIGhhbmRsZUtleWJvYXJkRXZlbnQoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50ICYmIGV2ZW50LmtleSAmJiB0aGlzLmFycm93S2V5TW92ZSkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmtleS50b0xvd2VyQ2FzZSgpID09PSAnYXJyb3dyaWdodCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm5leHRJbWFnZUxpZ2h0Ym94KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChldmVudC5rZXkudG9Mb3dlckNhc2UoKSA9PT0gJ2Fycm93bGVmdCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnByZXZJbWFnZUxpZ2h0Ym94KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChldmVudC5rZXkudG9Mb3dlckNhc2UoKSA9PT0gJ2VzY2FwZScpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsb3NlTGlnaHRib3goKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIGNkUmVmOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcixcbiAgICAgICAgcHJpdmF0ZSBlbFJlZjogRWxlbWVudFJlZixcbiAgICAgICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogYW55KSB7IH1cblxuICAgIG5nT25Jbml0KCkge1xuICAgIH1cblxuICAgIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5yZXNldFN0YXRlKCk7XG4gICAgfVxuXG4gICAgc2V0UG9wdXBTbGlkZXJXaWR0aCgpIHtcbiAgICAgICAgaWYgKHdpbmRvdyAmJiB3aW5kb3cuaW5uZXJXaWR0aCkge1xuICAgICAgICAgICAgdGhpcy5wb3B1cFdpZHRoID0gd2luZG93LmlubmVyV2lkdGg7XG4gICAgICAgICAgICB0aGlzLnRvdGFsSW1hZ2VzID0gdGhpcy5pbWFnZXMubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiAodGhpcy5jdXJyZW50SW1hZ2VJbmRleCkgPT09ICdudW1iZXInICYmIHRoaXMuY3VycmVudEltYWdlSW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubWFyZ2luTGVmdCA9IC0xICogdGhpcy5wb3B1cFdpZHRoICogdGhpcy5jdXJyZW50SW1hZ2VJbmRleDtcbiAgICAgICAgICAgICAgICB0aGlzLmdldEltYWdlRGF0YSgpO1xuICAgICAgICAgICAgICAgIHRoaXMubmV4dFByZXZEaXNhYmxlKCk7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2hvd0xvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9LCA1MDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xvc2VMaWdodGJveCgpIHtcbiAgICAgICAgdGhpcy5jbG9zZS5lbWl0KCk7XG4gICAgfVxuXG4gICAgcHJldkltYWdlTGlnaHRib3goKSB7XG4gICAgICAgIHRoaXMuZWZmZWN0U3R5bGUgPSBgYWxsICR7dGhpcy5zcGVlZH1zIGVhc2UtaW4tb3V0YDtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudEltYWdlSW5kZXggPiAwICYmICF0aGlzLmxpZ2h0Ym94UHJldkRpc2FibGUpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEltYWdlSW5kZXgtLTtcbiAgICAgICAgICAgIHRoaXMucHJldkltYWdlLmVtaXQoTElHSFRCT1hfUFJFVl9BUlJPV19DTElDS19NRVNTQUdFKTtcbiAgICAgICAgICAgIHRoaXMubWFyZ2luTGVmdCA9IC0xICogdGhpcy5wb3B1cFdpZHRoICogdGhpcy5jdXJyZW50SW1hZ2VJbmRleDtcbiAgICAgICAgICAgIHRoaXMuZ2V0SW1hZ2VEYXRhKCk7XG4gICAgICAgICAgICB0aGlzLm5leHRQcmV2RGlzYWJsZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmV4dEltYWdlTGlnaHRib3goKSB7XG4gICAgICAgIHRoaXMuZWZmZWN0U3R5bGUgPSBgYWxsICR7dGhpcy5zcGVlZH1zIGVhc2UtaW4tb3V0YDtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudEltYWdlSW5kZXggPCB0aGlzLmltYWdlcy5sZW5ndGggLSAxICYmICF0aGlzLmxpZ2h0Ym94TmV4dERpc2FibGUpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEltYWdlSW5kZXgrKztcbiAgICAgICAgICAgIHRoaXMubmV4dEltYWdlLmVtaXQoTElHSFRCT1hfTkVYVF9BUlJPV19DTElDS19NRVNTQUdFKTtcbiAgICAgICAgICAgIHRoaXMubWFyZ2luTGVmdCA9IC0xICogdGhpcy5wb3B1cFdpZHRoICogdGhpcy5jdXJyZW50SW1hZ2VJbmRleDtcbiAgICAgICAgICAgIHRoaXMuZ2V0SW1hZ2VEYXRhKCk7XG4gICAgICAgICAgICB0aGlzLm5leHRQcmV2RGlzYWJsZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmV4dFByZXZEaXNhYmxlKCkge1xuICAgICAgICB0aGlzLmxpZ2h0Ym94TmV4dERpc2FibGUgPSB0cnVlO1xuICAgICAgICB0aGlzLmxpZ2h0Ym94UHJldkRpc2FibGUgPSB0cnVlO1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuYXBwbHlCdXR0b25EaXNhYmxlQ29uZGl0aW9uKCk7XG4gICAgICAgIH0sIHRoaXMuc3BlZWQgKiAxMDAwKTtcbiAgICB9XG5cbiAgICBhcHBseUJ1dHRvbkRpc2FibGVDb25kaXRpb24oKSB7XG4gICAgICAgIHRoaXMubGlnaHRib3hOZXh0RGlzYWJsZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLmxpZ2h0Ym94UHJldkRpc2FibGUgPSBmYWxzZTtcbiAgICAgICAgaWYgKCF0aGlzLmluZmluaXRlICYmIHRoaXMuY3VycmVudEltYWdlSW5kZXggPj0gdGhpcy5pbWFnZXMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgdGhpcy5saWdodGJveE5leHREaXNhYmxlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuaW5maW5pdGUgJiYgdGhpcy5jdXJyZW50SW1hZ2VJbmRleCA8PSAwKSB7XG4gICAgICAgICAgICB0aGlzLmxpZ2h0Ym94UHJldkRpc2FibGUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0SW1hZ2VEYXRhKCkge1xuICAgICAgICBpZiAodGhpcy5pbWFnZXNcbiAgICAgICAgICAgICYmIHRoaXMuaW1hZ2VzLmxlbmd0aFxuICAgICAgICAgICAgJiYgdHlwZW9mICh0aGlzLmN1cnJlbnRJbWFnZUluZGV4KSA9PT0gJ251bWJlcidcbiAgICAgICAgICAgICYmIHRoaXMuY3VycmVudEltYWdlSW5kZXggIT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgJiYgdGhpcy5pbWFnZXNbdGhpcy5jdXJyZW50SW1hZ2VJbmRleF1cbiAgICAgICAgICAgICYmICh0aGlzLmltYWdlc1t0aGlzLmN1cnJlbnRJbWFnZUluZGV4XVsnaW1hZ2UnXSB8fCB0aGlzLmltYWdlc1t0aGlzLmN1cnJlbnRJbWFnZUluZGV4XVsndmlkZW8nXSkpIHtcbiAgICAgICAgICAgIHRoaXMudGl0bGUgPSB0aGlzLmltYWdlc1t0aGlzLmN1cnJlbnRJbWFnZUluZGV4XVsndGl0bGUnXSB8fCAnJztcbiAgICAgICAgICAgIHRoaXMudG90YWxJbWFnZXMgPSB0aGlzLmltYWdlcy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGlmcmFtZUkgaW4gdGhpcy5kb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaWZyYW1lJykpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaWZyYW1lJylbaWZyYW1lSV1cbiAgICAgICAgICAgICAgICAgICAgJiYgdGhpcy5kb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaWZyYW1lJylbaWZyYW1lSV0uY29udGVudFdpbmRvd1xuICAgICAgICAgICAgICAgICAgICAmJiB0aGlzLmRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpZnJhbWUnKVtpZnJhbWVJXS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2lmcmFtZScpW2lmcmFtZUldLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2UoJ3tcImV2ZW50XCI6XCJjb21tYW5kXCIsXCJmdW5jXCI6XCJwYXVzZVZpZGVvXCIsXCJhcmdzXCI6XCJcIn0nLCAnKicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoY29uc3QgdmlkZW9JIGluIHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3ZpZGVvJykpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgndmlkZW8nKVt2aWRlb0ldICYmIHRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3ZpZGVvJylbdmlkZW9JXS5wYXVzZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCd2aWRlbycpW3ZpZGVvSV0ucGF1c2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXNldFN0YXRlKCkge1xuICAgICAgICB0aGlzLmltYWdlcyA9IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN3aXBlIGV2ZW50IGhhbmRsZXJcbiAgICAgKiBSZWZlcmVuY2UgZnJvbSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNDQ1MTEwMDcvMjA2NzY0NlxuICAgICAqL1xuICAgIHN3aXBlTGlnaHRib3hJbWcoZTogVG91Y2hFdmVudCwgd2hlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvb3JkOiBbbnVtYmVyLCBudW1iZXJdID0gW2UuY2hhbmdlZFRvdWNoZXNbMF0ucGFnZVgsIGUuY2hhbmdlZFRvdWNoZXNbMF0ucGFnZVldO1xuICAgICAgICBjb25zdCB0aW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgaWYgKHdoZW4gPT09ICdzdGFydCcpIHtcbiAgICAgICAgICAgIHRoaXMuc3dpcGVMaWdodGJveEltZ0Nvb3JkID0gY29vcmQ7XG4gICAgICAgICAgICB0aGlzLnN3aXBlTGlnaHRib3hJbWdUaW1lID0gdGltZTtcbiAgICAgICAgfSBlbHNlIGlmICh3aGVuID09PSAnZW5kJykge1xuICAgICAgICAgICAgY29uc3QgZGlyZWN0aW9uID0gW2Nvb3JkWzBdIC0gdGhpcy5zd2lwZUxpZ2h0Ym94SW1nQ29vcmRbMF0sIGNvb3JkWzFdIC0gdGhpcy5zd2lwZUxpZ2h0Ym94SW1nQ29vcmRbMV1dO1xuICAgICAgICAgICAgY29uc3QgZHVyYXRpb24gPSB0aW1lIC0gdGhpcy5zd2lwZUxpZ2h0Ym94SW1nVGltZTtcblxuICAgICAgICAgICAgaWYgKGR1cmF0aW9uIDwgMTAwMCAvL1xuICAgICAgICAgICAgICAgICYmIE1hdGguYWJzKGRpcmVjdGlvblswXSkgPiAzMCAvLyBMb25nIGVub3VnaFxuICAgICAgICAgICAgICAgICYmIE1hdGguYWJzKGRpcmVjdGlvblswXSkgPiBNYXRoLmFicyhkaXJlY3Rpb25bMV0gKiAzKSkgeyAvLyBIb3Jpem9udGFsIGVub3VnaFxuICAgICAgICAgICAgICAgIGlmIChkaXJlY3Rpb25bMF0gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubmV4dEltYWdlTGlnaHRib3goKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXZJbWFnZUxpZ2h0Ym94KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuIiwiPGRpdiAqbmdJZj1cImltYWdlRnVsbHNjcmVlblZpZXdcIiBjbGFzcz1cIm5nLWltYWdlLWZ1bGxzY3JlZW4tdmlld1wiPlxuICAgIDxkaXYgY2xhc3M9XCJsaWdodGJveC13cmFwcGVyXCI+XG4gICAgICAgIDxhIGNsYXNzPVwiY2xvc2VcIiAoY2xpY2spPVwiY2xvc2VMaWdodGJveCgpXCI+PC9hPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibGlnaHRib3gtZGl2XCIgI2xpZ2h0Ym94RGl2PlxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cInNob3dMb2FkaW5nXCIgY2xhc3M9XCJwcmUtbG9hZGVyXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1ubWwtc3Bpbm5lclwiPjwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGlnaHRib3gtaW1hZ2UtbWFpblwiXG4gICAgICAgICAgICAgICAgW25nU3R5bGVdPVwieydtYXJnaW4tbGVmdCc6IG1hcmdpbkxlZnQgKyAncHgnLCAnZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zJzogJ3JlcGVhdCgnK2ltYWdlcy5sZW5ndGgrJywxZnIpJywgJ3RyYW5zaXRpb24nOiBlZmZlY3RTdHlsZX1cIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGlnaHRib3gtaW1hZ2VcIlxuICAgICAgICAgICAgICAgICAgICBbbmdTdHlsZV09XCJ7J3dpZHRoJzogcG9wdXBXaWR0aCArICdweCd9XCJcbiAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGltZyBvZiBpbWFnZXM7IGxldCBpID0gaW5kZXhcIlxuICAgICAgICAgICAgICAgICAgICBbYXR0ci5pZF09XCInbmctbGlnaHRib3gtaW1hZ2UtJyArIGlcIlxuICAgICAgICAgICAgICAgICAgICAodG91Y2hzdGFydCk9XCJzd2lwZUxpZ2h0Ym94SW1nKCRldmVudCwgJ3N0YXJ0JylcIlxuICAgICAgICAgICAgICAgICAgICAodG91Y2hlbmQpPVwic3dpcGVMaWdodGJveEltZygkZXZlbnQsICdlbmQnKVwiXG4gICAgICAgICAgICAgICAgICAgICNsaWdodGJveEltYWdlRGl2PlxuICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjbG9zZS1vdXRzaWRlXCIgKGNsaWNrKT1cIiFpbWc/LnZpZGVvICYmIGNsb3NlTGlnaHRib3goKVwiPjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8Y3VzdG9tLWltZ1xuICAgICAgICAgICAgICAgICAgICAgICAgW2ltYWdlVXJsXT1cImltZz8uaW1hZ2UgfHwgaW1nPy52aWRlb1wiXG4gICAgICAgICAgICAgICAgICAgICAgICBbaXNWaWRlb109XCIhIShpbWc/LnBvc3RlckltYWdlIHx8IGltZz8udmlkZW8pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtjdXJyZW50SW1hZ2VJbmRleF09XCJjdXJyZW50SW1hZ2VJbmRleFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbaW1hZ2VJbmRleF09XCJpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtzcGVlZF09XCJzcGVlZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbdmlkZW9BdXRvUGxheV09XCJ2aWRlb0F1dG9QbGF5ICYmIGkgPT0gY3VycmVudEltYWdlSW5kZXhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW3Nob3dWaWRlb0NvbnRyb2xzXT1cInNob3dWaWRlb0NvbnRyb2xzID8gMSA6IDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2FsdF09XCJpbWc/LmFsdCB8fCBpbWc/LnRpdGxlIHx8ICcnXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFt0aXRsZV09XCJpbWc/LnRpdGxlIHx8IGltZz8uYWx0IHx8ICcnXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtzaG93VmlkZW9dPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbZGlyZWN0aW9uXT1cImRpcmVjdGlvblwiPlxuICAgICAgICAgICAgICAgICAgICA8L2N1c3RvbS1pbWc+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgW2Rpcl09XCJkaXJlY3Rpb25cIiBbbmdDbGFzc109XCJ7J3Nob3cnOiB0aXRsZSwgJ2hpZGUnOiAhdGl0bGV9XCIgY2xhc3M9XCJjYXB0aW9uXCI+e3sgdGl0bGUgfX08L2Rpdj5cbiAgICAgICAgICAgIDxhICpuZ0lmPVwiaW1hZ2VzLmxlbmd0aCA+IDFcIiBbbmdDbGFzc109XCJ7J2Rpc2FibGUnOiBsaWdodGJveFByZXZEaXNhYmxlfVwiIGNsYXNzPVwicHJldiBpY29ucyBwcmV2LWljb25cIiAoY2xpY2spPVwicHJldkltYWdlTGlnaHRib3goKVwiPiZsc2FxdW87PC9hPlxuICAgICAgICAgICAgPGEgKm5nSWY9XCJpbWFnZXMubGVuZ3RoID4gMVwiIFtuZ0NsYXNzXT1cInsnZGlzYWJsZSc6IGxpZ2h0Ym94TmV4dERpc2FibGV9XCIgY2xhc3M9XCJuZXh0IGljb25zIG5leHQtaWNvblwiIChjbGljayk9XCJuZXh0SW1hZ2VMaWdodGJveCgpXCI+JnJzYXF1bzs8L2E+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDxkaXYgKm5nSWY9XCJwYWdpbmF0aW9uU2hvd1wiIGNsYXNzPVwicG9wdXAtcGFnaW5hdGlvblwiPnt7Y3VycmVudEltYWdlSW5kZXggKyAxfX0gb2Yge3t0b3RhbEltYWdlc319PC9kaXY+XG48L2Rpdj5cbiJdfQ==