@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
142 lines • 22.9 kB
JavaScript
import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, Input, Output, TemplateRef } from '@angular/core';
import { Paging } from '@c8y/client';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "../i18n/c8y-translate.directive";
import * as i3 from "./icon.directive";
import * as i4 from "../i18n/c8y-translate.pipe";
export class LoadMoreComponent {
get hostClass() {
return this.hidden || (!this.hasMore && !this.hasNoMoreData) ? '' : this.class;
}
get hasMore() {
return (this.paging && (this.paging.totalPages > this.paging.currentPage || !!this.paging.nextPage));
}
get isLastPage() {
return this.paging && this.paging.totalPages === this.paging.currentPage;
}
constructor(element, cdRef) {
this.element = element;
this.cdRef = cdRef;
this.useIntersection = true;
this.hidden = false;
this.class = 'c8y-list__item';
this.maxIterations = 10;
this.hideNoMoreDataHint = false;
this.onLoad = new EventEmitter();
this.isLoading = false;
this.counter = 0;
this.hasNoMoreData = false;
this.LOAD_SAME_PAGE_THRESHOLD = 50;
this.destroyed = false;
}
ngAfterContentInit() {
this.destroyed = false;
if (this.useIntersection && 'IntersectionObserver' in window) {
this.intersectionObserver = new IntersectionObserver(event => this.buttonInView(event[0]), {
root: this.container ? this.container.nativeElement : null
});
this.intersectionObserver.observe(this.element.nativeElement);
}
this.hasNoMoreData = this.shouldShowNoMoreDataHint();
}
ngOnDestroy() {
this.destroyed = true;
if (this.intersectionObserver) {
this.intersectionObserver.disconnect();
this.intersectionObserver.unobserve(this.element.nativeElement);
clearTimeout(this.loadUntilIntersected);
}
}
async loadMore(event) {
if (!this.destroyed) {
this.isLoading = true;
this.cdRef.detectChanges();
if (event) {
event.stopPropagation();
}
if (this.hasMore) {
const result = await this.paging.next();
this.paging = result.paging;
this.onLoad.emit(result.data);
this.intersectionLoading();
this.hasNoMoreData = this.shouldShowNoMoreDataHint();
}
else {
this.counter = 0;
this.isLoading = false;
}
this.cdRef.detectChanges();
}
}
intersectionLoading() {
if (this.useIntersection && this.hasMore && this.loadUntilIntersected !== null) {
this.loadUntilIntersected = setTimeout(() => this.loadMore(), this.getLoadingThreshold());
this.useIntersection = this.shouldSwitchMode();
}
else {
this.isLoading = false;
this.loadUntilIntersected = undefined;
this.cdRef.detectChanges();
}
}
getLoadingThreshold() {
return this.LOAD_SAME_PAGE_THRESHOLD * this.counter++;
}
shouldShowNoMoreDataHint() {
return (this.counter !== 0 || this.noMoreDataHint) && !this.hasMore;
}
shouldSwitchMode() {
return this.counter < this.maxIterations || this.hidden;
}
buttonInView(event) {
if (event.isIntersecting) {
this.loadMore();
}
else if (this.loadUntilIntersected) {
clearTimeout(this.loadUntilIntersected);
this.loadUntilIntersected = null;
this.isLoading = false;
this.cdRef.detectChanges();
}
else {
// avoiding a race condition when timeout is faster
// cleared then set
this.loadUntilIntersected = null;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LoadMoreComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LoadMoreComponent, selector: "c8y-load-more", inputs: { paging: "paging", useIntersection: "useIntersection", hidden: "hidden", container: "container", class: "class", maxIterations: "maxIterations", noMoreDataHint: "noMoreDataHint", loadingTemplate: "loadingTemplate", hideNoMoreDataHint: "hideNoMoreDataHint", loadNextLabel: "loadNextLabel", loadingLabel: "loadingLabel" }, outputs: { onLoad: "onLoad" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "<button\n class=\"btn btn-default btn-block text-center\"\n type=\"button\"\n title=\"{{ 'Load more' | translate }}\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n [style.visibility]=\"hidden ? 'hidden' : 'visible'\"\n [style.height]=\"hidden ? '1px' : null\"\n (click)=\"loadMore($event)\"\n *ngIf=\"hasMore && !(loadingTemplate && isLoading)\"\n>\n <ng-container *ngIf=\"!isLoading\">\n <span *ngIf=\"loadNextLabel; else loadPage\" [innerHTML]=\"loadNextLabel | translate\"></span>\n <ng-template #loadPage>\n <span translate ngNonBindable [translateParams]=\"{ pageNo: paging.currentPage + 1 }\">\n Load page {{ pageNo }}\n </span>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isLoading\">\n <span *ngIf=\"loadingLabel; else loading\" [innerHTML]=\"loadingLabel | translate\"></span>\n <ng-template #loading>\n <span translate ngNonBindable [translateParams]=\"{ pageNo: paging.currentPage + 1 }\">\n Page {{ pageNo }} is loading\u2026\n </span>\n </ng-template>\n </ng-container>\n</button>\n\n<ng-container *ngIf=\"hasNoMoreData && !hideNoMoreDataHint && !isLoading\">\n <ng-container *ngTemplateOutlet=\"noMoreDataHint || finishHint\"></ng-container>\n</ng-container>\n\n<ng-template #finishHint>\n <div class=\"legend form-block center last-record\" title=\"{{ 'Last record' | translate }}\">\n <i [c8yIcon]=\"'circle'\"></i>\n </div>\n</ng-template>\n\n<ng-container *ngIf=\"loadingTemplate && isLoading\">\n <ng-container *ngTemplateOutlet=\"loadingTemplate\"></ng-container>\n</ng-container>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: i4.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LoadMoreComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-load-more', template: "<button\n class=\"btn btn-default btn-block text-center\"\n type=\"button\"\n title=\"{{ 'Load more' | translate }}\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n [style.visibility]=\"hidden ? 'hidden' : 'visible'\"\n [style.height]=\"hidden ? '1px' : null\"\n (click)=\"loadMore($event)\"\n *ngIf=\"hasMore && !(loadingTemplate && isLoading)\"\n>\n <ng-container *ngIf=\"!isLoading\">\n <span *ngIf=\"loadNextLabel; else loadPage\" [innerHTML]=\"loadNextLabel | translate\"></span>\n <ng-template #loadPage>\n <span translate ngNonBindable [translateParams]=\"{ pageNo: paging.currentPage + 1 }\">\n Load page {{ pageNo }}\n </span>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isLoading\">\n <span *ngIf=\"loadingLabel; else loading\" [innerHTML]=\"loadingLabel | translate\"></span>\n <ng-template #loading>\n <span translate ngNonBindable [translateParams]=\"{ pageNo: paging.currentPage + 1 }\">\n Page {{ pageNo }} is loading\u2026\n </span>\n </ng-template>\n </ng-container>\n</button>\n\n<ng-container *ngIf=\"hasNoMoreData && !hideNoMoreDataHint && !isLoading\">\n <ng-container *ngTemplateOutlet=\"noMoreDataHint || finishHint\"></ng-container>\n</ng-container>\n\n<ng-template #finishHint>\n <div class=\"legend form-block center last-record\" title=\"{{ 'Last record' | translate }}\">\n <i [c8yIcon]=\"'circle'\"></i>\n </div>\n</ng-template>\n\n<ng-container *ngIf=\"loadingTemplate && isLoading\">\n <ng-container *ngTemplateOutlet=\"loadingTemplate\"></ng-container>\n</ng-container>\n" }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { paging: [{
type: Input
}], useIntersection: [{
type: Input
}], hidden: [{
type: Input
}], container: [{
type: Input
}], class: [{
type: Input
}], maxIterations: [{
type: Input
}], noMoreDataHint: [{
type: Input
}], loadingTemplate: [{
type: Input
}], hideNoMoreDataHint: [{
type: Input
}], loadNextLabel: [{
type: Input
}], loadingLabel: [{
type: Input
}], onLoad: [{
type: Output
}], hostClass: [{
type: HostBinding,
args: ['class']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZC1tb3JlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2NvcmUvY29tbW9uL2xvYWQtbW9yZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9jb3JlL2NvbW1vbi9sb2FkLW1vcmUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixXQUFXLEVBQ1gsS0FBSyxFQUNMLE1BQU0sRUFDTixXQUFXLEVBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFlLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQzs7Ozs7O0FBTWxELE1BQU0sT0FBTyxpQkFBaUI7SUFrQzVCLElBQ0ksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ2pGLENBQUM7SUFFRCxJQUFJLE9BQU87UUFDVCxPQUFPLENBQ0wsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUM1RixDQUFDO0lBQ0osQ0FBQztJQUVELElBQUksVUFBVTtRQUNaLE9BQU8sSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQztJQUMzRSxDQUFDO0lBRUQsWUFDVSxPQUFtQixFQUNuQixLQUF3QjtRQUR4QixZQUFPLEdBQVAsT0FBTyxDQUFZO1FBQ25CLFVB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QUFHLEtBQUssQ0FBQztZQUN2QixJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzdCLENBQUM7YUFBTSxDQUFDO1lBQ04sbURBQW1EO1lBQ25ELG1CQUFtQjtZQUNuQixJQUFJLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxDQUFDO1FBQ25DLENBQUM7SUFDSCxDQUFDOytHQW5JVSxpQkFBaUI7bUdBQWpCLGlCQUFpQixtZENoQjlCLHVqREF5Q0E7OzRGRHpCYSxpQkFBaUI7a0JBSjdCLFNBQVM7K0JBQ0UsZUFBZTsrR0FLekIsTUFBTTtzQkFETCxLQUFLO2dCQUdOLGVBQWU7c0JBRGQsS0FBSztnQkFHTixNQUFNO3NCQURMLEtBQUs7Z0JBR04sU0FBUztzQkFEUixLQUFLO2dCQUdOLEtBQUs7c0JBREosS0FBSztnQkFHTixhQUFhO3NCQURaLEtBQUs7Z0JBR04sY0FBYztzQkFEYixLQUFLO2dCQUdOLGVBQWU7c0JBRGQsS0FBSztnQkFHTixrQkFBa0I7c0JBRGpCLEtBQUs7Z0JBR04sYUFBYTtzQkFEWixLQUFLO2dCQUdOLFlBQVk7c0JBRFgsS0FBSztnQkFHTixNQUFNO3NCQURMLE1BQU07Z0JBWUgsU0FBUztzQkFEWixXQUFXO3VCQUFDLE9BQU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RCaW5kaW5nLFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBUZW1wbGF0ZVJlZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IElJZGVudGlmaWVkLCBQYWdpbmcgfSBmcm9tICdAYzh5L2NsaWVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1sb2FkLW1vcmUnLFxuICB0ZW1wbGF0ZVVybDogJy4vbG9hZC1tb3JlLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBMb2FkTW9yZUNvbXBvbmVudCB7XG4gIEBJbnB1dCgpXG4gIHBhZ2luZzogUGFnaW5nPGFueT47XG4gIEBJbnB1dCgpXG4gIHVzZUludGVyc2VjdGlvbiA9IHRydWU7XG4gIEBJbnB1dCgpXG4gIGhpZGRlbiA9IGZhbHNlO1xuICBASW5wdXQoKVxuICBjb250YWluZXI6IEVsZW1lbnRSZWY7XG4gIEBJbnB1dCgpXG4gIGNsYXNzID0gJ2M4eS1saXN0X19pdGVtJztcbiAgQElucHV0KClcbiAgbWF4SXRlcmF0aW9ucyA9IDEwO1xuICBASW5wdXQoKVxuICBub01vcmVEYXRhSGludDogVGVtcGxhdGVSZWY8YW55PjtcbiAgQElucHV0KClcbiAgbG9hZGluZ1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xuICBASW5wdXQoKVxuICBoaWRlTm9Nb3JlRGF0YUhpbnQgPSBmYWxzZTtcbiAgQElucHV0KClcbiAgbG9hZE5leHRMYWJlbDogc3RyaW5nO1xuICBASW5wdXQoKVxuICBsb2FkaW5nTGFiZWw6IHN0cmluZztcbiAgQE91dHB1dCgpXG4gIG9uTG9hZCA9IG5ldyBFdmVudEVtaXR0ZXI8SUlkZW50aWZpZWQ+KCk7XG5cbiAgaXNMb2FkaW5nID0gZmFsc2U7XG4gIGNvdW50ZXIgPSAwO1xuICBoYXNOb01vcmVEYXRhID0gZmFsc2U7XG4gIHByaXZhdGUgbG9hZFVudGlsSW50ZXJzZWN0ZWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgTE9BRF9TQU1FX1BBR0VfVEhSRVNIT0xEID0gNTA7XG4gIHByaXZhdGUgaW50ZXJzZWN0aW9uT2JzZXJ2ZXI6IEludGVyc2VjdGlvbk9ic2VydmVyO1xuICBwcml2YXRlIGRlc3Ryb3llZCA9IGZhbHNlO1xuXG4gIEBIb3N0QmluZGluZygnY2xhc3MnKVxuICBnZXQgaG9zdENsYXNzKCkge1xuICAgIHJldHVybiB0aGlzLmhpZGRlbiB8fCAoIXRoaXMuaGFzTW9yZSAmJiAhdGhpcy5oYXNOb01vcmVEYXRhKSA/ICcnIDogdGhpcy5jbGFzcztcbiAgfVxuXG4gIGdldCBoYXNNb3JlKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLnBhZ2luZyAmJiAodGhpcy5wYWdpbmcudG90YWxQYWdlcyA+IHRoaXMucGFnaW5nLmN1cnJlbnRQYWdlIHx8ICEhdGhpcy5wYWdpbmcubmV4dFBhZ2UpXG4gICAgKTtcbiAgfVxuXG4gIGdldCBpc0xhc3RQYWdlKCkge1xuICAgIHJldHVybiB0aGlzLnBhZ2luZyAmJiB0aGlzLnBhZ2luZy50b3RhbFBhZ2VzID09PSB0aGlzLnBhZ2luZy5jdXJyZW50UGFnZTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZWxlbWVudDogRWxlbWVudFJlZixcbiAgICBwcml2YXRlIGNkUmVmOiBDaGFuZ2VEZXRlY3RvclJlZlxuICApIHt9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIHRoaXMuZGVzdHJveWVkID0gZmFsc2U7XG4gICAgaWYgKHRoaXMudXNlSW50ZXJzZWN0aW9uICYmICdJbnRlcnNlY3Rpb25PYnNlcnZlcicgaW4gd2luZG93KSB7XG4gICAgICB0aGlzLmludGVyc2VjdGlvbk9ic2VydmVyID0gbmV3IEludGVyc2VjdGlvbk9ic2VydmVyKGV2ZW50ID0+IHRoaXMuYnV0dG9uSW5WaWV3KGV2ZW50WzBdKSwge1xuICAgICAgICByb290OiB0aGlzLmNvbnRhaW5lciA/IHRoaXMuY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQgOiBudWxsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuaW50ZXJzZWN0aW9uT2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudCk7XG4gICAgfVxuICAgIHRoaXMuaGFzTm9Nb3JlRGF0YSA9IHRoaXMuc2hvdWxkU2hvd05vTW9yZURhdGFIaW50KCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmRlc3Ryb3llZCA9IHRydWU7XG4gICAgaWYgKHRoaXMuaW50ZXJzZWN0aW9uT2JzZXJ2ZXIpIHtcbiAgICAgIHRoaXMuaW50ZXJzZWN0aW9uT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgICAgdGhpcy5pbnRlcnNlY3Rpb25PYnNlcnZlci51bm9ic2VydmUodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpO1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMubG9hZFVudGlsSW50ZXJzZWN0ZWQpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGxvYWRNb3JlKGV2ZW50Pykge1xuICAgIGlmICghdGhpcy5kZXN0cm95ZWQpIHtcbiAgICAgIHRoaXMuaXNMb2FkaW5nID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2RSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuaGFzTW9yZSkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnBhZ2luZy5uZXh0KCk7XG4gICAgICAgIHRoaXMucGFnaW5nID0gcmVzdWx0LnBhZ2luZztcbiAgICAgICAgdGhpcy5vbkxvYWQuZW1pdChyZXN1bHQuZGF0YSk7XG4gICAgICAgIHRoaXMuaW50ZXJzZWN0aW9uTG9hZGluZygpO1xuICAgICAgICB0aGlzLmhhc05vTW9yZURhdGEgPSB0aGlzLnNob3VsZFNob3dOb01vcmVEYXRhSGludCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jb3VudGVyID0gMDtcbiAgICAgICAgdGhpcy5pc0xvYWRpbmcgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY2RSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJzZWN0aW9uTG9hZGluZygpIHtcbiAgICBpZiAodGhpcy51c2VJbnRlcnNlY3Rpb24gJiYgdGhpcy5oYXNNb3JlICYmIHRoaXMubG9hZFVudGlsSW50ZXJzZWN0ZWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMubG9hZFVudGlsSW50ZXJzZWN0ZWQgPSBzZXRUaW1lb3V0KCgpID0+IHRoaXMubG9hZE1vcmUoKSwgdGhpcy5nZXRMb2FkaW5nVGhyZXNob2xkKCkpO1xuICAgICAgdGhpcy51c2VJbnRlcnNlY3Rpb24gPSB0aGlzLnNob3VsZFN3aXRjaE1vZGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5pc0xvYWRpbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMubG9hZFVudGlsSW50ZXJzZWN0ZWQgPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLmNkUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldExvYWRpbmdUaHJlc2hvbGQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5MT0FEX1NBTUVfUEFHRV9USFJFU0hPTEQgKiB0aGlzLmNvdW50ZXIrKztcbiAgfVxuXG4gIHByaXZhdGUgc2hvdWxkU2hvd05vTW9yZURhdGFIaW50KCkge1xuICAgIHJldHVybiAodGhpcy5jb3VudGVyICE9PSAwIHx8IHRoaXMubm9Nb3JlRGF0YUhpbnQpICYmICF0aGlzLmhhc01vcmU7XG4gIH1cblxuICBwcml2YXRlIHNob3VsZFN3aXRjaE1vZGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuY291bnRlciA8IHRoaXMubWF4SXRlcmF0aW9ucyB8fCB0aGlzLmhpZGRlbjtcbiAgfVxuXG4gIHByaXZhdGUgYnV0dG9uSW5WaWV3KGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50LmlzSW50ZXJzZWN0aW5nKSB7XG4gICAgICB0aGlzLmxvYWRNb3JlKCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmxvYWRVbnRpbEludGVyc2VjdGVkKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5sb2FkVW50aWxJbnRlcnNlY3RlZCk7XG4gICAgICB0aGlzLmxvYWRVbnRpbEludGVyc2VjdGVkID0gbnVsbDtcbiAgICAgIHRoaXMuaXNMb2FkaW5nID0gZmFsc2U7XG4gICAgICB0aGlzLmNkUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gYXZvaWRpbmcgYSByYWNlIGNvbmRpdGlvbiB3aGVuIHRpbWVvdXQgaXMgZmFzdGVyXG4gICAgICAvLyBjbGVhcmVkIHRoZW4gc2V0XG4gICAgICB0aGlzLmxvYWRVbnRpbEludGVyc2VjdGVkID0gbnVsbDtcbiAgICB9XG4gIH1cbn1cbiIsIjxidXR0b25cbiAgY2xhc3M9XCJidG4gYnRuLWRlZmF1bHQgYnRuLWJsb2NrIHRleHQtY2VudGVyXCJcbiAgdHlwZT1cImJ1dHRvblwiXG4gIHRpdGxlPVwie3sgJ0xvYWQgbW9yZScgfCB0cmFuc2xhdGUgfX1cIlxuICBbbmdDbGFzc109XCJ7ICdidG4tcGVuZGluZyc6IGlzTG9hZGluZyB9XCJcbiAgW3N0eWxlLnZpc2liaWxpdHldPVwiaGlkZGVuID8gJ2hpZGRlbicgOiAndmlzaWJsZSdcIlxuICBbc3R5bGUuaGVpZ2h0XT1cImhpZGRlbiA/ICcxcHgnIDogbnVsbFwiXG4gIChjbGljayk9XCJsb2FkTW9yZSgkZXZlbnQpXCJcbiAgKm5nSWY9XCJoYXNNb3JlICYmICEobG9hZGluZ1RlbXBsYXRlICYmIGlzTG9hZGluZylcIlxuPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWlzTG9hZGluZ1wiPlxuICAgIDxzcGFuICpuZ0lmPVwibG9hZE5leHRMYWJlbDsgZWxzZSBsb2FkUGFnZVwiIFtpbm5lckhUTUxdPVwibG9hZE5leHRMYWJlbCB8IHRyYW5zbGF0ZVwiPjwvc3Bhbj5cbiAgICA8bmctdGVtcGxhdGUgI2xvYWRQYWdlPlxuICAgICAgPHNwYW4gdHJhbnNsYXRlIG5nTm9uQmluZGFibGUgW3RyYW5zbGF0ZVBhcmFtc109XCJ7IHBhZ2VObzogcGFnaW5nLmN1cnJlbnRQYWdlICsgMSB9XCI+XG4gICAgICAgIExvYWQgcGFnZSB7eyBwYWdlTm8gfX1cbiAgICAgIDwvc3Bhbj5cbiAgICA8L25nLXRlbXBsYXRlPlxuICA8L25nLWNvbnRhaW5lcj5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImlzTG9hZGluZ1wiPlxuICAgIDxzcGFuICpuZ0lmPVwibG9hZGluZ0xhYmVsOyBlbHNlIGxvYWRpbmdcIiBbaW5uZXJIVE1MXT1cImxvYWRpbmdMYWJlbCB8IHRyYW5zbGF0ZVwiPjwvc3Bhbj5cbiAgICA8bmctdGVtcGxhdGUgI2xvYWRpbmc+XG4gICAgICA8c3BhbiB0cmFuc2xhdGUgbmdOb25CaW5kYWJsZSBbdHJhbnNsYXRlUGFyYW1zXT1cInsgcGFnZU5vOiBwYWdpbmcuY3VycmVudFBhZ2UgKyAxIH1cIj5cbiAgICAgICAgUGFnZSB7eyBwYWdlTm8gfX0gaXMgbG9hZGluZ+KAplxuICAgICAgPC9zcGFuPlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIDwvbmctY29udGFpbmVyPlxuPC9idXR0b24+XG5cbjxuZy1jb250YWluZXIgKm5nSWY9XCJoYXNOb01vcmVEYXRhICYmICFoaWRlTm9Nb3JlRGF0YUhpbnQgJiYgIWlzTG9hZGluZ1wiPlxuICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwibm9Nb3JlRGF0YUhpbnQgfHwgZmluaXNoSGludFwiPjwvbmctY29udGFpbmVyPlxuPC9uZy1jb250YWluZXI+XG5cbjxuZy10ZW1wbGF0ZSAjZmluaXNoSGludD5cbiAgPGRpdiBjbGFzcz1cImxlZ2VuZCBmb3JtLWJsb2NrIGNlbnRlciBsYXN0LXJlY29yZFwiIHRpdGxlPVwie3sgJ0xhc3QgcmVjb3JkJyB8IHRyYW5zbGF0ZSB9fVwiPlxuICAgIDxpIFtjOHlJY29uXT1cIidjaXJjbGUnXCI+PC9pPlxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy1jb250YWluZXIgKm5nSWY9XCJsb2FkaW5nVGVtcGxhdGUgJiYgaXNMb2FkaW5nXCI+XG4gIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJsb2FkaW5nVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbjwvbmctY29udGFpbmVyPlxuIl19