@nova-ui/bits
Version:
SolarWinds Nova Framework
293 lines • 47.5 kB
JavaScript
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { ChangeDetectorRef, Component, ContentChildren, ElementRef, EventEmitter, forwardRef, Input, Optional, Output, QueryList, Renderer2, ViewChild, ViewContainerRef, ViewEncapsulation, } from "@angular/core";
import { NG_VALUE_ACCESSOR } from "@angular/forms";
import _isNil from "lodash/isNil";
import _isUndefined from "lodash/isUndefined";
import { DOCUMENT_CLICK_EVENT } from "../../constants/event.constants";
import { EventBusService } from "../../services/event-bus.service";
import { NuiFormFieldControl } from "../form-field/public-api";
import * as i0 from "@angular/core";
import * as i1 from "../../services/event-bus.service";
import * as i2 from "@angular/common";
/*
* <example-url>./../examples/index.html#/radio-group</example-url>
*/
export class RadioGroupComponent {
/**
* Stores the value from selected radio
*/
get value() {
return this._value;
}
set value(newValue) {
if (this._value !== newValue) {
// Set this before proceeding to ensure no circular loop occurs with selection.
this._value = newValue;
this.updateSelectedRadioFromValue();
this.checkSelectedRadioButton();
}
}
constructor(renderer) {
this.renderer = renderer;
/**
* Input to set aria label text
*/
this.ariaLabel = "";
/**
* Emits an event when the radio selection changes
*/
this.valueChange = new EventEmitter();
this._value = null;
this.selectedRadio = null;
this.subscriptions = new Array();
this.setChildDisabled = (child) => {
if (!_isUndefined(this.disabled)) {
child.disabled = this.disabled;
}
};
}
registerChild(child) {
this.renderer.setAttribute(child.inputViewContainer.element.nativeElement, "name", this.name);
this.subscriptions.push(this.subscribeToRadioEvent(child));
// timeout to prevent "expression changed after it has been checked" error
setTimeout(() => {
this.setChildDisabled(child);
});
}
ngAfterContentInit() {
this.children.toArray().forEach((child) => this.registerChild(child));
this.children.changes.subscribe((radioComponentQueryList) => {
this.subscriptions.forEach((sub) => sub.unsubscribe());
radioComponentQueryList
.toArray()
.forEach((child) => this.registerChild(child));
});
}
onChange(value) { }
onTouched() { }
writeValue(value) {
this.value = value;
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
setDisabledState(isDisabled) {
this.disabled = isDisabled;
if (this.children) {
this.children.toArray().forEach(this.setChildDisabled);
}
}
ngOnDestroy() {
this.subscriptions.forEach((sub) => sub.unsubscribe());
}
checkSelectedRadioButton() {
if (this.selectedRadio && !this.selectedRadio.checked) {
this.selectedRadio.checked = true;
}
}
updateSelectedRadioFromValue() {
// If the value already matches the selected radio, do nothing.
const isAlreadySelected = this.selectedRadio !== null &&
this.selectedRadio.value === this._value;
if (this.children && !isAlreadySelected) {
this.children.forEach((radio) => {
radio.checked = this.value === radio.value;
if (radio.checked) {
this.selectedRadio = radio;
}
});
}
}
subscribeToRadioEvent(radio) {
return radio.valueChange.subscribe((value) => {
this.value = value;
this.valueChange.emit(value);
if (!radio.keepFormPristine) {
this.onChange(this.value);
this.onTouched();
}
this.writeValue(this.value);
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioGroupComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: RadioGroupComponent, selector: "nui-radio-group", inputs: { ariaLabel: "ariaLabel", name: "name", value: "value", disabled: "disabled" }, outputs: { valueChange: "valueChange" }, host: { attributes: { "role": "radiogroup" } }, providers: [
{
provide: NuiFormFieldControl,
useExisting: forwardRef(() => RadioGroupComponent),
multi: true,
},
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RadioGroupComponent),
multi: true,
},
], queries: [{ propertyName: "children", predicate: i0.forwardRef(() => RadioComponent), descendants: true }], ngImport: i0, template: `<div class="nui-radio-group" [attr.aria-label]="ariaLabel">
<ng-content></ng-content>
</div>`, isInline: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioGroupComponent, decorators: [{
type: Component,
args: [{
selector: "nui-radio-group",
template: `<div class="nui-radio-group" [attr.aria-label]="ariaLabel">
<ng-content></ng-content>
</div>`,
providers: [
{
provide: NuiFormFieldControl,
useExisting: forwardRef(() => RadioGroupComponent),
multi: true,
},
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RadioGroupComponent),
multi: true,
},
],
host: { role: "radiogroup" },
}]
}], ctorParameters: () => [{ type: i0.Renderer2 }], propDecorators: { ariaLabel: [{
type: Input
}], name: [{
type: Input
}], value: [{
type: Input
}], disabled: [{
type: Input
}], valueChange: [{
type: Output
}], children: [{
type: ContentChildren,
args: [forwardRef(() => RadioComponent), { descendants: true }]
}] } });
/**
* @ignore
* Should be used only within nui-radio-group.
*/
export class RadioComponent {
/**
* Sets whether the radio button is disabled
*/
get disabled() {
return this._disabled;
}
set disabled(val) {
if (this._disabled !== val) {
this.changeDetector.markForCheck();
}
this._disabled = val;
}
constructor(radioGroup, changeDetector, eventBusService) {
this.changeDetector = changeDetector;
this.eventBusService = eventBusService;
/**
* Emits an event when the value changes
*/
this.valueChange = new EventEmitter();
/**
* Sets whether the radio button is selected
*/
this.checked = false;
/**
* Input to set aria label text
*/
this.ariaLabel = "";
this.keepFormPristine = true;
this._disabled = false;
this.radioGroup = radioGroup;
}
ngOnInit() {
if (this.radioGroup !== null) {
if (this.radioGroup.value === this.value) {
this.checked = true;
}
}
if (this.checked) {
// TODO: remove timeout in v10 NUI-4843
// nui-radio-group should subscribe before event is emitted
this.timeoutId = setTimeout(() => {
this.valueChange.emit(this.value);
}, 0);
}
// Checks if user supplied any content as a label for radio button to adjust styles for radio buttons without labels
this.radioTranscludeIsEmpty = _isNil(this.radioTransclude.nativeElement.firstChild);
}
ngOnDestroy() {
clearTimeout(this.timeoutId);
}
hoverHandler() {
this.hovered = !this.hovered;
}
changeHandler() {
this.keepFormPristine = false;
this.valueChange.emit(this.value);
}
onInputClick(event) {
// We have to stop propagation for click events on the visual hidden input element.
// By default, when a user clicks on a label element, a generated click event will be
// dispatched on the associated input element. Since we are using a label element as our
// root container, the click event on the `radio-button` will be executed twice.
// The real click event will bubble up, and the generated click event also tries to bubble up.
// This will lead to multiple click events.
// Preventing bubbling for the second event will solve that issue.
event.stopPropagation();
this.eventBusService.getStream(DOCUMENT_CLICK_EVENT).next(event);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioComponent, deps: [{ token: RadioGroupComponent, optional: true }, { token: i0.ChangeDetectorRef }, { token: i1.EventBusService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: RadioComponent, selector: "nui-radio", inputs: { value: "value", hovered: "hovered", checked: "checked", hint: "hint", disabled: "disabled", ariaLabel: "ariaLabel" }, outputs: { valueChange: "valueChange" }, host: { attributes: { "role": "radio" }, properties: { "class.nui-radio--hovered": "hovered", "class.nui-radio--checked": "checked" } }, queries: [{ propertyName: "contentHints", predicate: ["[nui-radio-hint]"] }], viewQueries: [{ propertyName: "inputViewContainer", first: true, predicate: ["inputViewContainer"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "radioTransclude", first: true, predicate: ["radioTransclude"], descendants: true, static: true }], ngImport: i0, template: "<div\n class=\"nui-radio\"\n [class.nui-radio--empty]=\"radioTranscludeIsEmpty && !hint\"\n>\n <label\n class=\"nui-radio__label\"\n [class.nui-radio__label--translucent]=\"disabled\"\n (mouseenter)=\"hoverHandler()\"\n (mouseleave)=\"hoverHandler()\"\n >\n <div class=\"nui-radio__content\">\n <input\n #inputViewContainer\n class=\"nui-radio__input\"\n type=\"radio\"\n [value]=\"value\"\n [checked]=\"checked\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"ariaLabel\"\n (change)=\"changeHandler()\"\n (click)=\"onInputClick($event)\"\n />\n\n <div\n class=\"nui-radio__mark\"\n [class.nui-radio__mark--disabled]=\"disabled\"\n >\n <div class=\"nui-radio__glyph\"></div>\n </div>\n\n <div #radioTransclude class=\"nui-radio__transclude\">\n <ng-content></ng-content>\n </div>\n </div>\n\n <div #hintDiv class=\"nui-radio__hint nui-help-hint\">\n <ng-content select=\"[hint]\"></ng-content>\n <ng-container *ngIf=\"!!hint\">\n {{ hint }}\n </ng-container>\n </div>\n </label>\n</div>\n", styles: [".nui-radio-group-inline>.nui-radio-group{display:inline-flex}.nui-radio-group-inline>.nui-radio-group .nui-radio{margin-left:5px}.nui .nui-radio{border-radius:3px;cursor:pointer;line-height:14px}.nui .nui-radio:hover{background-color:var(--nui-color-bg-transparent-hover,rgba(17, 17, 17, .05))}.nui .nui-radio__label{cursor:pointer;font-weight:400;margin:0;min-height:30px;min-width:30px;padding:7px;position:relative;width:100%}.nui .nui-radio__label--translucent{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;color:var(--nui-color-text-disabled,rgba(17, 17, 17, .3));cursor:default}.nui .nui-radio__content{align-items:center;display:flex;flex-wrap:nowrap;justify-content:flex-start;min-height:16px}.nui .nui-radio__mark{background:var(--nui-color-bg-content,#fff);background-size:16px;border:solid 2px;border-color:var(--nui-color-active,#0079aa);border-radius:100%;height:16px;margin:0 7px 0 0;padding:3px;width:16px;flex-shrink:0;flex-grow:0}.nui .nui-radio__mark.nui-radio__mark--disabled{background-color:var(--nui-color-bg-content,#fff);border-color:var(--nui-color-disabled,#b3b3b3);cursor:not-allowed}.nui .nui-radio__glyph{background:var(--nui-color-bg-content,#fff);border-radius:100%;display:none;height:100%;width:100%}.nui .nui-radio__input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;outline:0;overflow:hidden;padding:0;position:absolute;width:1px}.nui .nui-radio__input[disabled],.nui .nui-radio__input.disabled{cursor:not-allowed}.nui .nui-radio__input:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.nui .nui-radio__input:disabled+.nui-radio__mark{background-color:var(--nui-color-bg-content,#fff);border-color:var(--nui-color-disabled,#b3b3b3)}.nui .nui-radio.nui-radio--empty{display:inline-block}.nui .nui-radio.nui-radio--empty .nui-radio__label{justify-content:center;margin:auto;width:auto}.nui .nui-radio.nui-radio--empty .nui-radio__mark{margin:auto}.nui .nui-radio .nui-help-hint{line-height:14px;margin-left:23px;padding:0}.nui .nui-radio--checked .nui-radio__mark{background-color:var(--nui-color-active,#0079aa);border-color:var(--nui-color-active,#0079aa)}.nui .nui-radio--checked .nui-radio__mark>.nui-radio__glyph{display:block}.nui .nui-radio--checked .nui-radio__mark--disabled{background-color:var(--nui-color-off,#4d4d4d);border-color:var(--nui-color-off,#4d4d4d)}.nui .nui-radio--checked .nui-radio__input+.nui-radio__mark{background-color:var(--nui-color-active,#0079aa);border-color:var(--nui-color-active,#0079aa)}.nui .nui-radio--checked .nui-radio__input+.nui-radio__mark>.nui-radio__glyph{display:block}.nui .nui-radio--checked .nui-radio__input:disabled+.nui-radio__mark{background-color:var(--nui-color-disabled,#b3b3b3);border-color:var(--nui-color-disabled,#b3b3b3)}.nui-repeat-item__radio .nui-radio:hover{background:none}.nui-repeat-item__radio .nui-radio .nui-radio__hint{display:none}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioComponent, decorators: [{
type: Component,
args: [{ selector: "nui-radio", encapsulation: ViewEncapsulation.None, host: {
"[class.nui-radio--hovered]": "hovered",
"[class.nui-radio--checked]": "checked",
role: "radio",
}, template: "<div\n class=\"nui-radio\"\n [class.nui-radio--empty]=\"radioTranscludeIsEmpty && !hint\"\n>\n <label\n class=\"nui-radio__label\"\n [class.nui-radio__label--translucent]=\"disabled\"\n (mouseenter)=\"hoverHandler()\"\n (mouseleave)=\"hoverHandler()\"\n >\n <div class=\"nui-radio__content\">\n <input\n #inputViewContainer\n class=\"nui-radio__input\"\n type=\"radio\"\n [value]=\"value\"\n [checked]=\"checked\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"ariaLabel\"\n (change)=\"changeHandler()\"\n (click)=\"onInputClick($event)\"\n />\n\n <div\n class=\"nui-radio__mark\"\n [class.nui-radio__mark--disabled]=\"disabled\"\n >\n <div class=\"nui-radio__glyph\"></div>\n </div>\n\n <div #radioTransclude class=\"nui-radio__transclude\">\n <ng-content></ng-content>\n </div>\n </div>\n\n <div #hintDiv class=\"nui-radio__hint nui-help-hint\">\n <ng-content select=\"[hint]\"></ng-content>\n <ng-container *ngIf=\"!!hint\">\n {{ hint }}\n </ng-container>\n </div>\n </label>\n</div>\n", styles: [".nui-radio-group-inline>.nui-radio-group{display:inline-flex}.nui-radio-group-inline>.nui-radio-group .nui-radio{margin-left:5px}.nui .nui-radio{border-radius:3px;cursor:pointer;line-height:14px}.nui .nui-radio:hover{background-color:var(--nui-color-bg-transparent-hover,rgba(17, 17, 17, .05))}.nui .nui-radio__label{cursor:pointer;font-weight:400;margin:0;min-height:30px;min-width:30px;padding:7px;position:relative;width:100%}.nui .nui-radio__label--translucent{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;color:var(--nui-color-text-disabled,rgba(17, 17, 17, .3));cursor:default}.nui .nui-radio__content{align-items:center;display:flex;flex-wrap:nowrap;justify-content:flex-start;min-height:16px}.nui .nui-radio__mark{background:var(--nui-color-bg-content,#fff);background-size:16px;border:solid 2px;border-color:var(--nui-color-active,#0079aa);border-radius:100%;height:16px;margin:0 7px 0 0;padding:3px;width:16px;flex-shrink:0;flex-grow:0}.nui .nui-radio__mark.nui-radio__mark--disabled{background-color:var(--nui-color-bg-content,#fff);border-color:var(--nui-color-disabled,#b3b3b3);cursor:not-allowed}.nui .nui-radio__glyph{background:var(--nui-color-bg-content,#fff);border-radius:100%;display:none;height:100%;width:100%}.nui .nui-radio__input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;outline:0;overflow:hidden;padding:0;position:absolute;width:1px}.nui .nui-radio__input[disabled],.nui .nui-radio__input.disabled{cursor:not-allowed}.nui .nui-radio__input:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.nui .nui-radio__input:disabled+.nui-radio__mark{background-color:var(--nui-color-bg-content,#fff);border-color:var(--nui-color-disabled,#b3b3b3)}.nui .nui-radio.nui-radio--empty{display:inline-block}.nui .nui-radio.nui-radio--empty .nui-radio__label{justify-content:center;margin:auto;width:auto}.nui .nui-radio.nui-radio--empty .nui-radio__mark{margin:auto}.nui .nui-radio .nui-help-hint{line-height:14px;margin-left:23px;padding:0}.nui .nui-radio--checked .nui-radio__mark{background-color:var(--nui-color-active,#0079aa);border-color:var(--nui-color-active,#0079aa)}.nui .nui-radio--checked .nui-radio__mark>.nui-radio__glyph{display:block}.nui .nui-radio--checked .nui-radio__mark--disabled{background-color:var(--nui-color-off,#4d4d4d);border-color:var(--nui-color-off,#4d4d4d)}.nui .nui-radio--checked .nui-radio__input+.nui-radio__mark{background-color:var(--nui-color-active,#0079aa);border-color:var(--nui-color-active,#0079aa)}.nui .nui-radio--checked .nui-radio__input+.nui-radio__mark>.nui-radio__glyph{display:block}.nui .nui-radio--checked .nui-radio__input:disabled+.nui-radio__mark{background-color:var(--nui-color-disabled,#b3b3b3);border-color:var(--nui-color-disabled,#b3b3b3)}.nui-repeat-item__radio .nui-radio:hover{background:none}.nui-repeat-item__radio .nui-radio .nui-radio__hint{display:none}\n"] }]
}], ctorParameters: () => [{ type: RadioGroupComponent, decorators: [{
type: Optional
}] }, { type: i0.ChangeDetectorRef }, { type: i1.EventBusService }], propDecorators: { value: [{
type: Input
}], valueChange: [{
type: Output
}], hovered: [{
type: Input
}], checked: [{
type: Input
}], hint: [{
type: Input
}], disabled: [{
type: Input
}], ariaLabel: [{
type: Input
}], inputViewContainer: [{
type: ViewChild,
args: ["inputViewContainer", { static: true, read: ViewContainerRef }]
}], radioTransclude: [{
type: ViewChild,
args: ["radioTransclude", { static: true }]
}], contentHints: [{
type: ContentChildren,
args: ["[nui-radio-hint]"]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFkaW8tZ3JvdXAuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9yYWRpby9yYWRpby1ncm91cC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9zcmMvbGliL3JhZGlvL3JhZGlvLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlEQUF5RDtBQUN6RCxFQUFFO0FBQ0YsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSw0REFBNEQ7QUFDNUQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSx1REFBdUQ7QUFDdkQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSw0RUFBNEU7QUFDNUUsK0VBQStFO0FBQy9FLDBFQUEwRTtBQUMxRSxpRkFBaUY7QUFDakYsNkVBQTZFO0FBQzdFLGlCQUFpQjtBQUVqQixPQUFPLEVBRUgsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxlQUFlLEVBQ2YsVUFBVSxFQUNWLFlBQVksRUFDWixVQUFVLEVBQ1YsS0FBSyxFQUdMLFFBQVEsRUFDUixNQUFNLEVBQ04sU0FBUyxFQUNULFNBQVMsRUFFVCxTQUFTLEVBQ1QsZ0JBQWdCLEVBQ2hCLGlCQUFpQixHQUNwQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXdCLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekUsT0FBTyxNQUFNLE1BQU0sY0FBYyxDQUFDO0FBQ2xDLE9BQU8sWUFBWSxNQUFNLG9CQUFvQixDQUFDO0FBRzlDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUNuRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7OztBQUUvRDs7R0FFRztBQW9CSCxNQUFNLE9BQU8sbUJBQW1CO0lB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LFFBQy9CO3dCQUNGLDRCQUE0QixFQUFFLFNBQVM7d0JBQ3ZDLDRCQUE0QixFQUFFLFNBQVM7d0JBQ3ZDLElBQUksRUFBRSxPQUFPO3FCQUNoQjs7MEJBOERJLFFBQVE7dUdBeERHLEtBQUs7c0JBQXBCLEtBQUs7Z0JBS1csV0FBVztzQkFBM0IsTUFBTTtnQkFFUyxPQUFPO3NCQUF0QixLQUFLO2dCQUtVLE9BQU87c0JBQXRCLEtBQUs7Z0JBS1UsSUFBSTtzQkFBbkIsS0FBSztnQkFNSyxRQUFRO3NCQURsQixLQUFLO2dCQWNVLFNBQVM7c0JBQXhCLEtBQUs7Z0JBR0Msa0JBQWtCO3NCQUR4QixTQUFTO3VCQUFDLG9CQUFvQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBSWxFLGVBQWU7c0JBRHJCLFNBQVM7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQVlwQyxZQUFZO3NCQURyQixlQUFlO3VCQUFDLGtCQUFrQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIMKpIDIwMjIgU29sYXJXaW5kcyBXb3JsZHdpZGUsIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyAgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG9cbi8vICBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vclxuLy8gIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vICBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vICBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vICBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyAgVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQge1xuICAgIEFmdGVyQ29udGVudEluaXQsXG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQ29tcG9uZW50LFxuICAgIENvbnRlbnRDaGlsZHJlbixcbiAgICBFbGVtZW50UmVmLFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBmb3J3YXJkUmVmLFxuICAgIElucHV0LFxuICAgIE9uRGVzdHJveSxcbiAgICBPbkluaXQsXG4gICAgT3B0aW9uYWwsXG4gICAgT3V0cHV0LFxuICAgIFF1ZXJ5TGlzdCxcbiAgICBSZW5kZXJlcjIsXG4gICAgVGVtcGxhdGVSZWYsXG4gICAgVmlld0NoaWxkLFxuICAgIFZpZXdDb250YWluZXJSZWYsXG4gICAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCBfaXNOaWwgZnJvbSBcImxvZGFzaC9pc05pbFwiO1xuaW1wb3J0IF9pc1VuZGVmaW5lZCBmcm9tIFwibG9kYXNoL2lzVW5kZWZpbmVkXCI7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tIFwicnhqc1wiO1xuXG5pbXBvcnQgeyBET0NVTUVOVF9DTElDS19FVkVOVCB9IGZyb20gXCIuLi8uLi9jb25zdGFudHMvZXZlbnQuY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBFdmVudEJ1c1NlcnZpY2UgfSBmcm9tIFwiLi4vLi4vc2VydmljZXMvZXZlbnQtYnVzLnNlcnZpY2VcIjtcbmltcG9ydCB7IE51aUZvcm1GaWVsZENvbnRyb2wgfSBmcm9tIFwiLi4vZm9ybS1maWVsZC9wdWJsaWMtYXBpXCI7XG5cbi8qXG4gKiA8ZXhhbXBsZS11cmw+Li8uLi9leGFtcGxlcy9pbmRleC5odG1sIy9yYWRpby1ncm91cDwvZXhhbXBsZS11cmw+XG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiBcIm51aS1yYWRpby1ncm91cFwiLFxuICAgIHRlbXBsYXRlOiBgPGRpdiBjbGFzcz1cIm51aS1yYWRpby1ncm91cFwiIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsXCI+XG4gICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICA8L2Rpdj5gLFxuICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBOdWlGb3JtRmllbGRDb250cm9sLFxuICAgICAgICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gUmFkaW9Hcm91cENvbXBvbmVudCksXG4gICAgICAgICAgICBtdWx0aTogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICAgICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBSYWRpb0dyb3VwQ29tcG9uZW50KSxcbiAgICAgICAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgICB9LFxuICAgIF0sXG4gICAgaG9zdDogeyByb2xlOiBcInJhZGlvZ3JvdXBcIiB9LFxufSlcbmV4cG9ydCBjbGFzcyBSYWRpb0dyb3VwQ29tcG9uZW50XG4gICAgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBPbkRlc3Ryb3ksIENvbnRyb2xWYWx1ZUFjY2Vzc29yXG57XG4gICAgLyoqXG4gICAgICogSW5wdXQgdG8gc2V0IGFyaWEgbGFiZWwgdGV4dFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBhcmlhTGFiZWw6IHN0cmluZyA9IFwiXCI7XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBcIm5hbWVcIiBhdHRyaWJ1dGUgZm9yIGVhY2ggcmFkaW8gYnV0dG9uIGluIHRoZSBncm91cFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBuYW1lOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBTdG9yZXMgdGhlIHZhbHVlIGZyb20gc2VsZWN0ZWQgcmFkaW9cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCB2YWx1ZSgpOiBhbnkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWU7XG4gICAgfVxuICAgIHNldCB2YWx1ZShuZXdWYWx1ZTogYW55KSB7XG4gICAgICAgIGlmICh0aGlzLl92YWx1ZSAhPT0gbmV3VmFsdWUpIHtcbiAgICAgICAgICAgIC8vIFNldCB0aGlzIGJlZm9yZSBwcm9jZWVkaW5nIHRvIGVuc3VyZSBubyBjaXJjdWxhciBsb29wIG9jY3VycyB3aXRoIHNlbGVjdGlvbi5cbiAgICAgICAgICAgIHRoaXMuX3ZhbHVlID0gbmV3VmFsdWU7XG5cbiAgICAgICAgICAgIHRoaXMudXBkYXRlU2VsZWN0ZWRSYWRpb0Zyb21WYWx1ZSgpO1xuICAgICAgICAgICAgdGhpcy5jaGVja1NlbGVjdGVkUmFkaW9CdXR0b24oKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgd2hldGhlciB0aGUgZ3JvdXAgaXMgZGlzYWJsZWRcbiAgICAgKi9cbiAgICBASW5wdXQoKSBwdWJsaWMgZGlzYWJsZWQ/OiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgd2hlbiB0aGUgcmFkaW8gc2VsZWN0aW9uIGNoYW5nZXNcbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgcHVibGljIHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgICBAQ29udGVudENoaWxkcmVuKGZvcndhcmRSZWYoKCkgPT4gUmFkaW9Db21wb25lbnQpLCB7IGRlc2NlbmRhbnRzOiB0cnVlIH0pXG4gICAgcHJpdmF0ZSBjaGlsZHJlbjogUXVlcnlMaXN0PFJhZGlvQ29tcG9uZW50PjtcbiAgICBwcml2YXRlIF92YWx1ZTogYW55ID0gbnVsbDtcbiAgICBwcml2YXRlIHNlbGVjdGVkUmFkaW86IFJhZGlvQ29tcG9uZW50IHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBzdWJzY3JpcHRpb25zID0gbmV3IEFycmF5PFN1YnNjcmlwdGlvbj4oKTtcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIpIHt9XG5cbiAgICBwcml2YXRlIHJlZ2lzdGVyQ2hpbGQoY2hpbGQ6IFJhZGlvQ29tcG9uZW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuc2V0QXR0cmlidXRlKFxuICAgICAgICAgICAgY2hpbGQuaW5wdXRWaWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICAgIFwibmFtZVwiLFxuICAgICAgICAgICAgdGhpcy5uYW1lXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKHRoaXMuc3Vic2NyaWJlVG9SYWRpb0V2ZW50KGNoaWxkKSk7XG4gICAgICAgIC8vIHRpbWVvdXQgdG8gcHJldmVudCBcImV4cHJlc3Npb24gY2hhbmdlZCBhZnRlciBpdCBoYXMgYmVlbiBjaGVja2VkXCIgZXJyb3JcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNldENoaWxkRGlzYWJsZWQoY2hpbGQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmNoaWxkcmVuLnRvQXJyYXkoKS5mb3JFYWNoKChjaGlsZCkgPT4gdGhpcy5yZWdpc3RlckNoaWxkKGNoaWxkKSk7XG4gICAgICAgIHRoaXMuY2hpbGRyZW4uY2hhbmdlcy5zdWJzY3JpYmUoXG4gICAgICAgICAgICAocmFkaW9Db21wb25lbnRRdWVyeUxpc3Q6IFF1ZXJ5TGlzdDxSYWRpb0NvbXBvbmVudD4pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZm9yRWFjaCgoc3ViKSA9PiBzdWIudW5zdWJzY3JpYmUoKSk7XG4gICAgICAgICAgICAgICAgcmFkaW9Db21wb25lbnRRdWVyeUxpc3RcbiAgICAgICAgICAgICAgICAgICAgLnRvQXJyYXkoKVxuICAgICAgICAgICAgICAgICAgICAuZm9yRWFjaCgoY2hpbGQpID0+IHRoaXMucmVnaXN0ZXJDaGlsZChjaGlsZCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBvbkNoYW5nZSh2YWx1ZTogYW55KTogdm9pZCB7fVxuXG4gICAgcHVibGljIG9uVG91Y2hlZCgpOiB2b2lkIHt9XG5cbiAgICBwdWJsaWMgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHZhbHVlOiBhbnkpID0+IHZvaWQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSA9IGZuO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWdpc3Rlck9uVG91Y2hlZChmbjogKCkgPT4gdm9pZCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgICAgIGlmICh0aGlzLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICB0aGlzLmNoaWxkcmVuLnRvQXJyYXkoKS5mb3JFYWNoKHRoaXMuc2V0Q2hpbGREaXNhYmxlZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5mb3JFYWNoKChzdWIpID0+IHN1Yi51bnN1YnNjcmliZSgpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldENoaWxkRGlzYWJsZWQgPSAoY2hpbGQ6IFJhZGlvQ29tcG9uZW50KSA9PiB7XG4gICAgICAgIGlmICghX2lzVW5kZWZpbmVkKHRoaXMuZGlzYWJsZWQpKSB7XG4gICAgICAgICAgICBjaGlsZC5kaXNhYmxlZCA9IHRoaXMuZGlzYWJsZWQ7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBjaGVja1NlbGVjdGVkUmFkaW9CdXR0b24oKSB7XG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGVkUmFkaW8gJiYgIXRoaXMuc2VsZWN0ZWRSYWRpby5jaGVja2VkKSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkUmFkaW8uY2hlY2tlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHVwZGF0ZVNlbGVjdGVkUmFkaW9Gcm9tVmFsdWUoKTogdm9pZCB7XG4gICAgICAgIC8vIElmIHRoZSB2YWx1ZSBhbHJlYWR5IG1hdGNoZXMgdGhlIHNlbGVjdGVkIHJhZGlvLCBkbyBub3RoaW5nLlxuICAgICAgICBjb25zdCBpc0FscmVhZHlTZWxlY3RlZCA9XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkUmFkaW8gIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRSYWRpby52YWx1ZSA9PT0gdGhpcy5fdmFsdWU7XG4gICAgICAgIGlmICh0aGlzLmNoaWxkcmVuICYmICFpc0FscmVhZHlTZWxlY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5jaGlsZHJlbi5mb3JFYWNoKChyYWRpbykgPT4ge1xuICAgICAgICAgICAgICAgIHJhZGlvLmNoZWNrZWQgPSB0aGlzLnZhbHVlID09PSByYWRpby52YWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAocmFkaW8uY2hlY2tlZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkUmFkaW8gPSByYWRpbztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3Vic2NyaWJlVG9SYWRpb0V2ZW50KHJhZGlvOiBSYWRpb0NvbXBvbmVudCk6IFN1YnNjcmlwdGlvbiB7XG4gICAgICAgIHJldHVybiByYWRpby52YWx1ZUNoYW5nZS5zdWJzY3JpYmUoKHZhbHVlOiBhbnkpID0+IHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoIXJhZGlvLmtlZXBGb3JtUHJpc3RpbmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMudmFsdWUpO1xuICAgICAgICAgICAgICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndyaXRlVmFsdWUodGhpcy52YWx1ZSk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBAaWdub3JlXG4gKiBTaG91bGQgYmUgdXNlZCBvbmx5IHdpdGhpbiBudWktcmFkaW8tZ3JvdXAuXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiBcIm51aS1yYWRpb1wiLFxuICAgIHRlbXBsYXRlVXJsOiBcIi4vcmFkaW8uY29tcG9uZW50Lmh0bWxcIixcbiAgICBzdHlsZVVybHM6IFtcIi4vcmFkaW8uY29tcG9uZW50Lmxlc3NcIl0sXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgICBob3N0OiB7XG4gICAgICAgIFwiW2NsYXNzLm51aS1yYWRpby0taG92ZXJlZF1cIjogXCJob3ZlcmVkXCIsXG4gICAgICAgIFwiW2NsYXNzLm51aS1yYWRpby0tY2hlY2tlZF1cIjogXCJjaGVja2VkXCIsXG4gICAgICAgIHJvbGU6IFwicmFkaW9cIixcbiAgICB9LFxufSlcbmV4cG9ydCBjbGFzcyBSYWRpb0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSByYWRpbyBpbnN0YW5jZSB2YWx1ZVxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyB2YWx1ZTogYW55O1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgd2hlbiB0aGUgdmFsdWUgY2hhbmdlc1xuICAgICAqL1xuICAgIEBPdXRwdXQoKSBwdWJsaWMgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICAgIEBJbnB1dCgpIHB1YmxpYyBob3ZlcmVkOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB3aGV0aGVyIHRoZSByYWRpbyBidXR0b24gaXMgc2VsZWN0ZWRcbiAgICAgKi9cbiAgICBASW5wdXQoKSBwdWJsaWMgY2hlY2tlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBoaW50IHRleHQgdW5kZXIgdGhlIHJhZGlvIGJ1dHRvblxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBoaW50Pzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB3aGV0aGVyIHRoZSByYWRpbyBidXR0b24gaXMgZGlzYWJsZWRcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBnZXQgZGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kaXNhYmxlZDtcbiAgICB9XG4gICAgcHVibGljIHNldCBkaXNhYmxlZCh2YWw6IGJvb2xlYW4pIHtcbiAgICAgICAgaWYgKHRoaXMuX2Rpc2FibGVkICE9PSB2YWwpIHtcbiAgICAgICAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3IubWFya0ZvckNoZWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fZGlzYWJsZWQgPSB2YWw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5wdXQgdG8gc2V0IGFyaWEgbGFiZWwgdGV4dFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBhcmlhTGFiZWw6IHN0cmluZyA9IFwiXCI7XG5cbiAgICBAVmlld0NoaWxkKFwiaW5wdXRWaWV3Q29udGFpbmVyXCIsIHsgc3RhdGljOiB0cnVlLCByZWFkOiBWaWV3Q29udGFpbmVyUmVmIH0pXG4gICAgcHVibGljIGlucHV0Vmlld0NvbnRhaW5lcjogVmlld0NvbnRhaW5lclJlZjtcblxuICAgIEBWaWV3Q2hpbGQoXCJyYWRpb1RyYW5zY2x1ZGVcIiwgeyBzdGF0aWM6IHRydWUgfSlcbiAgICBwdWJsaWMgcmFkaW9UcmFuc2NsdWRlOiBFbGVtZW50UmVmO1xuXG4gICAgcHVibGljIHJhZGlvVHJhbnNjbHVkZUlzRW1wdHk6IGJvb2xlYW47XG4gICAgcHVibGljIGtlZXBGb3JtUHJpc3RpbmU6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgcHJpdmF0ZSB0aW1lb3V0SWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIF9kaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgcmVhZG9ubHkgcmFkaW9Hcm91cDogUmFkaW9Hcm91cENvbXBvbmVudCB8IG51bGw7XG5cbiAgICBAQ29udGVudENoaWxkcmVuKFwiW251aS1yYWRpby1oaW50XVwiKVxuICAgIHByb3RlY3RlZCBjb250ZW50SGludHM6IFF1ZXJ5TGlzdDxUZW1wbGF0ZVJlZjxhbnk+PjtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBAT3B0aW9uYWwoKSByYWRpb0dyb3VwOiBSYWRpb0dyb3VwQ29tcG9uZW50LFxuICAgICAgICBwcml2YXRlIGNoYW5nZURldGVjdG9yOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgcHJpdmF0ZSBldmVudEJ1c1NlcnZpY2U6IEV2ZW50QnVzU2VydmljZVxuICAgICkge1xuICAgICAgICB0aGlzLnJhZGlvR3JvdXAgPSByYWRpb0dyb3VwO1xuICAgIH1cblxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMucmFkaW9Hcm91cCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHRoaXMucmFkaW9Hcm91cC52YWx1ZSA9PT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2hlY2tlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5jaGVja2VkKSB7XG4gICAgICAgICAgICAvLyBUT0RPOiByZW1vdmUgdGltZW91dCBpbiB2MTAgTlVJLTQ4NDNcbiAgICAgICAgICAgIC8vIG51aS1yYWRpby1ncm91cCBzaG91bGQgc3Vic2NyaWJlIGJlZm9yZSBldmVudCBpcyBlbWl0dGVkXG4gICAgICAgICAgICB0aGlzLnRpbWVvdXRJZCA9ICg8YW55PnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh0aGlzLnZhbHVlKTtcbiAgICAgICAgICAgIH0sIDApKSBhcyBudW1iZXI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVja3MgaWYgdXNlciBzdXBwbGllZCBhbnkgY29udGVudCBhcyBhIGxhYmVsIGZvciByYWRpbyBidXR0b24gdG8gYWRqdXN0IHN0eWxlcyBmb3IgcmFkaW8gYnV0dG9ucyB3aXRob3V0IGxhYmVsc1xuICAgICAgICB0aGlzLnJhZGlvVHJhbnNjbHVkZUlzRW1wdHkgPSBfaXNOaWwoXG4gICAgICAgICAgICB0aGlzLnJhZGlvVHJhbnNjbHVkZS5uYXRpdmVFbGVtZW50LmZpcnN0Q2hpbGRcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVvdXRJZCk7XG4gICAgfVxuXG4gICAgcHVibGljIGhvdmVySGFuZGxlcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5ob3ZlcmVkID0gIXRoaXMuaG92ZXJlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgY2hhbmdlSGFuZGxlcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5rZWVwRm9ybVByaXN0aW5lID0gZmFsc2U7XG4gICAgICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh0aGlzLnZhbHVlKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25JbnB1dENsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgICAgIC8vIFdlIGhhdmUgdG8gc3RvcCBwcm9wYWdhdGlvbiBmb3IgY2xpY2sgZXZlbnRzIG9uIHRoZSB2aXN1YWwgaGlkZGVuIGlucHV0IGVsZW1lbnQuXG4gICAgICAgIC8vIEJ5IGRlZmF1bHQsIHdoZW4gYSB1c2VyIGNsaWNrcyBvbiBhIGxhYmVsIGVsZW1lbnQsIGEgZ2VuZXJhdGVkIGNsaWNrIGV2ZW50IHdpbGwgYmVcbiAgICAgICAgLy8gZGlzcGF0Y2hlZCBvbiB0aGUgYXNzb2NpYXRlZCBpbnB1dCBlbGVtZW50LiBTaW5jZSB3ZSBhcmUgdXNpbmcgYSBsYWJlbCBlbGVtZW50IGFzIG91clxuICAgICAgICAvLyByb290IGNvbnRhaW5lciwgdGhlIGNsaWNrIGV2ZW50IG9uIHRoZSBgcmFkaW8tYnV0dG9uYCB3aWxsIGJlIGV4ZWN1dGVkIHR3aWNlLlxuICAgICAgICAvLyBUaGUgcmVhbCBjbGljayBldmVudCB3aWxsIGJ1YmJsZSB1cCwgYW5kIHRoZSBnZW5lcmF0ZWQgY2xpY2sgZXZlbnQgYWxzbyB0cmllcyB0byBidWJibGUgdXAuXG4gICAgICAgIC8vIFRoaXMgd2lsbCBsZWFkIHRvIG11bHRpcGxlIGNsaWNrIGV2ZW50cy5cbiAgICAgICAgLy8gUHJldmVudGluZyBidWJibGluZyBmb3IgdGhlIHNlY29uZCBldmVudCB3aWxsIHNvbHZlIHRoYXQgaXNzdWUuXG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICB0aGlzLmV2ZW50QnVzU2VydmljZS5nZXRTdHJlYW0oRE9DVU1FTlRfQ0xJQ0tfRVZFTlQpLm5leHQoZXZlbnQpO1xuICAgIH1cbn1cbiIsIjxkaXZcbiAgICBjbGFzcz1cIm51aS1yYWRpb1wiXG4gICAgW2NsYXNzLm51aS1yYWRpby0tZW1wdHldPVwicmFkaW9UcmFuc2NsdWRlSXNFbXB0eSAmJiAhaGludFwiXG4+XG4gICAgPGxhYmVsXG4gICAgICAgIGNsYXNzPVwibnVpLXJhZGlvX19sYWJlbFwiXG4gICAgICAgIFtjbGFzcy5udWktcmFkaW9fX2xhYmVsLS10cmFuc2x1Y2VudF09XCJkaXNhYmxlZFwiXG4gICAgICAgIChtb3VzZWVudGVyKT1cImhvdmVySGFuZGxlcigpXCJcbiAgICAgICAgKG1vdXNlbGVhdmUpPVwiaG92ZXJIYW5kbGVyKClcIlxuICAgID5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm51aS1yYWRpb19fY29udGVudFwiPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgI2lucHV0Vmlld0NvbnRhaW5lclxuICAgICAgICAgICAgICAgIGNsYXNzPVwibnVpLXJhZGlvX19pbnB1dFwiXG4gICAgICAgICAgICAgICAgdHlwZT1cInJhZGlvXCJcbiAgICAgICAgICAgICAgICBbdmFsdWVdPVwidmFsdWVcIlxuICAgICAgICAgICAgICAgIFtjaGVja2VkXT1cImNoZWNrZWRcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWxcIlxuICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwiY2hhbmdlSGFuZGxlcigpXCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwib25JbnB1dENsaWNrKCRldmVudClcIlxuICAgICAgICAgICAgLz5cblxuICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgIGNsYXNzPVwibnVpLXJhZGlvX19tYXJrXCJcbiAgICAgICAgICAgICAgICBbY2xhc3MubnVpLXJhZGlvX19tYXJrLS1kaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm51aS1yYWRpb19fZ2x5cGhcIj48L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICA8ZGl2ICNyYWRpb1RyYW5zY2x1ZGUgY2xhc3M9XCJudWktcmFkaW9fX3RyYW5zY2x1ZGVcIj5cbiAgICAgICAgICAgICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiAjaGludERpdiBjbGFzcz1cIm51aS1yYWRpb19faGludCBudWktaGVscC1oaW50XCI+XG4gICAgICAgICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbaGludF1cIj48L25nLWNvbnRlbnQ+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiISFoaW50XCI+XG4gICAgICAgICAgICAgICAge3sgaGludCB9fVxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvbGFiZWw+XG48L2Rpdj5cbiJdfQ==