ngx-skltn
Version:
Skeleton loader for Angular
185 lines • 25.7 kB
JavaScript
import { Component, Input, ElementRef, ChangeDetectorRef, HostListener, NgZone, } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { Subject } from 'rxjs';
import { throttleTime, debounceTime, filter, tap, takeUntil } from 'rxjs/operators';
import { SkltnService } from '../services/skltn.service';
import { generateId } from '../helpers';
import { BonesList } from '../classes/bones-list.class';
export class SkltnComponent {
constructor(skltnService, element, sanitizer, cd, zone, bonesList) {
this.skltnService = skltnService;
this.element = element;
this.sanitizer = sanitizer;
this.cd = cd;
this.zone = zone;
this.bonesList = bonesList;
this.showSkltn = true;
this.checkInterval = 100;
this.updStream$ = new Subject();
this.checkStream$ = new Subject();
this.unsubscribe$ = new Subject();
this.defaultConfig = {
rectRadius: 4,
bgFill: '#ddd',
flareFill: 'rgba(255, 255, 255, 0.6)',
flareWidth: '150px',
duration: 1200,
delay: 0,
timing: 'ease-in-out',
};
const conf = this.skltnService.config;
this.rectRadius = conf.rectRadius;
this.bgFill = conf.bgFill;
this.flareFill = conf.flareFill;
this.flareWidth = conf.flareWidth;
this.duration = conf.duration;
this.delay = conf.delay;
this.timing = conf.timing;
this.sufix = this.getSufixWithID();
this.gradientId = 'gradient-' + this.sufix;
this.maskId = 'mask-' + this.sufix;
}
onResize(event) {
this.updStream$.next();
}
ngOnInit() {
this.animationCss = this.sanitizer.bypassSecurityTrustHtml(`
<style>
skltnFlareAnimation {
0% { x: calc(0% - ${this.flareWidth}); }
100% { x: 100%; }
}
.skltn-flare {
animation-name: skltnFlareAnimation;
animation-duration: ${this.duration}ms;
animation-timing-function: ${this.timing};
animation-iteration-count: infinite;
animation-delay: ${this.delay}ms;
}
</style>`);
// Bones Updates
this.bonesList.changes.pipe(debounceTime(50), tap(list => {
this.bones = list;
this.calcShapes();
this.cd.detectChanges();
}), filter((list, index) => index === 0), tap(() => {
this.checkStream$.next();
}), takeUntil(this.unsubscribe$)).subscribe();
// Update
this.updStream$.pipe(throttleTime(50), takeUntil(this.unsubscribe$)).subscribe(() => this.calcShapes());
// Update href (Safari Bug, SVG Ref Path)
this.href = window.location.href;
this.zone.runOutsideAngular(() => {
this.checkStream$.pipe(tap(() => {
// Check if href changed
if (this.href !== window.location.href) {
this.href = window.location.href;
this.cd.detectChanges();
}
// Check if root element resized
const el = this.element.nativeElement;
const { width, height } = el.getBoundingClientRect();
if (this.parentClientRect.width !== width || this.parentClientRect.height !== height) {
this.updStream$.next();
this.cd.detectChanges();
}
setTimeout(() => {
this.checkStream$.next();
}, this.checkInterval);
}), takeUntil(this.unsubscribe$)).subscribe();
});
}
ngAfterViewInit() {
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
getSufixWithID() {
return generateId() + '-skltn';
}
calcShapes() {
var _a;
// Root SVG Element
const el = this.element.nativeElement;
this.parentClientRect = el.getBoundingClientRect();
this.viewBox = `0 0 ${this.parentClientRect.width} ${this.parentClientRect.height}`;
// SVG Shapes
if (!((_a = this.bones) === null || _a === void 0 ? void 0 : _a.length)) {
this.shapes = null;
return;
}
this.shapes = this.bones.map(bone => {
const boneEl = bone.element.nativeElement;
const clientRect = boneEl.getBoundingClientRect();
const radius = bone.rectRadius || this.rectRadius;
if (bone.type === 'circle') {
return {
type: 'circle',
cx: clientRect.x - this.parentClientRect.x + clientRect.width / 2,
cy: clientRect.y - this.parentClientRect.y + clientRect.height / 2,
rx: clientRect.width / 2,
ry: clientRect.height / 2,
};
}
if (bone.type === 'path') {
const x = clientRect.x - this.parentClientRect.x;
const y = clientRect.y - this.parentClientRect.y;
let transform = `translate(${x}, ${y})`;
if (bone.pathWidth && bone.pathHeight) {
const xScale = (clientRect.width / bone.pathWidth).toFixed(2);
const yScale = (clientRect.height / bone.pathHeight).toFixed(2);
transform += ` scale(${xScale}, ${yScale})`;
}
return {
type: 'path',
width: clientRect.width,
height: clientRect.height,
transform,
template: bone.template,
};
}
return {
type: 'rect',
x: clientRect.x - this.parentClientRect.x,
y: clientRect.y - this.parentClientRect.y,
width: clientRect.width,
height: clientRect.height,
rx: radius,
ry: radius,
};
});
}
}
SkltnComponent.decorators = [
{ type: Component, args: [{
selector: 'skltn-root',
template: "<div [innerHTML]=\"animationCss\"></div>\n\n<svg class=\"svg-root\" x=\"0px\" y=\"0px\" [attr.viewBox]=\"viewBox\" *ngIf=\"shapes?.length && showSkltn\">\n\n <!-- Gradient -->\n <linearGradient [attr.id]=\"gradientId\">\n <stop class=\"stop stop--1\" [attr.stop-color]=\"flareFill\" stop-opacity=\"0\" offset=\"0\"></stop>\n <stop class=\"stop stop--2\" [attr.stop-color]=\"flareFill\" stop-opacity=\"1\" offset=\"50%\"></stop>\n <stop class=\"stop stop--3\" [attr.stop-color]=\"flareFill\" stop-opacity=\"0\" offset=\"100%\"></stop>\n </linearGradient>\n\n <defs>\n <!-- Mask -->\n <mask [attr.id]=\"maskId\">\n <!-- Shapes -->\n <ng-container *ngFor=\"let shape of shapes\">\n <!-- Rect Type -->\n <rect *ngIf=\"shape.type === 'rect'\" [attr.x]=\"shape.x\" [attr.y]=\"shape.y\" [attr.rx]=\"shape.rx\"\n [attr.ry]=\"shape.ry\" [attr.width]=\"shape.width\" [attr.height]=\"shape.height\" fill=\"#FFFFFF\" />\n <!-- Circle Type -->\n <ellipse *ngIf=\"shape.type === 'circle'\" [attr.cx]=\"shape.cx\" [attr.cy]=\"shape.cy\" [attr.rx]=\"shape.rx\" [attr.ry]=\"shape.ry\" fill=\"#FFFFFF\"></ellipse>\n <!-- Path Type -->\n <ng-container *ngIf=\"shape.type === 'path'\">\n <g fill=\"#FFFFFF\" [attr.transform]=\"shape.transform\">\n <ng-container *ngTemplateOutlet=\"shape.template\"></ng-container>\n </g>\n </ng-container>\n </ng-container>\n </mask>\n </defs>\n\n <g [attr.mask]=\"'url(' + href + '#' + maskId + ')'\">\n <!-- Background Rectangle -->\n <rect class=\"bg-fill\" x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" [attr.fill]=\"bgFill\"></rect>\n\n <!-- Flare -->\n <rect class=\"skltn-flare\" [attr.x]=\"'-' + flareWidth\" y=\"0\" [attr.width]=\"flareWidth\" height=\"100%\" [attr.fill]=\"'url(' + href + '#' + gradientId + ')'\"></rect>\n </g>\n\n</svg>\n\n<ng-content></ng-content>\n",
providers: [{
provide: BonesList,
useClass: BonesList,
}],
styles: [":host{display:block;position:relative}.svg-root{display:block;position:absolute;top:0;bottom:0;left:0;right:0;z-index:1}"]
},] }
];
SkltnComponent.ctorParameters = () => [
{ type: SkltnService },
{ type: ElementRef },
{ type: DomSanitizer },
{ type: ChangeDetectorRef },
{ type: NgZone },
{ type: BonesList }
];
SkltnComponent.propDecorators = {
rectRadius: [{ type: Input }],
bgFill: [{ type: Input }],
flareFill: [{ type: Input }],
flareWidth: [{ type: Input }],
duration: [{ type: Input }],
delay: [{ type: Input }],
timing: [{ type: Input }],
showSkltn: [{ type: Input }],
checkInterval: [{ type: Input }],
onResize: [{ type: HostListener, args: ['window:resize', ['$event'],] }]
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tsdG4uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNrbHRuL3NyYy9saWIvc2tsdG4vc2tsdG4uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQVUsS0FBSyxFQUFFLFVBQVUsRUFDcEMsaUJBQWlCLEVBQUUsWUFBWSxFQUFpQixNQUFNLEdBQ3ZELE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxZQUFZLEVBQVksTUFBTSwyQkFBMkIsQ0FBQztBQUNuRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFcEYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDeEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBV3hELE1BQU0sT0FBTyxjQUFjO0lBc0R6QixZQUNVLFlBQTBCLEVBQzFCLE9BQW1CLEVBQ25CLFNBQXVCLEVBQ3ZCLEVBQXFCLEVBQ3JCLElBQVksRUFDWixTQUFvQjtRQUxwQixpQkFBWSxHQUFaLFlBQVksQ0FBYztRQUMxQixZQUFPLEdBQVAsT0FBTyxDQUFZO1FBQ25CLGNBQVMsR0FBVCxTQUFTLENBQWM7UUFDdkIsT0FBRSxHQUFGLEVBQUUsQ0FBbUI7UUFDckIsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUNaLGNBQVMsR0FBVCxTQUFTLENBQVc7UUE1Q3JCLGNBQVMsR0FBRyxJQUFJLENBQUM7UUFFakIsa0JBQWEsR0FBRyxHQUFHLENBQUM7UUFrQjdCLGVBQVUsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBRTNC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QUFDLGdCQUFnQixDQUFDLENBQUM7Z0JBQ3pDLEtBQUssRUFBRSxVQUFVLENBQUMsS0FBSztnQkFDdkIsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNO2dCQUN6QixFQUFFLEVBQUUsTUFBTTtnQkFDVixFQUFFLEVBQUUsTUFBTTthQUNYLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7OztZQXpORixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLFlBQVk7Z0JBQ3RCLGk2REFBcUM7Z0JBRXJDLFNBQVMsRUFBRSxDQUFDO3dCQUNWLE9BQU8sRUFBRSxTQUFTO3dCQUNsQixRQUFRLEVBQUUsU0FBUztxQkFDcEIsQ0FBQzs7YUFDSDs7O1lBWlEsWUFBWTtZQVJPLFVBQVU7WUFJN0IsWUFBWTtZQUhuQixpQkFBaUI7WUFBK0IsTUFBTTtZQVMvQyxTQUFTOzs7eUJBYWYsS0FBSztxQkFFTCxLQUFLO3dCQUVMLEtBQUs7eUJBRUwsS0FBSzt1QkFFTCxLQUFLO29CQUVMLEtBQUs7cUJBRUwsS0FBSzt3QkFFTCxLQUFLOzRCQUVMLEtBQUs7dUJBeURMLFlBQVksU0FBQyxlQUFlLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIEVsZW1lbnRSZWYsXG4gIENoYW5nZURldGVjdG9yUmVmLCBIb3N0TGlzdGVuZXIsIEFmdGVyVmlld0luaXQsIE5nWm9uZSwgT25EZXN0cm95LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFNrbHRuQm9uZURpcmVjdGl2ZSB9IGZyb20gJy4uL2RpcmVjdGl2ZXMvc2tsdG4tYm9uZS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgRG9tU2FuaXRpemVyLCBTYWZlSHRtbCB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGhyb3R0bGVUaW1lLCBkZWJvdW5jZVRpbWUsIGZpbHRlciwgdGFwLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBTa2x0bkNvbmZpZyB9IGZyb20gJy4uL2ludGVyZmFjZXMvc2tsdG4tY29uZmlnJztcbmltcG9ydCB7IFNrbHRuU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL3NrbHRuLnNlcnZpY2UnO1xuaW1wb3J0IHsgZ2VuZXJhdGVJZCB9IGZyb20gJy4uL2hlbHBlcnMnO1xuaW1wb3J0IHsgQm9uZXNMaXN0IH0gZnJvbSAnLi4vY2xhc3Nlcy9ib25lcy1saXN0LmNsYXNzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc2tsdG4tcm9vdCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9za2x0bi5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3NrbHRuLmNvbXBvbmVudC5zY3NzJ10sXG4gIHByb3ZpZGVyczogW3tcbiAgICBwcm92aWRlOiBCb25lc0xpc3QsXG4gICAgdXNlQ2xhc3M6IEJvbmVzTGlzdCxcbiAgfV1cbn0pXG5leHBvcnQgY2xhc3MgU2tsdG5Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgQElucHV0KCkgcmVjdFJhZGl1czogbnVtYmVyO1xuXG4gIEBJbnB1dCgpIGJnRmlsbDogc3RyaW5nO1xuXG4gIEBJbnB1dCgpIGZsYXJlRmlsbDogc3RyaW5nO1xuXG4gIEBJbnB1dCgpIGZsYXJlV2lkdGg6IHN0cmluZztcblxuICBASW5wdXQoKSBkdXJhdGlvbjogbnVtYmVyO1xuXG4gIEBJbnB1dCgpIGRlbGF5OiBudW1iZXI7XG5cbiAgQElucHV0KCkgdGltaW5nOiBzdHJpbmc7XG5cbiAgQElucHV0KCkgc2hvd1NrbHRuID0gdHJ1ZTtcblxuICBASW5wdXQoKSBjaGVja0ludGVydmFsID0gMTAwO1xuXG4gIHZpZXdCb3g6IHN0cmluZztcblxuICBzaGFwZXM6IGFueVtdO1xuXG4gIHBhcmVudENsaWVudFJlY3Q6IGFueTtcblxuICBhbmltYXRpb25Dc3M6IFNhZmVIdG1sO1xuXG4gIGhyZWY6IHN0cmluZztcblxuICBzdWZpeDogc3RyaW5nO1xuXG4gIGdyYWRpZW50SWQ6IHN0cmluZztcblxuICBtYXNrSWQ6IHN0cmluZztcblxuICB1cGRTdHJlYW0kID0gbmV3IFN1YmplY3QoKTtcblxuICBjaGVja1N0cmVhbSQgPSBuZXcgU3ViamVjdCgpO1xuXG4gIHVuc3Vic2NyaWJlJCA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgZGVmYXVsdENvbmZpZzogU2tsdG5Db25maWcgPSB7XG4gICAgcmVjdFJhZGl1czogNCxcbiAgICBiZ0ZpbGw6ICcjZGRkJyxcbiAgICBmbGFyZUZpbGw6ICdyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNiknLFxuICAgIGZsYXJlV2lkdGg6ICcxNTBweCcsXG4gICAgZHVyYXRpb246IDEyMDAsXG4gICAgZGVsYXk6IDAsXG4gICAgdGltaW5nOiAnZWFzZS1pbi1vdXQnLFxuICB9O1xuXG4gIHByaXZhdGUgYm9uZXM6IFNrbHRuQm9uZURpcmVjdGl2ZVtdO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgc2tsdG5TZXJ2aWNlOiBTa2x0blNlcnZpY2UsXG4gICAgcHJpdmF0ZSBlbGVtZW50OiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgc2FuaXRpemVyOiBEb21TYW5pdGl6ZXIsXG4gICAgcHJpdmF0ZSBjZDogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHJpdmF0ZSB6b25lOiBOZ1pvbmUsXG4gICAgcHJpdmF0ZSBib25lc0xpc3Q6IEJvbmVzTGlzdCxcbiAgKSB7XG4gICAgY29uc3QgY29uZiA9IHRoaXMuc2tsdG5TZXJ2aWNlLmNvbmZpZztcbiAgICB0aGlzLnJlY3RSYWRpdXMgPSBjb25mLnJlY3RSYWRpdXM7XG4gICAgdGhpcy5iZ0ZpbGwgPSBjb25mLmJnRmlsbDtcbiAgICB0aGlzLmZsYXJlRmlsbCA9IGNvbmYuZmxhcmVGaWxsO1xuICAgIHRoaXMuZmxhcmVXaWR0aCA9IGNvbmYuZmxhcmVXaWR0aDtcbiAgICB0aGlzLmR1cmF0aW9uID0gY29uZi5kdXJhdGlvbjtcbiAgICB0aGlzLmRlbGF5ID0gY29uZi5kZWxheTtcbiAgICB0aGlzLnRpbWluZyA9IGNvbmYudGltaW5nO1xuICAgIHRoaXMuc3VmaXggPSB0aGlzLmdldFN1Zml4V2l0aElEKCk7XG4gICAgdGhpcy5ncmFkaWVudElkID0gJ2dyYWRpZW50LScgKyB0aGlzLnN1Zml4O1xuICAgIHRoaXMubWFza0lkID0gJ21hc2stJyArIHRoaXMuc3VmaXg7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJywgWyckZXZlbnQnXSlcbiAgb25SZXNpemUoZXZlbnQ6IEV2ZW50KSB7XG4gICAgdGhpcy51cGRTdHJlYW0kLm5leHQoKTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuYW5pbWF0aW9uQ3NzID0gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdEh0bWwoYFxuICAgIDxzdHlsZT5cbiAgICBAa2V5ZnJhbWVzIHNrbHRuRmxhcmVBbmltYXRpb24ge1xuICAgICAgICAwJSB7IHg6IGNhbGMoMCUgLSAke3RoaXMuZmxhcmVXaWR0aH0pOyB9XG4gICAgICAgIDEwMCUgeyB4OiAxMDAlOyB9XG4gICAgfVxuICAgIC5za2x0bi1mbGFyZSB7XG4gICAgICBhbmltYXRpb24tbmFtZTogc2tsdG5GbGFyZUFuaW1hdGlvbjtcbiAgICAgIGFuaW1hdGlvbi1kdXJhdGlvbjogJHt0aGlzLmR1cmF0aW9ufW1zO1xuICAgICAgYW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjogJHt0aGlzLnRpbWluZ307XG4gICAgICBhbmltYXRpb24taXRlcmF0aW9uLWNvdW50OiBpbmZpbml0ZTtcbiAgICAgIGFuaW1hdGlvbi1kZWxheTogJHt0aGlzLmRlbGF5fW1zO1xuICAgIH1cbiAgICA8L3N0eWxlPmApO1xuXG4gICAgLy8gQm9uZXMgVXBkYXRlc1xuICAgIHRoaXMuYm9uZXNMaXN0LmNoYW5nZXMucGlwZShcbiAgICAgIGRlYm91bmNlVGltZSg1MCksXG4gICAgICB0YXAobGlzdCA9PiB7XG4gICAgICAgIHRoaXMuYm9uZXMgPSBsaXN0O1xuICAgICAgICB0aGlzLmNhbGNTaGFwZXMoKTtcbiAgICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB9KSxcbiAgICAgIGZpbHRlcigobGlzdCwgaW5kZXgpID0+IGluZGV4ID09PSAwKSxcbiAgICAgIHRhcCgoKSA9PiB7XG4gICAgICAgIHRoaXMuY2hlY2tTdHJlYW0kLm5leHQoKTtcbiAgICAgIH0pLFxuICAgICAgdGFrZVVudGlsKHRoaXMudW5zdWJzY3JpYmUkKSxcbiAgICApLnN1YnNjcmliZSgpO1xuXG4gICAgLy8gVXBkYXRlXG4gICAgdGhpcy51cGRTdHJlYW0kLnBpcGUoXG4gICAgICB0aHJvdHRsZVRpbWUoNTApLFxuICAgICAgdGFrZVVudGlsKHRoaXMudW5zdWJzY3JpYmUkKSxcbiAgICApLnN1YnNjcmliZSgoKSA9PiB0aGlzLmNhbGNTaGFwZXMoKSk7XG5cbiAgICAvLyBVcGRhdGUgaHJlZiAoU2FmYXJpIEJ1ZywgU1ZHIFJlZiBQYXRoKVxuICAgIHRoaXMuaHJlZiA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmO1xuXG4gICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIHRoaXMuY2hlY2tTdHJlYW0kLnBpcGUoXG4gICAgICAgIHRhcCgoKSA9PiB7XG4gICAgICAgICAgLy8gQ2hlY2sgaWYgaHJlZiBjaGFuZ2VkXG4gICAgICAgICAgaWYgKHRoaXMuaHJlZiAhPT0gd2luZG93LmxvY2F0aW9uLmhyZWYpIHtcbiAgICAgICAgICAgIHRoaXMuaHJlZiA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmO1xuICAgICAgICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQ2hlY2sgaWYgcm9vdCBlbGVtZW50IHJlc2l6ZWRcbiAgICAgICAgICBjb25zdCBlbCA9IHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50O1xuICAgICAgICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCB9ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgaWYgKHRoaXMucGFyZW50Q2xpZW50UmVjdC53aWR0aCAhPT0gd2lkdGggfHwgdGhpcy5wYXJlbnRDbGllbnRSZWN0LmhlaWdodCAhPT0gaGVpZ2h0KSB7XG4gICAgICAgICAgICB0aGlzLnVwZFN0cmVhbSQubmV4dCgpO1xuICAgICAgICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5jaGVja1N0cmVhbSQubmV4dCgpO1xuICAgICAgICAgIH0sIHRoaXMuY2hlY2tJbnRlcnZhbCk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWwodGhpcy51bnN1YnNjcmliZSQpLFxuICAgICAgKS5zdWJzY3JpYmUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMudW5zdWJzY3JpYmUkLm5leHQoKTtcbiAgICB0aGlzLnVuc3Vic2NyaWJlJC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgZ2V0U3VmaXhXaXRoSUQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gZ2VuZXJhdGVJZCgpICsgJy1za2x0bic7XG4gIH1cblxuICBjYWxjU2hhcGVzKCk6IHZvaWQge1xuICAgIC8vIFJvb3QgU1ZHIEVsZW1lbnRcbiAgICBjb25zdCBlbCA9IHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50O1xuICAgIHRoaXMucGFyZW50Q2xpZW50UmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHRoaXMudmlld0JveCA9IGAwIDAgJHt0aGlzLnBhcmVudENsaWVudFJlY3Qud2lkdGh9ICR7dGhpcy5wYXJlbnRDbGllbnRSZWN0LmhlaWdodH1gO1xuXG4gICAgLy8gU1ZHIFNoYXBlc1xuICAgIGlmICghdGhpcy5ib25lcz8ubGVuZ3RoKSB7XG4gICAgICB0aGlzLnNoYXBlcyA9IG51bGw7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc2hhcGVzID0gdGhpcy5ib25lcy5tYXAoYm9uZSA9PiB7XG4gICAgICBjb25zdCBib25lRWwgPSBib25lLmVsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICAgIGNvbnN0IGNsaWVudFJlY3QgPSBib25lRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBjb25zdCByYWRpdXMgPSBib25lLnJlY3RSYWRpdXMgfHwgdGhpcy5yZWN0UmFkaXVzO1xuICAgICAgaWYgKGJvbmUudHlwZSA9PT0gJ2NpcmNsZScpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiAnY2lyY2xlJyxcbiAgICAgICAgICBjeDogY2xpZW50UmVjdC54IC0gdGhpcy5wYXJlbnRDbGllbnRSZWN0LnggKyBjbGllbnRSZWN0LndpZHRoIC8gMixcbiAgICAgICAgICBjeTogY2xpZW50UmVjdC55IC0gdGhpcy5wYXJlbnRDbGllbnRSZWN0LnkgKyBjbGllbnRSZWN0LmhlaWdodCAvIDIsXG4gICAgICAgICAgcng6IGNsaWVudFJlY3Qud2lkdGggLyAyLFxuICAgICAgICAgIHJ5OiBjbGllbnRSZWN0LmhlaWdodCAvIDIsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBpZiAoYm9uZS50eXBlID09PSAncGF0aCcpIHtcbiAgICAgICAgY29uc3QgeCA9IGNsaWVudFJlY3QueCAtIHRoaXMucGFyZW50Q2xpZW50UmVjdC54O1xuICAgICAgICBjb25zdCB5ID0gY2xpZW50UmVjdC55IC0gdGhpcy5wYXJlbnRDbGllbnRSZWN0Lnk7XG4gICAgICAgIGxldCB0cmFuc2Zvcm0gPSBgdHJhbnNsYXRlKCR7eH0sICR7eX0pYDtcbiAgICAgICAgaWYgKGJvbmUucGF0aFdpZHRoICYmIGJvbmUucGF0aEhlaWdodCkge1xuICAgICAgICAgIGNvbnN0IHhTY2FsZSA9IChjbGllbnRSZWN0LndpZHRoIC8gYm9uZS5wYXRoV2lkdGgpLnRvRml4ZWQoMik7XG4gICAgICAgICAgY29uc3QgeVNjYWxlID0gKGNsaWVudFJlY3QuaGVpZ2h0IC8gYm9uZS5wYXRoSGVpZ2h0KS50b0ZpeGVkKDIpO1xuICAgICAgICAgIHRyYW5zZm9ybSArPSBgIHNjYWxlKCR7eFNjYWxlfSwgJHt5U2NhbGV9KWA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiAncGF0aCcsXG4gICAgICAgICAgd2lkdGg6IGNsaWVudFJlY3Qud2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiBjbGllbnRSZWN0LmhlaWdodCxcbiAgICAgICAgICB0cmFuc2Zvcm0sXG4gICAgICAgICAgdGVtcGxhdGU6IGJvbmUudGVtcGxhdGUsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiAncmVjdCcsXG4gICAgICAgIHg6IGNsaWVudFJlY3QueCAtIHRoaXMucGFyZW50Q2xpZW50UmVjdC54LFxuICAgICAgICB5OiBjbGllbnRSZWN0LnkgLSB0aGlzLnBhcmVudENsaWVudFJlY3QueSxcbiAgICAgICAgd2lkdGg6IGNsaWVudFJlY3Qud2lkdGgsXG4gICAgICAgIGhlaWdodDogY2xpZW50UmVjdC5oZWlnaHQsXG4gICAgICAgIHJ4OiByYWRpdXMsXG4gICAgICAgIHJ5OiByYWRpdXMsXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbn1cbiJdfQ==