slider-carousel
Version:
Angular component of the carousel, using the slider as a transition. This is a simple, clean and light alternative. It also does not need dependencies.
334 lines • 53 kB
JavaScript
import { Component, OnInit, HostBinding, Input, ElementRef, ViewChild, OnDestroy, OnChanges, Renderer2, AfterViewChecked } from '@angular/core';
import { DomSanitizer, SafeUrl, SafeStyle } from '@angular/platform-browser';
import { Helper } from './helper';
export class SliderCarouselComponent {
constructor(sanitizer, renderer, helper) {
this.sanitizer = sanitizer;
this.renderer = renderer;
this.helper = helper;
this.class = true;
this.images = [];
this.preview = true;
this.height = '500px';
this.width = '100%';
this.maxWidth = '100%';
this.autoSize = false;
this.safeImages = [];
this.initialized = false;
this.currentImageIndex = 0;
this.lastDirectionIsRight = false;
this.containerWidth = 0;
this.destroyed = false;
this.windowResizing = false;
this.listeners = [];
this.drag = {
state: 'none',
startOffset: 0,
currentOffset: 0,
startLeft: 0,
currentLeft: 0,
};
}
get currentImage() { return this.safeImages[this.currentImageIndex]; }
get currentIsFisrt() { return this.currentImageIndex === 0; }
get currentIsLast() { return this.currentImageIndex === (this.images.length - 1); }
get isDragging() { return this.drag.state !== 'none'; }
ngOnInit() {
}
ngOnChanges() {
this.prepare();
}
prepare() {
if (typeof this.height !== 'string')
this.height = '500px';
else if (!this.height.endsWith('%') && !this.height.endsWith('px'))
this.height += 'px';
if (typeof this.width !== 'string')
this.width = '100%';
else if (!this.width.endsWith('%') && !this.width.endsWith('px'))
this.width += 'px';
if (typeof this.maxWidth !== 'string')
this.maxWidth = '100%';
else if (!this.maxWidth.endsWith('%') && !this.maxWidth.endsWith('px'))
this.maxWidth += 'px';
this.initialized = true;
this.checkImages();
this.initSlideDragWatching();
this.ngAfterViewChecked();
}
ngAfterViewChecked() {
if (!this.windowResizing) {
let width = 0;
if (this.sectionEl && this.sectionEl.nativeElement)
width = this.sectionEl.nativeElement.clientWidth;
if (width !== this.containerWidth)
this.containerWidth = width;
}
}
checkImages() {
if (this.images && this.images.length) {
if (typeof this.images[0] !== 'string') {
this.images.forEach((image) => {
if (!image.md)
image.md = image.lg;
if (!image.sm)
image.sm = image.md;
});
}
else {
this.images = this.images.map((image) => {
return { lg: image, md: image, sm: image };
});
}
this.safeImages = this.images.map((image) => {
var _a, _b, _c, _d, _e, _f;
let sizes = {
lg: {
url: ((_a = image.lg) === null || _a === void 0 ? void 0 : _a.startsWith('http')) ? this.sanitizer.bypassSecurityTrustUrl(image.lg) : image.lg,
style: ((_b = image.lg) === null || _b === void 0 ? void 0 : _b.startsWith('http')) ? this.sanitizer.bypassSecurityTrustStyle(`url('${image.lg}')`) : `url('${image.lg}')`,
pure: image.lg
},
md: {
url: ((_c = image.md) === null || _c === void 0 ? void 0 : _c.startsWith('http')) ? this.sanitizer.bypassSecurityTrustUrl(image.md) : image.md,
style: ((_d = image.md) === null || _d === void 0 ? void 0 : _d.startsWith('http')) ? this.sanitizer.bypassSecurityTrustStyle(`url('${image.md}')`) : `url('${image.md}')`,
pure: image.md
},
sm: {
url: ((_e = image.sm) === null || _e === void 0 ? void 0 : _e.startsWith('http')) ? this.sanitizer.bypassSecurityTrustUrl(image.sm) : image.sm,
style: ((_f = image.sm) === null || _f === void 0 ? void 0 : _f.startsWith('http')) ? this.sanitizer.bypassSecurityTrustStyle(`url('${image.sm}')`) : `url('${image.sm}')`,
pure: image.sm
}
};
return sizes;
});
}
else {
this.safeImages = [];
}
}
initSlideDragWatching() {
if (this.innerImagesEl && this.innerImagesEl.nativeElement) {
this.stopSlideDragWatching();
if (this.helper.isMobileDevice())
this.listeners = [
this.renderer.listen(document.body, 'touchstart', this.onStartDrag.bind(this)),
this.renderer.listen(document.body, 'touchmove', this.onDragging.bind(this)),
this.renderer.listen(document.body, 'touchend', this.onEndDrag.bind(this))
];
else
this.listeners = [
this.renderer.listen(document.body, 'mousedown', this.onStartDrag.bind(this)),
this.renderer.listen(document.body, 'mousemove', this.onDragging.bind(this)),
this.renderer.listen(document.body, 'mouseup', this.onEndDrag.bind(this)),
];
}
else
setTimeout(() => this.initSlideDragWatching(), 200);
}
stopSlideDragWatching() {
if (this.listeners && this.listeners.length)
this.listeners.forEach((unListen) => unListen());
}
previewImage(image) {
if (!this.previewRef) {
this.previewRef = this.helper.openPreview({
image: {
pureUrl: image.lg.pure,
safeUrl: image.lg.url,
}
});
this.previewRef.onClose.subscribe(() => this.previewRef = null);
}
}
selectImage(imageIndex, event) {
if (imageIndex !== this.currentImageIndex) {
this.lastDirectionIsRight = imageIndex > this.currentImageIndex;
this.currentImageIndex = imageIndex;
if (event.target && this.imageListEl && this.imageListEl.nativeElement)
this.scrollingToElement(event.target, this.lastDirectionIsRight);
}
}
goPrevImage(salt = 0) {
if (this.currentImageIndex > 0) {
if (salt) {
if ((this.currentImageIndex - salt) >= 0)
this.currentImageIndex -= salt + 1;
else
this.currentImageIndex = 0;
}
else
this.currentImageIndex--;
this.lastDirectionIsRight = false;
let target = this.imageListEl.nativeElement.children[0].children[this.currentImageIndex];
if (this.imageListEl && this.imageListEl.nativeElement)
this.scrollingToElement(target, this.lastDirectionIsRight);
}
}
goNextImage(salt = 0) {
if ((this.currentImageIndex + 1) < this.images.length) {
if (salt) {
if ((this.currentImageIndex + salt + 1) <= (this.images.length - 1))
this.currentImageIndex = salt + 1;
else
this.currentImageIndex = this.images.length;
}
else
this.currentImageIndex++;
this.lastDirectionIsRight = true;
let target = this.imageListEl.nativeElement.children[0].children[this.currentImageIndex];
if (this.imageListEl && this.imageListEl.nativeElement)
this.scrollingToElement(target, this.lastDirectionIsRight);
}
}
scrollingToElement(element, directionIsRight) {
let scrollElement = this.imageListEl.nativeElement;
if (scrollElement && scrollElement.scrollWidth > 0) {
let blockWidth = element.clientWidth + 14;
let scrollLeft = element.offsetLeft - 14;
let scrollRight = element.offsetLeft + element.clientWidth + 14;
let currentScrollLeft = scrollElement.scrollLeft;
let currentScrollRight = scrollElement.scrollLeft + scrollElement.clientWidth;
let scroll = .1;
if (directionIsRight && (currentScrollRight - scrollRight) < Math.floor(blockWidth / 2))
scroll = currentScrollLeft + blockWidth + 100;
else if (!directionIsRight && (scrollLeft - currentScrollLeft) < Math.floor(blockWidth / 2))
scroll = currentScrollLeft - blockWidth;
if (scroll !== .1) {
if (this.timerSroll)
clearInterval(this.timerSroll);
this.timerSroll = this.helper.smoothScroll(scrollElement, scroll, 400, 'left');
}
}
}
onKeydown(event) {
if (!this.destroyed && !this.isDragging && [37, 39].indexOf(event.keyCode) >= 0) {
if (event.keyCode === 37)
this.goPrevImage();
else
this.goNextImage();
if (this.previewRef)
this.previewRef.instance.onImageChange({
pureUrl: this.currentImage.lg.pure,
safeUrl: this.currentImage.lg.url,
});
}
}
onWindowResize() {
if (!this.destroyed && !this.windowResizing) {
this.windowResizing = true;
setTimeout(() => {
this.containerWidth = this.sectionEl.nativeElement.clientWidth;
setTimeout(() => {
this.windowResizing = false;
setTimeout(() => {
if (this.imageListEl && this.imageListEl.nativeElement) {
let target = this.imageListEl.nativeElement.children[0].children[this.currentImageIndex];
if (this.imageListEl && this.imageListEl.nativeElement)
this.scrollingToElement(target, this.lastDirectionIsRight);
}
}, 100);
});
});
}
}
onStartDrag(event) {
let isTouching = false;
if (event.touches) {
isTouching = true;
event = event.touches[0];
}
if (isTouching || event.button === 0) {
if (this.helper.elementIsChild(event.target, this.sectionEl.nativeElement)) {
this.drag.startLeft = this.innerImagesEl.nativeElement.offsetLeft;
this.drag.currentLeft = this.innerImagesEl.nativeElement.offsetLeft;
this.drag.startOffset = event.clientX;
this.drag.currentOffset = event.clientX;
this.drag.state = 'start';
}
}
}
onDragging(event) {
if (event.touches)
event = event.touches[0];
if (this.drag.state === 'start' || this.drag.state === 'dragging') {
this.drag.state = 'dragging';
this.drag.currentOffset = event.clientX;
if (this.drag.startOffset !== this.drag.currentOffset) {
let draggingRight = this.drag.currentOffset > this.drag.startOffset;
let delta = Math.abs(this.drag.currentOffset - this.drag.startOffset) * .8;
if (((draggingRight && this.currentIsFisrt) || (!draggingRight && this.currentIsLast)) && delta > Math.floor(this.containerWidth / 3))
delta = Math.floor(this.containerWidth / 3);
this.drag.currentLeft = this.drag.startLeft + ((draggingRight ? 1 : -1) * delta);
}
else
this.drag.currentLeft = this.drag.startLeft;
}
}
onEndDrag(event) {
let isTouching = false;
if (event.touches) {
isTouching = true;
event = event.touches[0];
}
if (isTouching || event.button === 0) {
let amountDragged = Math.abs(this.drag.startOffset - this.drag.currentOffset);
if (this.drag.state === 'dragging' && amountDragged > 0)
setTimeout(() => {
this.drag.state = 'none';
let minDreg = 70;
if (amountDragged >= minDreg) {
let draggingRight = this.drag.currentOffset > this.drag.startOffset;
let salts = (amountDragged / this.sectionEl.nativeElement.clientWidth) - 1;
if (salts >= 1)
salts = Math.floor(salts);
else
salts = 0;
if (draggingRight && !this.currentIsFisrt)
this.goPrevImage(salts);
else if (!draggingRight && !this.currentIsLast)
this.goNextImage(salts);
}
});
else {
this.drag.state = 'none';
}
}
}
ngOnDestroy() {
this.destroyed = true;
this.stopSlideDragWatching();
}
}
SliderCarouselComponent.ctorParameters = () => [
{ type: DomSanitizer },
{ type: Renderer2 },
{ type: Helper }
];
SliderCarouselComponent.decorators = [
{ type: Component, args: [{
selector: 'slider-carousel',
template: "<section #section *ngIf=\"safeImages && safeImages.length\" [style.width]=\"width\" [style.maxWidth]=\"maxWidth\">\n <div *ngIf=\"!windowResizing && containerWidth > 0\" class=\"image-controller animated fadeIn\" [style.maxWidth.px]=\"containerWidth\">\n\n <!-- INNER CONTAINER -->\n <ul #innerImages *ngIf=\"!autoSize\"\n [ngClass]=\"{'dragging-effect': isDragging}\"\n\t\t\t[style.left.px]=\"isDragging ? drag.currentLeft : (-currentImageIndex * containerWidth)\"\n\t\t\t[style.width.px]=\"safeImages.length * containerWidth\"\n [style.height]=\"height\">\n <li *ngFor=\"let image of safeImages; let i = index;\"\n [style.backgroundImage]=\"image.md.style\"\n [style.width.px]=\"containerWidth\"\n [ngClass]=\"{'cursor-pointer': preview, 'is-current': i === currentImageIndex}\"\n (click)=\"!isDragging && previewImage(image)\">\n </li>\n </ul>\n <ul #innerImages *ngIf=\"autoSize\" [ngClass]=\"{'dragging-effect': isDragging}\" [style.left.px]=\"isDragging ? drag.currentLeft : (-currentImageIndex * containerWidth)\">\n <div *ngFor=\"let image of safeImages; let i = index;\" [style.width.px]=\"containerWidth\">\n\t\t\t\t<img [src]=\"image.md.url\" draggable=\"false\" [ngClass]=\"{'cursor-pointer': preview, 'is-current': i === currentImageIndex}\" (click)=\"!isDragging && previewImage(image)\"/>\n </div>\n </ul>\n\n <!-- NAVIGATION BUTTONS -->\n <div (click)=\"goPrevImage()\" class=\"image-controller-prev\" [ngClass]=\"{'disabled': currentImageIndex <= 0}\" role=\"button\">\n <svg viewBox=\"0 0 456 456\">\n <path d=\"M227.996,0C102.081,0,0,102.081,0,227.996c0,125.945,102.081,227.996,227.996,227.996\n\t\t\t\tc125.945,0,227.996-102.051,227.996-227.996C455.992,102.081,353.941,0,227.996,0z M299.435,238.788l-98.585,98.585\n\t\t\t\tc-5.928,5.897-15.565,5.897-21.492,0c-5.928-5.928-5.928-15.595,0-21.492l87.885-87.885l-87.885-87.885\n\t\t\t\tc-5.928-5.928-5.928-15.565,0-21.492s15.565-5.928,21.492,0l98.585,98.585c3.04,2.979,4.469,6.901,4.438,10.792\n\t\t\t\tC303.873,231.918,302.414,235.809,299.435,238.788z\"/>\n </svg> \n </div>\n <div (click)=\"goNextImage()\" class=\"image-controller-next\" [ngClass]=\"{'disabled': (currentImageIndex + 1) >= safeImages.length}\" role=\"button\">\n <svg viewBox=\"0 0 456 456\">\n <path d=\"M227.996,0C102.081,0,0,102.081,0,227.996c0,125.945,102.081,227.996,227.996,227.996\n\t\t\t\tc125.945,0,227.996-102.051,227.996-227.996C455.992,102.081,353.941,0,227.996,0z M299.435,238.788l-98.585,98.585\n\t\t\t\tc-5.928,5.897-15.565,5.897-21.492,0c-5.928-5.928-5.928-15.595,0-21.492l87.885-87.885l-87.885-87.885\n\t\t\t\tc-5.928-5.928-5.928-15.565,0-21.492s15.565-5.928,21.492,0l98.585,98.585c3.04,2.979,4.469,6.901,4.438,10.792\n\t\t\t\tC303.873,231.918,302.414,235.809,299.435,238.788z\"/>\n </svg> \n </div>\n\n </div>\n\n <!-- GALLERY NAVIGATION -->\n <div *ngIf=\"!windowResizing && containerWidth > 0\" #imageList class=\"footer-images animated fadeIn\" [style.maxWidth.px]=\"containerWidth\">\n <ul>\n <li matRipple (click)=\"selectImage(i, $event)\" *ngFor=\"let image of safeImages; let i = index;\"\n [ngClass]=\"{'is-current': i === currentImageIndex}\"\n [style.backgroundImage]=\"image.sm.style\">\n </li>\n </ul>\n </div>\n</section>",
host: {
'(document:keydown)': 'onKeydown($event)',
'(window:resize)': 'onWindowResize()'
}
},] }
];
SliderCarouselComponent.ctorParameters = () => [
{ type: DomSanitizer },
{ type: Renderer2 },
{ type: Helper }
];
SliderCarouselComponent.propDecorators = {
class: [{ type: HostBinding, args: ['class.slider-carousel',] }],
sectionEl: [{ type: ViewChild, args: ['section',] }],
imageListEl: [{ type: ViewChild, args: ['imageList',] }],
innerImagesEl: [{ type: ViewChild, args: ['innerImages',] }],
images: [{ type: Input }],
preview: [{ type: Input }],
height: [{ type: Input }],
width: [{ type: Input }],
maxWidth: [{ type: Input, args: ['max-width',] }],
autoSize: [{ type: Input, args: ['auto-size',] }]
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xpZGVyLWNhcm91c2VsLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL3NsaWRlci1jYXJvdXNlbC8iLCJzb3VyY2VzIjpbInNsaWRlci1jYXJvdXNlbC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hKLE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRzdFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFVbEMsTUFBTSxPQUFPLHVCQUF1QjtJQW9EbkMsWUFDUyxTQUF1QixFQUN2QixRQUFtQixFQUNuQixNQUFjO1FBRmQsY0FBUyxHQUFULFNBQVMsQ0FBYztRQUN2QixhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQ25CLFdBQU0sR0FBTixNQUFNLENBQVE7UUF0RHNCLFVBQUssR0FBWSxJQUFJLENBQUM7UUFNbkQsV0FBTSxHQUEwRCxFQUFFLENBQUM7UUFFbkUsWUFBTyxHQUFZLElBQUksQ0FBQztRQUN4QixXQUFNLEdBQVcsT0FBTyxDQUFDO1FBQ3pCLFVBQUssR0FBVyxNQUFNLENBQUM7UUFDWixhQUFRLEdBQVcsTUFBTSxDQUFDO1FBQzFCLGFBQVEsR0FBWSxLQUFLLENBQUM7UUFFOUMsZUFBVSxHQUlYLEVBQUUsQ0FBQztRQUVGLGdCQUFXLEdBQVksS0FBSyxDQUFDO1FBRTdCLHNCQUFpQixHQUFXLENBQUMsQ0FBQztRQUM5Qix5QkFBb0IsR0FBWSxLQUFLLENBQUM7UUFJdEMsbUJBQWMsR0FBVyxDQUFDLENBQUM7UUFFMUIsY0FBUyxHQUFZLEtBQUssQ0FBQztRQUM1QixtQkFBYyxHQUFZLEtBQUssQ0FB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LG8vR0FBK0M7Z0JBQy9DLElBQUksRUFBRTtvQkFDTCxvQkFBb0IsRUFBRSxtQkFBbUI7b0JBQ3pDLGlCQUFpQixFQUFFLGtCQUFrQjtpQkFDckM7YUFDRDs7O1lBWlEsWUFBWTtZQUR3RSxTQUFTO1lBSTdGLE1BQU07OztvQkFXYixXQUFXLFNBQUMsdUJBQXVCO3dCQUVuQyxTQUFTLFNBQUMsU0FBUzswQkFDbkIsU0FBUyxTQUFDLFdBQVc7NEJBQ3JCLFNBQVMsU0FBQyxhQUFhO3FCQUV2QixLQUFLO3NCQUVMLEtBQUs7cUJBQ0wsS0FBSztvQkFDTCxLQUFLO3VCQUNMLEtBQUssU0FBQyxXQUFXO3VCQUNqQixLQUFLLFNBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBIb3N0QmluZGluZywgSW5wdXQsIEVsZW1lbnRSZWYsIFZpZXdDaGlsZCwgT25EZXN0cm95LCBPbkNoYW5nZXMsIFJlbmRlcmVyMiwgQWZ0ZXJWaWV3Q2hlY2tlZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRG9tU2FuaXRpemVyLCBTYWZlVXJsLCBTYWZlU3R5bGUgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFNsaWRlckNhcm91c2VsUHJldmlld0NvbXBvbmVudCB9IGZyb20gJy4vc2xpZGVyLWNhcm91c2VsLXByZXZpZXcvc2xpZGVyLWNhcm91c2VsLXByZXZpZXcuY29tcG9uZW50JztcbmltcG9ydCB7IEhlbHBlciB9IGZyb20gJy4vaGVscGVyJztcblxuQENvbXBvbmVudCh7XG5cdHNlbGVjdG9yOiAnc2xpZGVyLWNhcm91c2VsJyxcblx0dGVtcGxhdGVVcmw6ICcuL3NsaWRlci1jYXJvdXNlbC5jb21wb25lbnQuaHRtbCcsXG5cdGhvc3Q6IHtcblx0XHQnKGRvY3VtZW50OmtleWRvd24pJzogJ29uS2V5ZG93bigkZXZlbnQpJyxcblx0XHQnKHdpbmRvdzpyZXNpemUpJzogJ29uV2luZG93UmVzaXplKCknXG5cdH1cbn0pXG5leHBvcnQgY2xhc3MgU2xpZGVyQ2Fyb3VzZWxDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95LCBBZnRlclZpZXdDaGVja2VkIHtcblx0QEhvc3RCaW5kaW5nKCdjbGFzcy5zbGlkZXItY2Fyb3VzZWwnKSBwdWJsaWMgY2xhc3M6IGJvb2xlYW4gPSB0cnVlO1xuXG5cdEBWaWV3Q2hpbGQoJ3NlY3Rpb24nKSBwcml2YXRlIHNlY3Rpb25FbDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG5cdEBWaWV3Q2hpbGQoJ2ltYWdlTGlzdCcpIHByaXZhdGUgaW1hZ2VMaXN0RWw6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuXHRAVmlld0NoaWxkKCdpbm5lckltYWdlcycpIHByaXZhdGUgaW5uZXJJbWFnZXNFbDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG5cblx0QElucHV0KCkgcHVibGljIGltYWdlczogeyBsZzogc3RyaW5nLCBtZD86IHN0cmluZywgc20/OiBzdHJpbmcgfVtdIHwgc3RyaW5nW10gPSBbXTtcblxuXHRASW5wdXQoKSBwdWJsaWMgcHJldmlldzogYm9vbGVhbiA9IHRydWU7XG5cdEBJbnB1dCgpIHB1YmxpYyBoZWlnaHQ6IHN0cmluZyA9ICc1MDBweCc7XG5cdEBJbnB1dCgpIHB1YmxpYyB3aWR0aDogc3RyaW5nID0gJzEwMCUnO1xuXHRASW5wdXQoJ21heC13aWR0aCcpIHB1YmxpYyBtYXhXaWR0aDogc3RyaW5nID0gJzEwMCUnO1xuXHRASW5wdXQoJ2F1dG8tc2l6ZScpIHB1YmxpYyBhdXRvU2l6ZTogYm9vbGVhbiA9IGZhbHNlO1xuXG5cdHB1YmxpYyBzYWZlSW1hZ2VzOiB7XG5cdFx0bGc6IHsgdXJsOiBTYWZlVXJsIHwgc3RyaW5nLCBzdHlsZTogU2FmZVN0eWxlIHwgc3RyaW5nLCBwdXJlOiBzdHJpbmcgfSxcblx0XHRtZDogeyB1cmw6IFNhZmVVcmwgfCBzdHJpbmcsIHN0eWxlOiBTYWZlU3R5bGUgfCBzdHJpbmcsIHB1cmU6IHN0cmluZyB9LFxuXHRcdHNtOiB7IHVybDogU2FmZVVybCB8IHN0cmluZywgc3R5bGU6IFNhZmVTdHlsZSB8IHN0cmluZywgcHVyZTogc3RyaW5nIH1cblx0fVtdID0gW107XG5cblx0cHVibGljIGluaXRpYWxpemVkOiBib29sZWFuID0gZmFsc2U7XG5cblx0cHVibGljIGN1cnJlbnRJbWFnZUluZGV4OiBudW1iZXIgPSAwO1xuXHRwdWJsaWMgbGFzdERpcmVjdGlvbklzUmlnaHQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuXHRwcml2YXRlIHRpbWVyU3JvbGw6IGFueTtcblxuXHRwdWJsaWMgY29udGFpbmVyV2lkdGg6IG51bWJlciA9IDA7XG5cblx0cHJpdmF0ZSBkZXN0cm95ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblx0cHVibGljIHdpbmRvd1Jlc2l6aW5nOiBib29sZWFuID0gZmFsc2U7XG5cdHByaXZhdGUgcHJldmlld1JlZjoge1xuXHRcdG9uQ2xvc2U6IE9ic2VydmFibGU8YW55Pixcblx0XHRpbnN0YW5jZTogU2xpZGVyQ2Fyb3VzZWxQcmV2aWV3Q29tcG9uZW50XG5cdH07XG5cblx0cHJpdmF0ZSBsaXN0ZW5lcnM6ICgoKSA9PiB2b2lkKVtdID0gW107XG5cblx0cHVibGljIGdldCBjdXJyZW50SW1hZ2UoKSB7IHJldHVybiB0aGlzLnNhZmVJbWFnZXNbdGhpcy5jdXJyZW50SW1hZ2VJbmRleF07IH1cblx0cHVibGljIGdldCBjdXJyZW50SXNGaXNydCgpIHsgcmV0dXJuIHRoaXMuY3VycmVudEltYWdlSW5kZXggPT09IDA7IH1cblx0cHVibGljIGdldCBjdXJyZW50SXNMYXN0KCkgeyByZXR1cm4gdGhpcy5jdXJyZW50SW1hZ2VJbmRleCA9PT0gKHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDEpOyB9XG5cblx0cHVibGljIGdldCBpc0RyYWdnaW5nKCkgeyByZXR1cm4gdGhpcy5kcmFnLnN0YXRlICE9PSAnbm9uZSc7IH1cblx0cHVibGljIGRyYWcgPSB7XG5cdFx0c3RhdGU6ICdub25lJywgLy8gJ3N0YXJ0JywgJ2RyYWdnaW5nJywgJ25vbmUnXG5cdFx0c3RhcnRPZmZzZXQ6IDAsXG5cdFx0Y3VycmVudE9mZnNldDogMCxcblx0XHRzdGFydExlZnQ6IDAsXG5cdFx0Y3VycmVudExlZnQ6IDAsXG5cdH07XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0cHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcixcblx0XHRwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG5cdFx0cHJpdmF0ZSBoZWxwZXI6IEhlbHBlclxuXHQpIHtcblx0fVxuXG5cdG5nT25Jbml0KCkge1xuXHR9XG5cblx0bmdPbkNoYW5nZXMoKSB7XG5cdFx0dGhpcy5wcmVwYXJlKCk7XG5cdH1cblxuXHRwcml2YXRlIHByZXBhcmUoKSB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzLmhlaWdodCAhPT0gJ3N0cmluZycpXG5cdFx0XHR0aGlzLmhlaWdodCA9ICc1MDBweCc7XG5cdFx0ZWxzZSBpZiAoIXRoaXMuaGVpZ2h0LmVuZHNXaXRoKCclJykgJiYgIXRoaXMuaGVpZ2h0LmVuZHNXaXRoKCdweCcpKVxuXHRcdFx0dGhpcy5oZWlnaHQgKz0gJ3B4JztcblxuXHRcdGlmICh0eXBlb2YgdGhpcy53aWR0aCAhPT0gJ3N0cmluZycpXG5cdFx0XHR0aGlzLndpZHRoID0gJzEwMCUnO1xuXHRcdGVsc2UgaWYgKCF0aGlzLndpZHRoLmVuZHNXaXRoKCclJykgJiYgIXRoaXMud2lkdGguZW5kc1dpdGgoJ3B4JykpXG5cdFx0XHR0aGlzLndpZHRoICs9ICdweCc7XG5cblx0XHRpZiAodHlwZW9mIHRoaXMubWF4V2lkdGggIT09ICdzdHJpbmcnKVxuXHRcdFx0dGhpcy5tYXhXaWR0aCA9ICcxMDAlJztcblx0XHRlbHNlIGlmICghdGhpcy5tYXhXaWR0aC5lbmRzV2l0aCgnJScpICYmICF0aGlzLm1heFdpZHRoLmVuZHNXaXRoKCdweCcpKVxuXHRcdFx0dGhpcy5tYXhXaWR0aCArPSAncHgnO1xuXG5cdFx0dGhpcy5pbml0aWFsaXplZCA9IHRydWU7XG5cdFx0dGhpcy5jaGVja0ltYWdlcygpO1xuXHRcdHRoaXMuaW5pdFNsaWRlRHJhZ1dhdGNoaW5nKCk7XG5cdFx0dGhpcy5uZ0FmdGVyVmlld0NoZWNrZWQoKTtcblx0fVxuXG5cdG5nQWZ0ZXJWaWV3Q2hlY2tlZCgpOiB2b2lkIHtcblx0XHRpZiAoIXRoaXMud2luZG93UmVzaXppbmcpIHtcblx0XHRcdGxldCB3aWR0aCA9IDA7XG5cdFx0XHRpZiAodGhpcy5zZWN0aW9uRWwgJiYgdGhpcy5zZWN0aW9uRWwubmF0aXZlRWxlbWVudClcblx0XHRcdFx0d2lkdGggPSB0aGlzLnNlY3Rpb25FbC5uYXRpdmVFbGVtZW50LmNsaWVudFdpZHRoO1xuXG5cdFx0XHRpZiAod2lkdGggIT09IHRoaXMuY29udGFpbmVyV2lkdGgpXG5cdFx0XHRcdHRoaXMuY29udGFpbmVyV2lkdGggPSB3aWR0aDtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIGNoZWNrSW1hZ2VzKCkge1xuXHRcdGlmICh0aGlzLmltYWdlcyAmJiB0aGlzLmltYWdlcy5sZW5ndGgpIHtcblx0XHRcdGlmICh0eXBlb2YgdGhpcy5pbWFnZXNbMF0gIT09ICdzdHJpbmcnKSB7XG5cdFx0XHRcdCh0aGlzLmltYWdlcyBhcyB7IGxnOiBzdHJpbmcsIG1kPzogc3RyaW5nLCBzbT86IHN0cmluZyB9W10pLmZvckVhY2goKGltYWdlKSA9PiB7XG5cdFx0XHRcdFx0aWYgKCFpbWFnZS5tZClcblx0XHRcdFx0XHRcdGltYWdlLm1kID0gaW1hZ2UubGc7XG5cdFx0XHRcdFx0aWYgKCFpbWFnZS5zbSlcblx0XHRcdFx0XHRcdGltYWdlLnNtID0gaW1hZ2UubWQ7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHRoaXMuaW1hZ2VzID0gKHRoaXMuaW1hZ2VzIGFzIHN0cmluZ1tdKS5tYXAoKGltYWdlKSA9PiB7XG5cdFx0XHRcdFx0cmV0dXJuIHsgbGc6IGltYWdlLCBtZDogaW1hZ2UsIHNtOiBpbWFnZSB9O1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5zYWZlSW1hZ2VzID0gKHRoaXMuaW1hZ2VzIGFzIHsgbGc6IHN0cmluZywgbWQ6IHN0cmluZywgc206IHN0cmluZyB9W10pLm1hcCgoaW1hZ2UpID0+IHtcblx0XHRcdFx0bGV0IHNpemVzID0ge1xuXHRcdFx0XHRcdGxnOiB7IFxuXHRcdFx0XHRcdFx0dXJsOiBpbWFnZS5sZz8uc3RhcnRzV2l0aCgnaHR0cCcpID8gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFVybChpbWFnZS5sZykgOiBpbWFnZS5sZyxcblx0XHRcdFx0XHRcdHN0eWxlOiBpbWFnZS5sZz8uc3RhcnRzV2l0aCgnaHR0cCcpID8gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFN0eWxlKGB1cmwoJyR7aW1hZ2UubGd9JylgKSA6IGB1cmwoJyR7aW1hZ2UubGd9JylgLFxuXHRcdFx0XHRcdFx0cHVyZTogaW1hZ2UubGdcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdG1kOiB7IFxuXHRcdFx0XHRcdFx0dXJsOiBpbWFnZS5tZD8uc3RhcnRzV2l0aCgnaHR0cCcpID8gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFVybChpbWFnZS5tZCkgOiBpbWFnZS5tZCxcblx0XHRcdFx0XHRcdHN0eWxlOiBpbWFnZS5tZD8uc3RhcnRzV2l0aCgnaHR0cCcpID8gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFN0eWxlKGB1cmwoJyR7aW1hZ2UubWR9JylgKSA6IGB1cmwoJyR7aW1hZ2UubWR9JylgLFxuXHRcdFx0XHRcdFx0cHVyZTogaW1hZ2UubWRcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHNtOiB7IFxuXHRcdFx0XHRcdFx0dXJsOiBpbWFnZS5zbT8uc3RhcnRzV2l0aCgnaHR0cCcpID8gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFVybChpbWFnZS5zbSkgOiBpbWFnZS5zbSxcblx0XHRcdFx0XHRcdHN0eWxlOiBpbWFnZS5zbT8uc3RhcnRzV2l0aCgnaHR0cCcpID8gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFN0eWxlKGB1cmwoJyR7aW1hZ2Uuc219JylgKSA6IGB1cmwoJyR7aW1hZ2Uuc219JylgLFxuXHRcdFx0XHRcdFx0cHVyZTogaW1hZ2Uuc21cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH07XG5cdFx0XHRcdHJldHVybiBzaXplcztcblx0XHRcdH0pO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHRoaXMuc2FmZUltYWdlcyA9IFtdO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgaW5pdFNsaWRlRHJhZ1dhdGNoaW5nKCkge1xuXHRcdGlmICh0aGlzLmlubmVySW1hZ2VzRWwgJiYgdGhpcy5pbm5lckltYWdlc0VsLm5hdGl2ZUVsZW1lbnQpIHtcblx0XHRcdHRoaXMuc3RvcFNsaWRlRHJhZ1dhdGNoaW5nKCk7XG5cblx0XHRcdGlmICh0aGlzLmhlbHBlci5pc01vYmlsZURldmljZSgpKVxuXHRcdFx0XHR0aGlzLmxpc3RlbmVycyA9IFtcblx0XHRcdFx0XHR0aGlzLnJlbmRlcmVyLmxpc3Rlbihkb2N1bWVudC5ib2R5LCAndG91Y2hzdGFydCcsIHRoaXMub25TdGFydERyYWcuYmluZCh0aGlzKSksXG5cdFx0XHRcdFx0dGhpcy5yZW5kZXJlci5saXN0ZW4oZG9jdW1lbnQuYm9keSwgJ3RvdWNobW92ZScsIHRoaXMub25EcmFnZ2luZy5iaW5kKHRoaXMpKSxcblx0XHRcdFx0XHR0aGlzLnJlbmRlcmVyLmxpc3Rlbihkb2N1bWVudC5ib2R5LCAndG91Y2hlbmQnLCB0aGlzLm9uRW5kRHJhZy5iaW5kKHRoaXMpKVxuXHRcdFx0XHRdO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHR0aGlzLmxpc3RlbmVycyA9IFtcblx0XHRcdFx0XHR0aGlzLnJlbmRlcmVyLmxpc3Rlbihkb2N1bWVudC5ib2R5LCAnbW91c2Vkb3duJywgdGhpcy5vblN0YXJ0RHJhZy5iaW5kKHRoaXMpKSxcblx0XHRcdFx0XHR0aGlzLnJlbmRlcmVyLmxpc3Rlbihkb2N1bWVudC5ib2R5LCAnbW91c2Vtb3ZlJywgdGhpcy5vbkRyYWdnaW5nLmJpbmQodGhpcykpLFxuXHRcdFx0XHRcdHRoaXMucmVuZGVyZXIubGlzdGVuKGRvY3VtZW50LmJvZHksICdtb3VzZXVwJywgdGhpcy5vbkVuZERyYWcuYmluZCh0aGlzKSksXG5cdFx0XHRcdF07XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHRcdHNldFRpbWVvdXQoKCkgPT4gdGhpcy5pbml0U2xpZGVEcmFnV2F0Y2hpbmcoKSwgMjAwKTtcblx0fVxuXG5cdHByaXZhdGUgc3RvcFNsaWRlRHJhZ1dhdGNoaW5nKCkge1xuXHRcdGlmICh0aGlzLmxpc3RlbmVycyAmJiB0aGlzLmxpc3RlbmVycy5sZW5ndGgpXG5cdFx0XHR0aGlzLmxpc3RlbmVycy5mb3JFYWNoKCh1bkxpc3RlbikgPT4gdW5MaXN0ZW4oKSk7XG5cdH1cblxuXHRwdWJsaWMgcHJldmlld0ltYWdlKGltYWdlOiBhbnkpIHtcblx0XHRpZiAoIXRoaXMucHJldmlld1JlZikge1xuXHRcdFx0dGhpcy5wcmV2aWV3UmVmID0gdGhpcy5oZWxwZXIub3BlblByZXZpZXcoe1xuXHRcdFx0XHRpbWFnZToge1xuXHRcdFx0XHRcdHB1cmVVcmw6IGltYWdlLmxnLnB1cmUsXG5cdFx0XHRcdFx0c2FmZVVybDogaW1hZ2UubGcudXJsLFxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0dGhpcy5wcmV2aWV3UmVmLm9uQ2xvc2Uuc3Vic2NyaWJlKCgpID0+IHRoaXMucHJldmlld1JlZiA9IG51bGwpO1xuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBzZWxlY3RJbWFnZShpbWFnZUluZGV4OiBudW1iZXIsIGV2ZW50KSB7XG5cdFx0aWYgKGltYWdlSW5kZXggIT09IHRoaXMuY3VycmVudEltYWdlSW5kZXgpIHtcblx0XHRcdHRoaXMubGFzdERpcmVjdGlvbklzUmlnaHQgPSBpbWFnZUluZGV4ID4gdGhpcy5jdXJyZW50SW1hZ2VJbmRleDtcblx0XHRcdHRoaXMuY3VycmVudEltYWdlSW5kZXggPSBpbWFnZUluZGV4O1xuXG5cdFx0XHRpZiAoZXZlbnQudGFyZ2V0ICYmIHRoaXMuaW1hZ2VMaXN0RWwgJiYgdGhpcy5pbWFnZUxpc3RFbC5uYXRpdmVFbGVtZW50KVxuXHRcdFx0XHR0aGlzLnNjcm9sbGluZ1RvRWxlbWVudChldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQsIHRoaXMubGFzdERpcmVjdGlvbklzUmlnaHQpO1xuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBnb1ByZXZJbWFnZShzYWx0OiBudW1iZXIgPSAwKSB7XG5cdFx0aWYgKHRoaXMuY3VycmVudEltYWdlSW5kZXggPiAwKSB7XG5cdFx0XHRpZiAoc2FsdCkge1xuXHRcdFx0XHRpZiAoKHRoaXMuY3VycmVudEltYWdlSW5kZXggLSBzYWx0KSA+PSAwKVxuXHRcdFx0XHRcdHRoaXMuY3VycmVudEltYWdlSW5kZXggLT0gc2FsdCArIDE7XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHR0aGlzLmN1cnJlbnRJbWFnZUluZGV4ID0gMDtcblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdFx0dGhpcy5jdXJyZW50SW1hZ2VJbmRleC0tO1xuXG5cdFx0XHR0aGlzLmxhc3REaXJlY3Rpb25Jc1JpZ2h0ID0gZmFsc2U7XG5cblx0XHRcdGxldCB0YXJnZXQgPSB0aGlzLmltYWdlTGlzdEVsLm5hdGl2ZUVsZW1lbnQuY2hpbGRyZW5bMF0uY2hpbGRyZW5bdGhpcy5jdXJyZW50SW1hZ2VJbmRleF0gYXMgSFRNTEVsZW1lbnQ7XG5cdFx0XHRpZiAodGhpcy5pbWFnZUxpc3RFbCAmJiB0aGlzLmltYWdlTGlzdEVsLm5hdGl2ZUVsZW1lbnQpXG5cdFx0XHRcdHRoaXMuc2Nyb2xsaW5nVG9FbGVtZW50KHRhcmdldCwgdGhpcy5sYXN0RGlyZWN0aW9uSXNSaWdodCk7XG5cdFx0fVxuXHR9XG5cblx0cHVibGljIGdvTmV4dEltYWdlKHNhbHQ6IG51bWJlciA9IDApIHtcblx0XHRpZiAoKHRoaXMuY3VycmVudEltYWdlSW5kZXggKyAxKSA8IHRoaXMuaW1hZ2VzLmxlbmd0aCkge1xuXHRcdFx0aWYgKHNhbHQpIHtcblx0XHRcdFx0aWYgKCh0aGlzLmN1cnJlbnRJbWFnZUluZGV4ICsgc2FsdCArIDEpIDw9ICh0aGlzLmltYWdlcy5sZW5ndGggLSAxKSlcblx0XHRcdFx0XHR0aGlzLmN1cnJlbnRJbWFnZUluZGV4ID0gc2FsdCArIDE7XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHR0aGlzLmN1cnJlbnRJbWFnZUluZGV4ID0gdGhpcy5pbWFnZXMubGVuZ3RoO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZVxuXHRcdFx0XHR0aGlzLmN1cnJlbnRJbWFnZUluZGV4Kys7XG5cblx0XHRcdHRoaXMubGFzdERpcmVjdGlvbklzUmlnaHQgPSB0cnVlO1xuXG5cdFx0XHRsZXQgdGFyZ2V0ID0gdGhpcy5pbWFnZUxpc3RFbC5uYXRpdmVFbGVtZW50LmNoaWxkcmVuWzBdLmNoaWxkcmVuW3RoaXMuY3VycmVudEltYWdlSW5kZXhdIGFzIEhUTUxFbGVtZW50O1xuXHRcdFx0aWYgKHRoaXMuaW1hZ2VMaXN0RWwgJiYgdGhpcy5pbWFnZUxpc3RFbC5uYXRpdmVFbGVtZW50KVxuXHRcdFx0XHR0aGlzLnNjcm9sbGluZ1RvRWxlbWVudCh0YXJnZXQsIHRoaXMubGFzdERpcmVjdGlvbklzUmlnaHQpO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgc2Nyb2xsaW5nVG9FbGVtZW50KGVsZW1lbnQ6IEhUTUxFbGVtZW50LCBkaXJlY3Rpb25Jc1JpZ2h0OiBib29sZWFuKSB7XG5cdFx0bGV0IHNjcm9sbEVsZW1lbnQgPSB0aGlzLmltYWdlTGlzdEVsLm5hdGl2ZUVsZW1lbnQ7XG5cdFx0aWYgKHNjcm9sbEVsZW1lbnQgJiYgc2Nyb2xsRWxlbWVudC5zY3JvbGxXaWR0aCA+IDApe1xuXHRcdFx0bGV0IGJsb2NrV2lkdGggPSBlbGVtZW50LmNsaWVudFdpZHRoICsgMTQ7XG5cdFx0XHRsZXQgc2Nyb2xsTGVmdCA9IGVsZW1lbnQub2Zmc2V0TGVmdCAtIDE0O1xuXHRcdFx0bGV0IHNjcm9sbFJpZ2h0ID0gZWxlbWVudC5vZmZzZXRMZWZ0ICsgZWxlbWVudC5jbGllbnRXaWR0aCArIDE0O1xuXHRcdFx0bGV0IGN1cnJlbnRTY3JvbGxMZWZ0ID0gc2Nyb2xsRWxlbWVudC5zY3JvbGxMZWZ0O1xuXHRcdFx0bGV0IGN1cnJlbnRTY3JvbGxSaWdodCA9IHNjcm9sbEVsZW1lbnQuc2Nyb2xsTGVmdCArIHNjcm9sbEVsZW1lbnQuY2xpZW50V2lkdGg7XG5cblx0XHRcdGxldCBzY3JvbGwgPSAuMTtcblxuXHRcdFx0aWYgKGRpcmVjdGlvbklzUmlnaHQgJiYgKGN1cnJlbnRTY3JvbGxSaWdodCAtIHNjcm9sbFJpZ2h0KSA8IE1hdGguZmxvb3IoYmxvY2tXaWR0aCAvIDIpKVxuXHRcdFx0XHRzY3JvbGwgPSBjdXJyZW50U2Nyb2xsTGVmdCArIGJsb2NrV2lkdGggKyAxMDA7XG5cdFx0XHRlbHNlIGlmICghZGlyZWN0aW9uSXNSaWdodCAmJiAoc2Nyb2xsTGVmdCAtIGN1cnJlbnRTY3JvbGxMZWZ0KSA8IE1hdGguZmxvb3IoYmxvY2tXaWR0aCAvIDIpKVxuXHRcdFx0XHRzY3JvbGwgPSBjdXJyZW50U2Nyb2xsTGVmdCAtIGJsb2NrV2lkdGg7XG5cblx0XHRcdGlmIChzY3JvbGwgIT09IC4xKSB7XG5cdFx0XHRcdGlmICh0aGlzLnRpbWVyU3JvbGwpIGNsZWFySW50ZXJ2YWwodGhpcy50aW1lclNyb2xsKTtcblx0XHRcdFx0dGhpcy50aW1lclNyb2xsID0gdGhpcy5oZWxwZXIuc21vb3RoU2Nyb2xsKHNjcm9sbEVsZW1lbnQsIHNjcm9sbCwgNDAwLCAnbGVmdCcpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBvbktleWRvd24oZXZlbnQpIHtcblx0XHRpZiAoIXRoaXMuZGVzdHJveWVkICYmICF0aGlzLmlzRHJhZ2dpbmcgJiYgWzM3LCAzOV0uaW5kZXhPZihldmVudC5rZXlDb2RlKSA+PSAwKSB7XG4gICAgICAgICAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0gMzcpXG4gICAgICAgICAgICAgICAgdGhpcy5nb1ByZXZJbWFnZSgpO1xuICAgICAgICAgICAgZWxzZVxuXHRcdFx0XHR0aGlzLmdvTmV4dEltYWdlKCk7XG5cdFx0XHRcdFxuXHRcdFx0aWYgKHRoaXMucHJldmlld1JlZilcblx0XHRcdFx0dGhpcy5wcmV2aWV3UmVmLmluc3RhbmNlLm9uSW1hZ2VDaGFuZ2Uoe1xuXHRcdFx0XHRcdHB1cmVVcmw6IHRoaXMuY3VycmVudEltYWdlLmxnLnB1cmUsXG5cdFx0XHRcdFx0c2FmZVVybDogdGhpcy5jdXJyZW50SW1hZ2UubGcudXJsLFxuXHRcdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgb25XaW5kb3dSZXNpemUoKSB7XG5cdFx0aWYgKCF0aGlzLmRlc3Ryb3llZCAmJiAhdGhpcy53aW5kb3dSZXNpemluZykge1xuXHRcdFx0dGhpcy53aW5kb3dSZXNpemluZyA9IHRydWU7XG5cdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0dGhpcy5jb250YWluZXJXaWR0aCA9IHRoaXMuc2VjdGlvbkVsLm5hdGl2ZUVsZW1lbnQuY2xpZW50V2lkdGg7XG5cdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRcdHRoaXMud2luZG93UmVzaXppbmcgPSBmYWxzZTtcblxuXHRcdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRcdFx0aWYgKHRoaXMuaW1hZ2VMaXN0RWwgJiYgdGhpcy5pbWFnZUxpc3RFbC5uYXRpdmVFbGVtZW50KSB7XG5cdFx0XHRcdFx0XHRcdGxldCB0YXJnZXQgPSB0aGlzLmltYWdlTGlzdEVsLm5hdGl2ZUVsZW1lbnQuY2hpbGRyZW5bMF0uY2hpbGRyZW5bdGhpcy5jdXJyZW50SW1hZ2VJbmRleF0gYXMgSFRNTEVsZW1lbnQ7XG5cdFx0XHRcdFx0XHRcdGlmICh0aGlzLmltYWdlTGlzdEVsICYmIHRoaXMuaW1hZ2VMaXN0RWwubmF0aXZlRWxlbWVudClcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnNjcm9sbGluZ1RvRWxlbWVudCh0YXJnZXQsIHRoaXMubGFzdERpcmVjdGlvbklzUmlnaHQpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sIDEwMCk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBvblN0YXJ0RHJhZyhldmVudCkge1xuXHRcdGxldCBpc1RvdWNoaW5nID0gZmFsc2U7XG5cdFx0aWYgKGV2ZW50LnRvdWNoZXMpIHtcblx0XHRcdGlzVG91Y2hpbmcgPSB0cnVlO1xuXHRcdFx0ZXZlbnQgPSBldmVudC50b3VjaGVzWzBdO1xuXHRcdH1cblx0XHRcblx0XHRpZiAoaXNUb3VjaGluZyB8fCBldmVudC5idXR0b24gPT09IDApIHtcblx0XHRcdGlmICh0aGlzLmhlbHBlci5lbGVtZW50SXNDaGlsZChldmVudC50YXJnZXQsIHRoaXMuc2VjdGlvbkVsLm5hdGl2ZUVsZW1lbnQpKSB7XG5cdFx0XHRcdHRoaXMuZHJhZy5zdGFydExlZnQgPSB0aGlzLmlubmVySW1hZ2VzRWwubmF0aXZlRWxlbWVudC5vZmZzZXRMZWZ0O1xuXHRcdFx0XHR0aGlzLm