@ngspot/ngx-errors
Version:
<p align="center"> <img width="20%" height="20%" src="https://github.com/DmitryEfimenko/ngspot/blob/main/packages/ngx-errors/package/assets/logo.png?raw=true"> </p>
204 lines • 28.1 kB
JavaScript
/* eslint-disable @angular-eslint/directive-selector */
import { ChangeDetectorRef, computed, Directive, effect, inject, input, TemplateRef, ViewContainerRef, } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
import { combineLatest, Subscription } from 'rxjs';
import { map, switchMap, tap } from 'rxjs/operators';
import { getErrorStateMatcher } from './all-errors-state.service';
import { ErrorStateMatchers } from './error-state-matchers.service';
import { NgxErrorsBase } from './errors-base.directive';
import { ERROR_CONFIGURATION } from './errors-configuration';
import { filterOutNullish } from './misc';
import { ValueMustBeStringError } from './ngx-errors';
import * as i0 from "@angular/core";
let errorDirectiveId = 0;
/**
* Directive to provide a validation error for a specific error name.
* Used as a child of ngxErrors directive.
*
* Example:
* ```html
* <div [ngxErrors]="control">
* <div ngxError="required">This input is required</div>
* </div>
* ```
*/
export class ErrorDirective {
constructor() {
this.subs = new Subscription();
this.config = inject(ERROR_CONFIGURATION);
this.errorStateMatchers = inject(ErrorStateMatchers);
this.errorsDirective = inject(NgxErrorsBase);
this.templateRef = inject(TemplateRef);
this.viewContainerRef = inject(ViewContainerRef);
this.cdr = inject(ChangeDetectorRef);
this.errorDirectiveId = ++errorDirectiveId;
this.errorName = input.required({ alias: 'ngxError' });
this.showWhen = input('', { alias: 'ngxErrorShowWhen' });
this.computedShowWhen = computed(() => {
const errorDirectiveShowWhen = this.showWhen();
if (errorDirectiveShowWhen) {
return errorDirectiveShowWhen;
}
const errorsDirectiveShowWhen = this.errorsDirective.showWhen();
if (errorsDirectiveShowWhen) {
return errorsDirectiveShowWhen;
}
if (this.config.showErrorsWhenInput === 'formIsSubmitted' &&
!this.errorsDirective.parentControlContainer) {
return 'touched';
}
return this.config.showErrorsWhenInput;
});
this.errorStateMatcher = computed(() => {
const showWhen = this.computedShowWhen();
return getErrorStateMatcher(this.errorStateMatchers, showWhen);
});
this.controlState$ = toObservable(this.errorsDirective.controlState).pipe(filterOutNullish());
/**
* Calculates whether the error could be shown based on the result of
* ErrorStateMatcher and whether there is an error for this particular errorName
* The calculation does not take into account config.showMaxErrors
*
* In addition, it observable produces a side-effect of updating NgxErrorsStateService
* with the information of whether this directive could be shown and a side-effect
* of updating err object in case it was mutated
*/
this.couldBeShown$ = combineLatest([
this.controlState$,
toObservable(this.errorName),
toObservable(this.errorStateMatcher),
]).pipe(switchMap(([controlState, errorName, errorStateMatcher]) => controlState.watchedEvents$.pipe(map(() => ({
controlState,
errorName,
errorStateMatcher,
})))), map(({ controlState, errorName, errorStateMatcher }) => {
const isErrorState = errorStateMatcher.isErrorState(controlState.control, controlState.parentForm);
const hasError = controlState.control.hasError(errorName);
const couldBeShown = isErrorState && hasError;
const prevCouldBeShown = controlState.errors()[this.errorDirectiveId];
return {
prevCouldBeShown,
couldBeShown,
errorName,
controlState,
hasError,
};
}), tap(({ controlState, errorName, prevCouldBeShown, couldBeShown, hasError, }) => {
if (prevCouldBeShown !== couldBeShown) {
controlState.errors.update((errors) => {
return { ...errors, [this.errorDirectiveId]: couldBeShown };
});
}
const err = controlState.control.getError(errorName);
const errorUpdated = hasError && JSON.stringify(this.err) !== JSON.stringify(err);
if (errorUpdated) {
this.err = err;
if (this.view) {
this.view.context.$implicit = this.err;
this.view.markForCheck();
}
}
}));
this.subscribeToCouldBeShown = this.subs.add(this.couldBeShown$.subscribe());
/**
* Determines whether the error is shown to the user based on
* the value of couldBeShown and the config.showMaxErrors.
* In addition, this reacts to the changes in visibility for all
* errors associated with the control
*/
this.isShown = computed(() => {
const controlState = this.errorsDirective.controlState();
if (!controlState) {
return false;
}
const errors = controlState.errors();
const couldBeShown = errors[this.errorDirectiveId];
if (!couldBeShown) {
return false;
}
const { showMaxErrors } = this.config;
if (!showMaxErrors) {
return true;
}
// get all errors for this control that are possibly visible,
// take directive ids associated with them, sort them
// and show only these with index <= to config.showMaxErrors
return Object.entries(errors)
.reduce((acc, curr) => {
const [id, couldBeShown] = curr;
if (couldBeShown) {
acc.push(Number(id));
}
return acc;
}, [])
.sort()
.filter((_, ix) => ix < showMaxErrors)
.includes(this.errorDirectiveId);
});
this.isShownEffect = effect(() => {
const isShown = this.isShown();
const control = this.errorsDirective.resolvedControl();
if (!control) {
return;
}
const prevHidden = this.hidden;
this.hidden = !isShown;
if (isShown) {
this.err = control.getError(this.errorName());
}
else {
this.err = {};
}
if (prevHidden !== this.hidden) {
this.toggleVisibility();
}
this.cdr.detectChanges();
});
this.hidden = true;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.err = {};
}
ngAfterViewInit() {
this.validateDirective();
}
ngOnDestroy() {
this.subs.unsubscribe();
}
toggleVisibility() {
if (this.hidden) {
if (this.view) {
this.view.destroy();
this.view = undefined;
}
}
else {
if (this.view) {
this.view.context.$implicit = this.err;
this.view.markForCheck();
}
else {
this.view = this.viewContainerRef.createEmbeddedView(this.templateRef, {
$implicit: this.err,
});
}
}
}
validateDirective() {
const errorName = this.errorName();
if (typeof errorName !== 'string' || errorName.trim() === '') {
throw new ValueMustBeStringError();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: ErrorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "17.3.7", type: ErrorDirective, isStandalone: true, selector: "[ngxError]", inputs: { errorName: { classPropertyName: "errorName", publicName: "ngxError", isSignal: true, isRequired: true, transformFunction: null }, showWhen: { classPropertyName: "showWhen", publicName: "ngxErrorShowWhen", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["ngxError"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: ErrorDirective, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: '[ngxError]',
exportAs: 'ngxError',
standalone: true,
}]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3IuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvbmd4LWVycm9ycy9wYWNrYWdlL3NyYy9saWIvZXJyb3IuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHVEQUF1RDtBQUN2RCxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLFFBQVEsRUFDUixTQUFTLEVBQ1QsTUFBTSxFQUVOLE1BQU0sRUFDTixLQUFLLEVBRUwsV0FBVyxFQUNYLGdCQUFnQixHQUNqQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFMUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbkQsT0FBTyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFckQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3hELE9BQU8sRUFBRSxtQkFBbUIsRUFBaUIsTUFBTSx3QkFBd0IsQ0FBQztBQUM1RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDMUMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sY0FBYyxDQUFDOztBQUV0RCxJQUFJLGdCQUFnQixHQUFHLENBQUMsQ0FBQztBQUV6Qjs7Ozs7Ozs7OztHQVVHO0FBT0gsTUFBTSxPQUFPLGNBQWM7SUFOM0I7UUFPVSxTQUFJLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUUxQixXQUFNLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFFckMsdUJBQWtCLEdBQUcsTUFBTSxD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LE9BQU8sRUFBRSxDQUFDO2dCQUNwQixJQUFJLENBQUMsSUFBSSxHQUFHLFNBQVMsQ0FBQztZQUN4QixDQUFDO1FBQ0gsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDZCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztnQkFDdkMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUMzQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRTtvQkFDckUsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHO2lCQUNwQixDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ25DLElBQUksT0FBTyxTQUFTLEtBQUssUUFBUSxJQUFJLFNBQVMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUM3RCxNQUFNLElBQUksc0JBQXNCLEVBQUUsQ0FBQztRQUNyQyxDQUFDO0lBQ0gsQ0FBQzs4R0F0T1UsY0FBYztrR0FBZCxjQUFjOzsyRkFBZCxjQUFjO2tCQU4xQixTQUFTO21CQUFDO29CQUNULDhEQUE4RDtvQkFDOUQsUUFBUSxFQUFFLFlBQVk7b0JBQ3RCLFFBQVEsRUFBRSxVQUFVO29CQUNwQixVQUFVLEVBQUUsSUFBSTtpQkFDakIiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBAYW5ndWxhci1lc2xpbnQvZGlyZWN0aXZlLXNlbGVjdG9yICovXHJcbmltcG9ydCB7XHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBjb21wdXRlZCxcclxuICBEaXJlY3RpdmUsXHJcbiAgZWZmZWN0LFxyXG4gIEVtYmVkZGVkVmlld1JlZixcclxuICBpbmplY3QsXHJcbiAgaW5wdXQsXHJcbiAgT25EZXN0cm95LFxyXG4gIFRlbXBsYXRlUmVmLFxyXG4gIFZpZXdDb250YWluZXJSZWYsXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IHRvT2JzZXJ2YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcclxuXHJcbmltcG9ydCB7IGNvbWJpbmVMYXRlc3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBtYXAsIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5cclxuaW1wb3J0IHsgZ2V0RXJyb3JTdGF0ZU1hdGNoZXIgfSBmcm9tICcuL2FsbC1lcnJvcnMtc3RhdGUuc2VydmljZSc7XHJcbmltcG9ydCB7IEVycm9yU3RhdGVNYXRjaGVycyB9IGZyb20gJy4vZXJyb3Itc3RhdGUtbWF0Y2hlcnMuc2VydmljZSc7XHJcbmltcG9ydCB7IE5neEVycm9yc0Jhc2UgfSBmcm9tICcuL2Vycm9ycy1iYXNlLmRpcmVjdGl2ZSc7XHJcbmltcG9ydCB7IEVSUk9SX0NPTkZJR1VSQVRJT04sIFNob3dFcnJvcldoZW4gfSBmcm9tICcuL2Vycm9ycy1jb25maWd1cmF0aW9uJztcclxuaW1wb3J0IHsgZmlsdGVyT3V0TnVsbGlzaCB9IGZyb20gJy4vbWlzYyc7XHJcbmltcG9ydCB7IFZhbHVlTXVzdEJlU3RyaW5nRXJyb3IgfSBmcm9tICcuL25neC1lcnJvcnMnO1xyXG5cclxubGV0IGVycm9yRGlyZWN0aXZlSWQgPSAwO1xyXG5cclxuLyoqXHJcbiAqIERpcmVjdGl2ZSB0byBwcm92aWRlIGEgdmFsaWRhdGlvbiBlcnJvciBmb3IgYSBzcGVjaWZpYyBlcnJvciBuYW1lLlxyXG4gKiBVc2VkIGFzIGEgY2hpbGQgb2Ygbmd4RXJyb3JzIGRpcmVjdGl2ZS5cclxuICpcclxuICogRXhhbXBsZTpcclxuICogYGBgaHRtbFxyXG4gKiA8ZGl2IFtuZ3hFcnJvcnNdPVwiY29udHJvbFwiPlxyXG4gKiAgIDxkaXYgbmd4RXJyb3I9XCJyZXF1aXJlZFwiPlRoaXMgaW5wdXQgaXMgcmVxdWlyZWQ8L2Rpdj5cclxuICogPC9kaXY+XHJcbiAqIGBgYFxyXG4gKi9cclxuQERpcmVjdGl2ZSh7XHJcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9kaXJlY3RpdmUtc2VsZWN0b3JcclxuICBzZWxlY3RvcjogJ1tuZ3hFcnJvcl0nLFxyXG4gIGV4cG9ydEFzOiAnbmd4RXJyb3InLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBFcnJvckRpcmVjdGl2ZSBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgcHJpdmF0ZSBzdWJzID0gbmV3IFN1YnNjcmlwdGlvbigpO1xyXG5cclxuICBwcml2YXRlIGNvbmZpZyA9IGluamVjdChFUlJPUl9DT05GSUdVUkFUSU9OKTtcclxuXHJcbiAgcHJpdmF0ZSBlcnJvclN0YXRlTWF0Y2hlcnMgPSBpbmplY3QoRXJyb3JTdGF0ZU1hdGNoZXJzKTtcclxuXHJcbiAgcHJpdmF0ZSBlcnJvcnNEaXJlY3RpdmUgPSBpbmplY3QoTmd4RXJyb3JzQmFzZSk7XHJcblxyXG4gIHByaXZhdGUgdGVtcGxhdGVSZWYgPSBpbmplY3QoVGVtcGxhdGVSZWYpO1xyXG5cclxuICBwcml2YXRlIHZpZXdDb250YWluZXJSZWYgPSBpbmplY3QoVmlld0NvbnRhaW5lclJlZik7XHJcblxyXG4gIHByaXZhdGUgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcclxuXHJcbiAgcHJpdmF0ZSB2aWV3OiBFbWJlZGRlZFZpZXdSZWY8YW55PiB8IHVuZGVmaW5lZDtcclxuXHJcbiAgcHJpdmF0ZSBlcnJvckRpcmVjdGl2ZUlkID0gKytlcnJvckRpcmVjdGl2ZUlkO1xyXG5cclxuICBlcnJvck5hbWUgPSBpbnB1dC5yZXF1aXJlZDxzdHJpbmc+KHsgYWxpYXM6ICduZ3hFcnJvcicgfSk7XHJcblxyXG4gIHNob3dXaGVuID0gaW5wdXQ8U2hvd0Vycm9yV2hlbj4oJycsIHsgYWxpYXM6ICduZ3hFcnJvclNob3dXaGVuJyB9KTtcclxuXHJcbiAgcHJpdmF0ZSBjb21wdXRlZFNob3dXaGVuID0gY29tcHV0ZWQoKCkgPT4ge1xyXG4gICAgY29uc3QgZXJyb3JEaXJlY3RpdmVTaG93V2hlbiA9IHRoaXMuc2hvd1doZW4oKTtcclxuICAgIGlmIChlcnJvckRpcmVjdGl2ZVNob3dXaGVuKSB7XHJcbiAgICAgIHJldHVybiBlcnJvckRpcmVjdGl2ZVNob3dXaGVuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGVycm9yc0RpcmVjdGl2ZVNob3dXaGVuID0gdGhpcy5lcnJvcnNEaXJlY3RpdmUuc2hvd1doZW4oKTtcclxuICAgIGlmIChlcnJvcnNEaXJlY3RpdmVTaG93V2hlbikge1xyXG4gICAgICByZXR1cm4gZXJyb3JzRGlyZWN0aXZlU2hvd1doZW47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKFxyXG4gICAgICB0aGlzLmNvbmZpZy5zaG93RXJyb3JzV2hlbklucHV0ID09PSAnZm9ybUlzU3VibWl0dGVkJyAmJlxyXG4gICAgICAhdGhpcy5lcnJvcnNEaXJlY3RpdmUucGFyZW50Q29udHJvbENvbnRhaW5lclxyXG4gICAgKSB7XHJcbiAgICAgIHJldHVybiAndG91Y2hlZCc7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLnNob3dFcnJvcnNXaGVuSW5wdXQ7XHJcbiAgfSk7XHJcblxyXG4gIHByaXZhdGUgZXJyb3JTdGF0ZU1hdGNoZXIgPSBjb21wdXRlZCgoKSA9PiB7XHJcbiAgICBjb25zdCBzaG93V2hlbiA9IHRoaXMuY29tcHV0ZWRTaG93V2hlbigpO1xyXG4gICAgcmV0dXJuIGdldEVycm9yU3RhdGVNYXRjaGVyKHRoaXMuZXJyb3JTdGF0ZU1hdGNoZXJzLCBzaG93V2hlbik7XHJcbiAgfSk7XHJcblxyXG4gIHByaXZhdGUgY29udHJvbFN0YXRlJCA9IHRvT2JzZXJ2YWJsZSh0aGlzLmVycm9yc0RpcmVjdGl2ZS5jb250cm9sU3RhdGUpLnBpcGUoXHJcbiAgICBmaWx0ZXJPdXROdWxsaXNoKCksXHJcbiAgKTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ2FsY3VsYXRlcyB3aGV0aGVyIHRoZSBlcnJvciBjb3VsZCBiZSBzaG93biBiYXNlZCBvbiB0aGUgcmVzdWx0IG9mXHJcbiAgICogRXJyb3JTdGF0ZU1hdGNoZXIgYW5kIHdoZXRoZXIgdGhlcmUgaXMgYW4gZXJyb3IgZm9yIHRoaXMgcGFydGljdWxhciBlcnJvck5hbWVcclxuICAgKiBUaGUgY2FsY3VsYXRpb24gZG9lcyBub3QgdGFrZSBpbnRvIGFjY291bnQgY29uZmlnLnNob3dNYXhFcnJvcnNcclxuICAgKlxyXG4gICAqIEluIGFkZGl0aW9uLCBpdCBvYnNlcnZhYmxlIHByb2R1Y2VzIGEgc2lkZS1lZmZlY3Qgb2YgdXBkYXRpbmcgTmd4RXJyb3JzU3RhdGVTZXJ2aWNlXHJcbiAgICogd2l0aCB0aGUgaW5mb3JtYXRpb24gb2Ygd2hldGhlciB0aGlzIGRpcmVjdGl2ZSBjb3VsZCBiZSBzaG93biBhbmQgYSBzaWRlLWVmZmVjdFxyXG4gICAqIG9mIHVwZGF0aW5nIGVyciBvYmplY3QgaW4gY2FzZSBpdCB3YXMgbXV0YXRlZFxyXG4gICAqL1xyXG4gIHByaXZhdGUgY291bGRCZVNob3duJCA9IGNvbWJpbmVMYXRlc3QoW1xyXG4gICAgdGhpcy5jb250cm9sU3RhdGUkLFxyXG4gICAgdG9PYnNlcnZhYmxlKHRoaXMuZXJyb3JOYW1lKSxcclxuICAgIHRvT2JzZXJ2YWJsZSh0aGlzLmVycm9yU3RhdGVNYXRjaGVyKSxcclxuICBdKS5waXBlKFxyXG4gICAgc3dpdGNoTWFwKChbY29udHJvbFN0YXRlLCBlcnJvck5hbWUsIGVycm9yU3RhdGVNYXRjaGVyXSkgPT5cclxuICAgICAgY29udHJvbFN0YXRlLndhdGNoZWRFdmVudHMkLnBpcGUoXHJcbiAgICAgICAgbWFwKCgpID0+ICh7XHJcbiAgICAgICAgICBjb250cm9sU3RhdGUsXHJcbiAgICAgICAgICBlcnJvck5hbWUsXHJcbiAgICAgICAgICBlcnJvclN0YXRlTWF0Y2hlcixcclxuICAgICAgICB9KSksXHJcbiAgICAgICksXHJcbiAgICApLFxyXG4gICAgbWFwKCh7IGNvbnRyb2xTdGF0ZSwgZXJyb3JOYW1lLCBlcnJvclN0YXRlTWF0Y2hlciB9KSA9PiB7XHJcbiAgICAgIGNvbnN0IGlzRXJyb3JTdGF0ZSA9IGVycm9yU3RhdGVNYXRjaGVyLmlzRXJyb3JTdGF0ZShcclxuICAgICAgICBjb250cm9sU3RhdGUuY29udHJvbCxcclxuICAgICAgICBjb250cm9sU3RhdGUucGFyZW50Rm9ybSxcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGNvbnN0IGhhc0Vycm9yID0gY29udHJvbFN0YXRlLmNvbnRyb2wuaGFzRXJyb3IoZXJyb3JOYW1lKTtcclxuICAgICAgY29uc3QgY291bGRCZVNob3duID0gaXNFcnJvclN0YXRlICYmIGhhc0Vycm9yO1xyXG5cclxuICAgICAgY29uc3QgcHJldkNvdWxkQmVTaG93biA9IGNvbnRyb2xTdGF0ZS5lcnJvcnMoKVt0aGlzLmVycm9yRGlyZWN0aXZlSWRdO1xyXG5cclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBwcmV2Q291bGRCZVNob3duLFxyXG4gICAgICAgIGNvdWxkQmVTaG93bixcclxuICAgICAgICBlcnJvck5hbWUsXHJcbiAgICAgICAgY29udHJvbFN0YXRlLFxyXG4gICAgICAgIGhhc0Vycm9yLFxyXG4gICAgICB9O1xyXG4gICAgfSksXHJcbiAgICB0YXAoXHJcbiAgICAgICh7XHJcbiAgICAgICAgY29udHJvbFN0YXRlLFxyXG4gICAgICAgIGVycm9yTmFtZSxcclxuICAgICAgICBwcmV2Q291bGRCZVNob3duLFxyXG4gICAgICAgIGNvdWxkQmVTaG93bixcclxuICAgICAgICBoYXNFcnJvcixcclxuICAgICAgfSkgPT4ge1xyXG4gICAgICAgIGlmIChwcmV2Q291bGRCZVNob3duICE9PSBjb3VsZEJlU2hvd24pIHtcclxuICAgICAgICAgIGNvbnRyb2xTdGF0ZS5lcnJvcnMudXBkYXRlKChlcnJvcnMpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIHsgLi4uZXJyb3JzLCBbdGhpcy5lcnJvckRpcmVjdGl2ZUlkXTogY291bGRCZVNob3duIH07XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGVyciA9IGNvbnRyb2xTdGF0ZS5jb250cm9sLmdldEVycm9yKGVycm9yTmFtZSk7XHJcblxyXG4gICAgICAgIGNvbnN0IGVycm9yVXBkYXRlZCA9XHJcbiAgICAgICAgICBoYXNFcnJvciAmJiBKU09OLnN0cmluZ2lmeSh0aGlzLmVycikgIT09IEpTT04uc3RyaW5naWZ5KGVycik7XHJcblxyXG4gICAgICAgIGlmIChlcnJvclVwZGF0ZWQpIHtcclxuICAgICAgICAgIHRoaXMuZXJyID0gZXJyO1xyXG4gICAgICAgICAgaWYgKHRoaXMudmlldykge1xyXG4gICAgICAgICAgICB0aGlzLnZpZXcuY29udGV4dC4kaW1wbGljaXQgPSB0aGlzLmVycjtcclxuICAgICAgICAgICAgdGhpcy52aWV3Lm1hcmtGb3JDaGVjaygpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSxcclxuICAgICksXHJcbiAgKTtcclxuXHJcbiAgcHJpdmF0ZSBzdWJzY3JpYmVUb0NvdWxkQmVTaG93biA9IHRoaXMuc3Vicy5hZGQoXHJcbiAgICB0aGlzLmNvdWxkQmVTaG93biQuc3Vic2NyaWJlKCksXHJcbiAgKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBlcnJvciBpcyBzaG93biB0byB0aGUgdXNlciBiYXNlZCBvblxyXG4gICAqIHRoZSB2YWx1ZSBvZiBjb3VsZEJlU2hvd24gYW5kIHRoZSBjb25maWcuc2hvd01heEVycm9ycy5cclxuICAgKiBJbiBhZGRpdGlvbiwgdGhpcyByZWFjdHMgdG8gdGhlIGNoYW5nZXMgaW4gdmlzaWJpbGl0eSBmb3IgYWxsXHJcbiAgICogZXJyb3JzIGFzc29jaWF0ZWQgd2l0aCB0aGUgY29udHJvbFxyXG4gICAqL1xyXG4gIHByaXZhdGUgaXNTaG93biA9IGNvbXB1dGVkKCgpID0+IHtcclxuICAgIGNvbnN0IGNvbnRyb2xTdGF0ZSA9IHRoaXMuZXJyb3JzRGlyZWN0aXZlLmNvbnRyb2xTdGF0ZSgpO1xyXG4gICAgaWYgKCFjb250cm9sU3RhdGUpIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGVycm9ycyA9IGNvbnRyb2xTdGF0ZS5lcnJvcnMoKTtcclxuXHJcbiAgICBjb25zdCBjb3VsZEJlU2hvd24gPSBlcnJvcnNbdGhpcy5lcnJvckRpcmVjdGl2ZUlkXTtcclxuXHJcbiAgICBpZiAoIWNvdWxkQmVTaG93bikge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgeyBzaG93TWF4RXJyb3JzIH0gPSB0aGlzLmNvbmZpZztcclxuICAgIGlmICghc2hvd01heEVycm9ycykge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBnZXQgYWxsIGVycm9ycyBmb3IgdGhpcyBjb250cm9sIHRoYXQgYXJlIHBvc3NpYmx5IHZpc2libGUsXHJcbiAgICAvLyB0YWtlIGRpcmVjdGl2ZSBpZHMgYXNzb2NpYXRlZCB3aXRoIHRoZW0sIHNvcnQgdGhlbVxyXG4gICAgLy8gYW5kIHNob3cgb25seSB0aGVzZSB3aXRoIGluZGV4IDw9IHRvIGNvbmZpZy5zaG93TWF4RXJyb3JzXHJcbiAgICByZXR1cm4gT2JqZWN0LmVudHJpZXMoZXJyb3JzKVxyXG4gICAgICAucmVkdWNlKChhY2MsIGN1cnIpID0+IHtcclxuICAgICAgICBjb25zdCBbaWQsIGNvdWxkQmVTaG93bl0gPSBjdXJyO1xyXG4gICAgICAgIGlmIChjb3VsZEJlU2hvd24pIHtcclxuICAgICAgICAgIGFjYy5wdXNoKE51bWJlcihpZCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gYWNjO1xyXG4gICAgICB9LCBbXSBhcyBudW1iZXJbXSlcclxuICAgICAgLnNvcnQoKVxyXG4gICAgICAuZmlsdGVyKChfLCBpeCkgPT4gaXggPCBzaG93TWF4RXJyb3JzKVxyXG4gICAgICAuaW5jbHVkZXModGhpcy5lcnJvckRpcmVjdGl2ZUlkKTtcclxuICB9KTtcclxuXHJcbiAgcHJpdmF0ZSBpc1Nob3duRWZmZWN0ID0gZWZmZWN0KCgpID0+IHtcclxuICAgIGNvbnN0IGlzU2hvd24gPSB0aGlzLmlzU2hvd24oKTtcclxuICAgIGNvbnN0IGNvbnRyb2wgPSB0aGlzLmVycm9yc0RpcmVjdGl2ZS5yZXNvbHZlZENvbnRyb2woKTtcclxuXHJcbiAgICBpZiAoIWNvbnRyb2wpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHByZXZIaWRkZW4gPSB0aGlzLmhpZGRlbjtcclxuICAgIHRoaXMuaGlkZGVuID0gIWlzU2hvd247XHJcblxyXG4gICAgaWYgKGlzU2hvd24pIHtcclxuICAgICAgdGhpcy5lcnIgPSBjb250cm9sLmdldEVycm9yKHRoaXMuZXJyb3JOYW1lKCkpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5lcnIgPSB7fTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAocHJldkhpZGRlbiAhPT0gdGhpcy5oaWRkZW4pIHtcclxuICAgICAgdGhpcy50b2dnbGVWaXNpYmlsaXR5KCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gIH0pO1xyXG5cclxuICBoaWRkZW4gPSB0cnVlO1xyXG5cclxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxyXG4gIGVycjogYW55ID0ge307XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcclxuICAgIHRoaXMudmFsaWRhdGVEaXJlY3RpdmUoKTtcclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCkge1xyXG4gICAgdGhpcy5zdWJzLnVuc3Vic2NyaWJlKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHRvZ2dsZVZpc2liaWxpdHkoKSB7XHJcbiAgICBpZiAodGhpcy5oaWRkZW4pIHtcclxuICAgICAgaWYgKHRoaXMudmlldykge1xyXG4gICAgICAgIHRoaXMudmlldy5kZXN0cm95KCk7XHJcbiAgICAgICAgdGhpcy52aWV3ID0gdW5kZWZpbmVkO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAodGhpcy52aWV3KSB7XHJcbiAgICAgICAgdGhpcy52aWV3LmNvbnRleHQuJGltcGxpY2l0ID0gdGhpcy5lcnI7XHJcbiAgICAgICAgdGhpcy52aWV3Lm1hcmtGb3JDaGVjaygpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMudmlldyA9IHRoaXMudmlld0NvbnRhaW5lclJlZi5jcmVhdGVFbWJlZGRlZFZpZXcodGhpcy50ZW1wbGF0ZVJlZiwge1xyXG4gICAgICAgICAgJGltcGxpY2l0OiB0aGlzLmVycixcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZURpcmVjdGl2ZSgpIHtcclxuICAgIGNvbnN0IGVycm9yTmFtZSA9IHRoaXMuZXJyb3JOYW1lKCk7XHJcbiAgICBpZiAodHlwZW9mIGVycm9yTmFtZSAhPT0gJ3N0cmluZycgfHwgZXJyb3JOYW1lLnRyaW0oKSA9PT0gJycpIHtcclxuICAgICAgdGhyb3cgbmV3IFZhbHVlTXVzdEJlU3RyaW5nRXJyb3IoKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19