ngnz-time-input
Version:
Material design time input for Angular 8
403 lines • 58.1 kB
JavaScript
var NgnzTimeInputInlineComponent_1;
import * as tslib_1 from "tslib";
import { FocusMonitor } from '@angular/cdk/a11y';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, DoCheck, ElementRef, EventEmitter, HostBinding, HostListener, Input, OnDestroy, OnInit, Optional, Output, Self, } from '@angular/core';
import { ControlValueAccessor, FormControl, FormGroup, NgControl } from '@angular/forms';
import { MatFormFieldControl } from '@angular/material';
import * as moment from 'moment';
import { Subject } from 'rxjs/internal/Subject';
import { debounceTime, filter, takeUntil } from 'rxjs/operators';
import { CssClassCreator } from '../../classes/css-class-creator/css-class-creator';
import { TimeValue } from '../../classes/time-value/time-value';
import { TimeInputMode } from '../../datatypes/time-input-mode.enum';
/**
* Time Input Component.
* The component as a part of UI allows to change time part of Moment data type.
* It looks and uses like a input field.
* It is possible to use mouse wheel and/or control buttons to change time.
* Can be used with [value] attribute or FormControl inside angular reactive form
* @author Aleksey Nazarenko
* @version 0.0.1
*/
let NgnzTimeInputInlineComponent = NgnzTimeInputInlineComponent_1 = class NgnzTimeInputInlineComponent {
constructor(_fm, _elRef, _chDetector, ngControl) {
this._fm = _fm;
this._elRef = _elRef;
this._chDetector = _chDetector;
this.ngControl = ngControl;
this.BUTTON_HOST_ATTRIBUTES = [
'mat-button',
'mat-flat-button',
'mat-icon-button',
'mat-raised-button',
'mat-stroked-button',
'mat-mini-fab',
'mat-fab',
];
this.stateChanges = new Subject();
this._hoursControl = new FormControl(null);
this._minutesControl = new FormControl(null);
this._secondsControl = new FormControl(null);
this.parts = new FormGroup({
hours: this._hoursControl,
minutes: this._minutesControl,
seconds: this._secondsControl,
});
this._required = false;
this._disabled = false;
this._unsubscribe = new Subject();
this._debounceTime = 300;
this._focused = false;
this.controlType = 'ngnz-time-input-inline';
this.id = [
this.controlType,
++NgnzTimeInputInlineComponent_1.nextId,
].join('-');
this.describedBy = '';
this.inputClassesConf = {};
this.buttonDecreaseClassesConf = {};
this.buttonIncreaseClassesConf = {};
// enum defining of time change mode: Limit, Circular, CircularForwarding
this.inputMode = TimeInputMode.CircularForwarding;
// do not show control buttons; normally buttons are shown on focus
this.noButtons = false;
// always show control buttons; normally buttons are shown on focus
this.showButtons = false;
// do not show seconds block if it is not necessary
this.noSeconds = false;
// mat icon name for descrease controll button
this.decreaseBtnIconName = 'remove';
// mat icon name for increase control button
this.increaseBtnIconName = 'add';
this.timeChange = new EventEmitter();
this._timeChange = new EventEmitter();
this._onChange = function (_) { };
this._onTouched = function (_) { };
this._timeValue = new TimeValue();
if (this.ngControl !== null) {
this.ngControl.valueAccessor = this;
}
this._fm
.monitor(this._elRef.nativeElement, true)
.subscribe((origin) => {
if (origin == null) {
this._onTouched(this);
}
this.focused = !!origin;
this.detectChangies();
});
this._hoursControl.valueChanges
.pipe(filter((data) => +data !== this._timeValue.hours), takeUntil(this._unsubscribe.asObservable()))
.subscribe((data) => {
this._timeValue.setHours(+data);
});
this._timeValue.hoursChanged
.pipe(takeUntil(this._unsubscribe.asObservable()))
.subscribe((data) => {
this._hoursControl.setValue(this.padNumber(data));
this._timeChange.emit(this.value);
});
this._minutesControl.valueChanges
.pipe(filter((data) => +data !== this._timeValue.minutes), takeUntil(this._unsubscribe.asObservable()))
.subscribe((data) => {
this._timeValue.setMinutes(+data);
});
this._timeValue.minutesChanged
.pipe(takeUntil(this._unsubscribe.asObservable()))
.subscribe((data) => {
this._minutesControl.setValue(this.padNumber(data));
this._timeChange.emit(this.value);
});
this._secondsControl.valueChanges
.pipe(filter((data) => +data !== this._timeValue.seconds), takeUntil(this._unsubscribe.asObservable()))
.subscribe((data) => {
this._timeValue.setSeconds(+data);
});
this._timeValue.secondsChanged
.pipe(takeUntil(this._unsubscribe.asObservable()))
.subscribe((data) => {
this._secondsControl.setValue(this.padNumber(data));
this._timeChange.emit(this.value);
});
this._timeChange
.pipe(debounceTime(this._debounceTime), takeUntil(this._unsubscribe.asObservable()))
.subscribe((data) => {
this.timeChange.emit(data);
});
}
get focused() {
return this._focused;
}
set focused(val) {
this._focused = val;
}
get shouldLabelFloat() {
return this.focused || !this.empty;
}
// placeholder // FIXME: is to show when value is not set
get placeholder() {
return this._placeholder;
}
set placeholder(placeholder) {
this._placeholder = placeholder;
}
get value() {
const out = moment({
years: this._inputValue.year(),
months: this._inputValue.month(),
days: this._inputValue.date(),
hours: this._timeValue.hours,
minutes: this._timeValue.minutes,
seconds: this._timeValue.seconds,
});
return out;
}
set value(value) {
this._inputValue = (!!value && moment.isMoment(value) && value) || moment();
const hours = +this._inputValue.hours();
const minutes = +this._inputValue.minutes();
const seconds = +this._inputValue.seconds();
this._timeValue.setHours(hours).setMinutes(minutes).setSeconds(seconds);
this.detectChangies();
}
get required() {
return this._required;
}
set required(req) {
this._required = coerceBooleanProperty(req);
this.detectChangies();
}
get disabled() {
return this._disabled;
}
set disabled(value) {
this._disabled = coerceBooleanProperty(value);
this._disabled ? this.parts.disable() : this.parts.enable();
this.detectChangies();
}
// one character to separate hours from minutes and minutes from seconds; default is ':'
get splitter() {
return this._splitter || ':';
}
set splitter(value) {
this._splitter = ('' + value).slice(0);
}
ngOnInit() {
this._timeValue.inputMode = this.inputMode;
this._cssClassChange();
}
ngDoCheck() {
this._cssClassChange();
}
ngOnDestroy() {
this._unsubscribe.next();
this._unsubscribe.complete();
this._fm.stopMonitoring(this._elRef.nativeElement);
}
detectChangies() {
this.stateChanges.next();
this._cssClassChange();
this._chDetector.detectChanges();
}
get errorState() {
return !!(!!this.ngControl &&
this.ngControl.touched &&
this.ngControl.invalid);
}
get empty() {
const value = this.parts.value;
return (!(value.hours && value.hours >= 0) &&
!(value.minutes && value.minutes >= 0) &&
!(value.seconds && value.minutes >= 0));
}
setDescribedByIds(ids) {
this.describedBy = ids.join(' ');
}
onContainerClick(event) {
}
writeValue(value) {
this.value = value;
}
registerOnChange(fn) {
this._onChange = (_) => {
fn(_);
};
}
registerOnTouched(fn) {
this._onTouched = (_) => {
fn(_);
};
}
setDisabledState(isDisabled) {
this.disabled = isDisabled;
}
btnsAction(partName, step) {
switch (partName) {
case 'hours':
this._timeValue.setHours(this._timeValue.hours + step);
break;
case 'minutes':
this._timeValue.setMinutes(this._timeValue.minutes + step);
break;
case 'seconds':
this._timeValue.setSeconds(this._timeValue.seconds + step);
break;
}
this.detectChangies();
}
btnIncrease($event, partName) {
$event.preventDefault();
$event.stopPropagation();
this.btnsAction(partName, 1);
}
btnDecrease($event, partName) {
$event.preventDefault();
$event.stopPropagation();
this.btnsAction(partName, -1);
}
padNumber(value, places = 2) {
return String(value).padStart(places, '0');
}
wheel($event, partName) {
if (this.focused) {
$event.preventDefault();
$event.stopPropagation();
const step = $event.deltaY > 0 ? -1 : $event.deltaY < 0 ? 1 : 0;
this.btnsAction(partName, step);
}
}
// rearrange additional and conditional classes
_cssClassChange() {
this._defineCssButtons();
this._defineCssInputs();
}
// detect type of control buttons in material design
_defineMatButtonType() {
const out = this.buttonMatTypeClassName = (!!this.buttonMatType && ('' + this.buttonMatType))
|| this.BUTTON_HOST_ATTRIBUTES.filter((attribute) => {
return this._elRef.nativeElement.hasAttribute(attribute);
}).join(' ');
return out;
}
// detect color of control buttons in material design
_defineMatButtonColor() {
return this.colorClassName = !!this.color ? 'mat-' + this.color : '';
}
// combine additional and conditional classes for control buttons
_defineCssButtons() {
const cssClasses = new CssClassCreator()
.appendCssClasses(this.colorClassName || this._defineMatButtonColor())
.appendCssClasses(this.buttonMatTypeClassName || this._defineMatButtonType())
.appendCssClasses(this.buttonsClasses)
.generate();
const cssCreatorLeft = new CssClassCreator()
.appendCssClasses(this.buttonDecreaseClasses)
.appendCssClasses(cssClasses);
const cssCreatorRight = new CssClassCreator()
.appendCssClasses(this.buttonIncreaseClasses)
.appendCssClasses(cssClasses);
Object.assign(this.buttonDecreaseClassesConf, cssCreatorLeft.generate());
Object.assign(this.buttonIncreaseClassesConf, cssCreatorRight.generate());
}
// combine additional and conditional classes for inputs
_defineCssInputs() {
const cssCreator = new CssClassCreator()
.appendCssClasses({
'ngnz-lr-margin-1em': () => (!this.showButtons && !this.noButtons && !this.focused),
})
.appendCssClasses(this.inputClasses);
Object.assign(this.inputClassesConf, cssCreator.generate());
}
};
NgnzTimeInputInlineComponent.nextId = 0;
NgnzTimeInputInlineComponent.ctorParameters = () => [
{ type: FocusMonitor },
{ type: ElementRef },
{ type: ChangeDetectorRef },
{ type: NgControl, decorators: [{ type: Optional }, { type: Self }] }
];
tslib_1.__decorate([
HostBinding()
], NgnzTimeInputInlineComponent.prototype, "id", void 0);
tslib_1.__decorate([
HostBinding('attr.aria-describedby')
], NgnzTimeInputInlineComponent.prototype, "describedBy", void 0);
tslib_1.__decorate([
HostBinding('class.floating')
], NgnzTimeInputInlineComponent.prototype, "shouldLabelFloat", null);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "color", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "buttonMatType", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "inputClasses", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "buttonsClasses", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "buttonDecreaseClasses", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "buttonIncreaseClasses", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "placeholder", null);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "inputMode", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "value", null);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "required", null);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "disabled", null);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "splitter", null);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "noButtons", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "showButtons", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "noSeconds", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "decreaseBtnIconName", void 0);
tslib_1.__decorate([
Input()
], NgnzTimeInputInlineComponent.prototype, "increaseBtnIconName", void 0);
tslib_1.__decorate([
Output()
], NgnzTimeInputInlineComponent.prototype, "timeChange", void 0);
tslib_1.__decorate([
HostListener('timeChange', ['$event']),
HostListener('change', ['$event'])
], NgnzTimeInputInlineComponent.prototype, "_onChange", void 0);
NgnzTimeInputInlineComponent = NgnzTimeInputInlineComponent_1 = tslib_1.__decorate([
Component({
selector: 'ngnz-time-input-inline',
template: "<div class=\"ngnz-time-group\" [formGroup]=\"parts\">\n \n <div class=\"ngnz-hours-block\">\n <button\n *ngIf=\"showButtons || (!noButtons && focused)\"\n class=\"ngnz-button\"\n [ngClass]=\"buttonDecreaseClassesConf\"\n (click)=\"btnDecrease($event, 'hours')\"\n >\n <mat-icon class=\"ngnz-square-1em\">{{\n decreaseBtnIconName\n }}</mat-icon>\n </button>\n <input\n #hours\n class=\"ngnz-hours ngnz-width-2em\"\n formControlName=\"hours\"\n readonly\n [matTooltip]=\"focused ? '\u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u043A\u043E\u043B\u0435\u0441\u043E \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438' : ''\"\n [ngClass]=\"inputClassesConf\"\n (wheel)=\"wheel($event, 'hours')\"\n />\n <button\n *ngIf=\"showButtons || (!noButtons && focused)\"\n class=\"ngnz-button\"\n [ngClass]=\"buttonIncreaseClassesConf\"\n (click)=\"btnIncrease($event, 'hours')\"\n >\n <mat-icon class=\"ngnz-square-1em\">{{\n increaseBtnIconName\n }}</mat-icon>\n </button>\n </div>\n\n <div class=\"ngnz-splitter\">{{ splitter }}</div>\n\n <div class=\"ngnz-minutes-block\">\n <button\n *ngIf=\"showButtons || (!noButtons && focused)\"\n class=\"ngnz-button\"\n [ngClass]=\"buttonDecreaseClassesConf\"\n (click)=\"btnDecrease($event, 'minutes')\"\n >\n <mat-icon class=\"ngnz-square-1em\">{{\n decreaseBtnIconName\n }}</mat-icon>\n </button>\n <input\n #minutes\n class=\"ngnz-minutes ngnz-width-2em\"\n formControlName=\"minutes\"\n readonly\n [matTooltip]=\"focused ? '\u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u043A\u043E\u043B\u0435\u0441\u043E \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438' : ''\"\n [ngClass]=\"inputClassesConf\"\n (wheel)=\"wheel($event, 'minutes')\"\n />\n <button\n *ngIf=\"showButtons || (!noButtons && focused)\"\n class=\"ngnz-button\"\n [ngClass]=\"buttonIncreaseClassesConf\"\n (click)=\"btnIncrease($event, 'minutes')\"\n >\n <mat-icon class=\"ngnz-square-1em\">{{\n increaseBtnIconName\n }}</mat-icon>\n </button>\n </div>\n\n <div class=\"ngnz-splitter\" *ngIf=\"!noSeconds\">{{ splitter }}</div>\n\n <div class=\"ngnz-seconds-block\" *ngIf=\"!noSeconds\">\n <button\n *ngIf=\"showButtons || (!noButtons && focused)\"\n class=\"ngnz-button\"\n [ngClass]=\"buttonDecreaseClassesConf\"\n (click)=\"btnDecrease($event, 'seconds')\"\n >\n <mat-icon class=\"ngnz-square-1em\">{{\n decreaseBtnIconName\n }}</mat-icon>\n </button>\n <input\n #seconds\n class=\"ngnz-seconds ngnz-width-2em\"\n formControlName=\"seconds\"\n readonly\n [matTooltip]=\"focused ? '\u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u043A\u043E\u043B\u0435\u0441\u043E \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438' : ''\"\n [ngClass]=\"inputClassesConf\"\n (wheel)=\"wheel($event, 'seconds')\"\n />\n <button\n *ngIf=\"showButtons || (!noButtons && focused)\"\n class=\"ngnz-button\"\n [ngClass]=\"buttonIncreaseClassesConf\"\n (click)=\"btnIncrease($event, 'seconds')\"\n >\n <mat-icon class=\"ngnz-square-1em\">{{\n increaseBtnIconName\n }}</mat-icon>\n </button>\n </div>\n \n</div>\n",
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: MatFormFieldControl,
useExisting: NgnzTimeInputInlineComponent_1,
},
],
styles: [".ngnz-time-group{display:flex!important;justify-content:center!important;align-items:center!important;padding:0!important}.ngnz-time-group .ngnz-hours-block,.ngnz-time-group .ngnz-minutes-block,.ngnz-time-group .ngnz-seconds-block,.ngnz-time-group .ngnz-splitter{display:flex!important;align-items:center!important;justify-content:center!important;flex-direction:row!important}.ngnz-time-group .ngnz-hours-block .ngnz-hours,.ngnz-time-group .ngnz-hours-block .ngnz-minutes,.ngnz-time-group .ngnz-hours-block .ngnz-seconds,.ngnz-time-group .ngnz-minutes-block .ngnz-hours,.ngnz-time-group .ngnz-minutes-block .ngnz-minutes,.ngnz-time-group .ngnz-minutes-block .ngnz-seconds,.ngnz-time-group .ngnz-seconds-block .ngnz-hours,.ngnz-time-group .ngnz-seconds-block .ngnz-minutes,.ngnz-time-group .ngnz-seconds-block .ngnz-seconds,.ngnz-time-group .ngnz-splitter .ngnz-hours,.ngnz-time-group .ngnz-splitter .ngnz-minutes,.ngnz-time-group .ngnz-splitter .ngnz-seconds{color:inherit;border:none;outline:0;font:inherit;text-align:center!important;vertical-align:middle!important;padding:0!important}.ngnz-time-group .ngnz-hours-block .ngnz-button,.ngnz-time-group .ngnz-minutes-block .ngnz-button,.ngnz-time-group .ngnz-seconds-block .ngnz-button,.ngnz-time-group .ngnz-splitter .ngnz-button{cursor:pointer;padding:0!important;font-weight:700;display:flex!important;justify-content:center!important;align-items:center!important;line-height:inherit!important;font-size:inherit!important;box-sizing:border-box;position:relative;top:0}.ngnz-time-group .ngnz-hours-block .ngnz-button ::ng-deep .mat-button-wrapper,.ngnz-time-group .ngnz-minutes-block .ngnz-button ::ng-deep .mat-button-wrapper,.ngnz-time-group .ngnz-seconds-block .ngnz-button ::ng-deep .mat-button-wrapper,.ngnz-time-group .ngnz-splitter .ngnz-button ::ng-deep .mat-button-wrapper{line-height:inherit!important;padding:0!important}.ngnz-time-group .ngnz-hours-block .ngnz-button ::ng-deep .mat-button-base,.ngnz-time-group .ngnz-minutes-block .ngnz-button ::ng-deep .mat-button-base,.ngnz-time-group .ngnz-seconds-block .ngnz-button ::ng-deep .mat-button-base,.ngnz-time-group .ngnz-splitter .ngnz-button ::ng-deep .mat-button-base{min-width:inherit!important}.ngnz-time-group .ngnz-splitter{opacity:0;min-width:1em!important;transition:opacity .2s!important}:host.floating .ngnz-splitter{opacity:1}.ngnz-lr-margin-1em{margin-left:1em;margin-right:1em}.ngnz-square-1em,.ngnz-time-group .ngnz-hours-block .ngnz-button,.ngnz-time-group .ngnz-minutes-block .ngnz-button,.ngnz-time-group .ngnz-seconds-block .ngnz-button,.ngnz-time-group .ngnz-splitter .ngnz-button,.ngnz-width-1em{width:1em!important;min-width:1em!important}.ngnz-height-1em,.ngnz-square-1em,.ngnz-time-group .ngnz-hours-block .ngnz-button,.ngnz-time-group .ngnz-minutes-block .ngnz-button,.ngnz-time-group .ngnz-seconds-block .ngnz-button,.ngnz-time-group .ngnz-splitter .ngnz-button{height:1em!important;min-height:1em!important}.ngnz-width-2em{width:2em!important;min-width:2em!important}.ngnz-height-2em{height:2em!important;min-height:2em!important}.material-icons{font-size:inherit!important}"]
}),
tslib_1.__param(3, Optional()), tslib_1.__param(3, Self())
], NgnzTimeInputInlineComponent);
export { NgnzTimeInputInlineComponent };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmduei10aW1lLWlucHV0LWlubGluZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ256LXRpbWUtaW5wdXQvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9uZ256LXRpbWUtaW5wdXQtaW5saW5lL25nbnotdGltZS1pbnB1dC1pbmxpbmUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzlELE9BQU8sRUFDSCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxPQUFPLEVBQ1AsVUFBVSxFQUNWLFlBQVksRUFDWixXQUFXLEVBQ1gsWUFBWSxFQUNaLEtBQUssRUFDTCxTQUFTLEVBQ1QsTUFBTSxFQUNOLFFBQVEsRUFDUixNQUFNLEVBQ04sSUFBSSxHQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3pGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3hELE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbURBQW1ELENBQUM7QUFDcEYsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBR2hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUdyRTs7Ozs7Ozs7R0FRRztBQWFILElBQWEsNEJBQTRCLG9D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QUFtQjtnQkFDNUIsV0FBVyxFQUFFLDhCQUE0QjthQUM1QztTQUNKOztLQUNKLENBQUM7SUE4S08sbUJBQUEsUUFBUSxFQUFFLENBQUEsRUFBRSxtQkFBQSxJQUFJLEVBQUUsQ0FBQTtHQTdLZCw0QkFBNEIsQ0FzWXhDO1NBdFlZLDRCQUE0QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEZvY3VzTW9uaXRvciB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQge1xuICAgIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICAgIENoYW5nZURldGVjdG9yUmVmLFxuICAgIENvbXBvbmVudCxcbiAgICBEb0NoZWNrLFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIEhvc3RCaW5kaW5nLFxuICAgIEhvc3RMaXN0ZW5lcixcbiAgICBJbnB1dCxcbiAgICBPbkRlc3Ryb3ksXG4gICAgT25Jbml0LFxuICAgIE9wdGlvbmFsLFxuICAgIE91dHB1dCxcbiAgICBTZWxmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBOZ0NvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBNYXRGb3JtRmllbGRDb250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwnO1xuaW1wb3J0ICogYXMgbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcy9pbnRlcm5hbC9TdWJqZWN0JztcbmltcG9ydCB7IGRlYm91bmNlVGltZSwgZmlsdGVyLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IENzc0NsYXNzQ3JlYXRvciB9IGZyb20gJy4uLy4uL2NsYXNzZXMvY3NzLWNsYXNzLWNyZWF0b3IvY3NzLWNsYXNzLWNyZWF0b3InO1xuaW1wb3J0IHsgVGltZVZhbHVlIH0gZnJvbSAnLi4vLi4vY2xhc3Nlcy90aW1lLXZhbHVlL3RpbWUtdmFsdWUnO1xuaW1wb3J0IHsgQ3NzQ2xhc3NlcyB9IGZyb20gJy4uLy4uL2RhdGF0eXBlcy9jc3MtY2xhc3Nlcyc7XG5pbXBvcnQgeyBDc3NDbGFzc2VzRGVmaW5pdGlvbiB9IGZyb20gJy4uLy4uL2RhdGF0eXBlcy9jc3MtY2xhc3Nlcy1kZWZpbml0aW9uJztcbmltcG9ydCB7IFRpbWVJbnB1dE1vZGUgfSBmcm9tICcuLi8uLi9kYXRhdHlwZXMvdGltZS1pbnB1dC1tb2RlLmVudW0nO1xuaW1wb3J0IHsgVGltZVZhbHVlVHlwZSB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvdGltZS12YWx1ZS10eXBlJztcblxuLyoqXG4gKiBUaW1lIElucHV0IENvbXBvbmVudC5cbiAqIFRoZSBjb21wb25lbnQgYXMgYSBwYXJ0IG9mIFVJIGFsbG93cyB0byBjaGFuZ2UgdGltZSBwYXJ0IG9mIE1vbWVudCBkYXRhIHR5cGUuXG4gKiBJdCBsb29rcyBhbmQgdXNlcyBsaWtlIGEgaW5wdXQgZmllbGQuXG4gKiBJdCBpcyBwb3NzaWJsZSB0byB1c2UgbW91c2Ugd2hlZWwgYW5kL29yIGNvbnRyb2wgYnV0dG9ucyB0byBjaGFuZ2UgdGltZS5cbiAqIENhbiBiZSB1c2VkIHdpdGggW3ZhbHVlXSBhdHRyaWJ1dGUgb3IgRm9ybUNvbnRyb2wgaW5zaWRlIGFuZ3VsYXIgcmVhY3RpdmUgZm9ybVxuICogQGF1dGhvciBBbGVrc2V5IE5hemFyZW5rb1xuICogQHZlcnNpb24gMC4wLjFcbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICduZ256LXRpbWUtaW5wdXQtaW5saW5lJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vbmduei10aW1lLWlucHV0LWlubGluZS5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vbmduei10aW1lLWlucHV0LWlubGluZS5jb21wb25lbnQuc2NzcyddLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBNYXRGb3JtRmllbGRDb250cm9sLFxuICAgICAgICAgICAgdXNlRXhpc3Rpbmc6IE5nbnpUaW1lSW5wdXRJbmxpbmVDb21wb25lbnQsXG4gICAgICAgIH0sXG4gICAgXSxcbn0pXG5leHBvcnQgY2xhc3MgTmduelRpbWVJbnB1dElubGluZUNvbXBvbmVudFxuICAgIGltcGxlbWVudHNcbiAgICBDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgICBNYXRGb3JtRmllbGRDb250cm9sPG1vbWVudC5Nb21lbnQ+LFxuICAgIE9uSW5pdCxcbiAgICBPbkRlc3Ryb3ksXG4gICAgRG9DaGVjayB7XG4gICAgc3RhdGljIG5leHRJZCA9IDA7XG4gICAgcmVhZG9ubHkgQlVUVE9OX0hPU1RfQVRUUklCVVRFUyA9IFtcbiAgICAgICAgJ21hdC1idXR0b24nLFxuICAgICAgICAnbWF0LWZsYXQtYnV0dG9uJyxcbiAgICAgICAgJ21hdC1pY29uLWJ1dHRvbicsXG4gICAgICAgICdtYXQtcmFpc2VkLWJ1dHRvbicsXG4gICAgICAgICdtYXQtc3Ryb2tlZC1idXR0b24nLFxuICAgICAgICAnbWF0LW1pbmktZmFiJyxcbiAgICAgICAgJ21hdC1mYWInLFxuICAgIF07XG4gICAgc3RhdGVDaGFuZ2VzID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgICBwcm90ZWN0ZWQgX3RpbWVWYWx1ZTogVGltZVZhbHVlO1xuICAgIHByb3RlY3RlZCBfaW5wdXRWYWx1ZTogbW9tZW50Lk1vbWVudDtcblxuICAgIHByb3RlY3RlZCBfaG91cnNDb250cm9sID0gbmV3IEZvcm1Db250cm9sKG51bGwpO1xuICAgIHByb3RlY3RlZCBfbWludXRlc0NvbnRyb2wgPSBuZXcgRm9ybUNvbnRyb2wobnVsbCk7XG4gICAgcHJvdGVjdGVkIF9zZWNvbmRzQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbChudWxsKTtcbiAgICBwdWJsaWMgcGFydHM6IEZvcm1Hcm91cCA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgICBob3VyczogdGhpcy5faG91cnNDb250cm9sLFxuICAgICAgICBtaW51dGVzOiB0aGlzLl9taW51dGVzQ29udHJvbCxcbiAgICAgICAgc2Vjb25kczogdGhpcy5fc2Vjb25kc0NvbnRyb2wsXG4gICAgfSk7XG4gICAgcHJvdGVjdGVkIF9wbGFjZWhvbGRlcjogc3RyaW5nO1xuICAgIHByb3RlY3RlZCBfcmVxdWlyZWQgPSBmYWxzZTtcbiAgICBwcm90ZWN0ZWQgX2Rpc2FibGVkID0gZmFsc2U7XG4gICAgcHJvdGVjdGVkIF91bnN1YnNjcmliZSA9IG5ldyBTdWJqZWN0KCk7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IF9kZWJvdW5jZVRpbWUgPSAzMDA7XG4gICAgX2ZvY3VzZWQgPSBmYWxzZTtcbiAgICBnZXQgZm9jdXNlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ZvY3VzZWQ7XG4gICAgfVxuICAgIHNldCBmb2N1c2VkKHZhbDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9mb2N1c2VkID0gdmFsO1xuICAgIH1cbiAgICBjb250cm9sVHlwZSA9ICduZ256LXRpbWUtaW5wdXQtaW5saW5lJztcbiAgICBhdXRvZmlsbGVkPzogYm9vbGVhbjtcbiAgICBASG9zdEJpbmRpbmcoKSBpZCA9IFtcbiAgICAgICAgdGhpcy5jb250cm9sVHlwZSxcbiAgICAgICAgKytOZ256VGltZUlucHV0SW5saW5lQ29tcG9uZW50Lm5leHRJZCxcbiAgICBdLmpvaW4oJy0nKTtcbiAgICBASG9zdEJpbmRpbmcoJ2F0dHIuYXJpYS1kZXNjcmliZWRieScpIGRlc2NyaWJlZEJ5ID0gJyc7XG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5mbG9hdGluZycpIGdldCBzaG91bGRMYWJlbEZsb2F0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c2VkIHx8ICF0aGlzLmVtcHR5O1xuICAgIH1cblxuXG4gICAgLy8gZnJvbSBNYXRlcmlhbCB0aGVtZTogcHJpbWFyeSwgYWNjZW50LCB3YXJuXG4gICAgQElucHV0KCkgY29sb3I6IHN0cmluZztcbiAgICBwdWJsaWMgY29sb3JDbGFzc05hbWU6IHN0cmluZztcblxuICAgIC8vIHR5cGUgb2YgY29udHJvbCBidXR0b25zIGluIE1hdGVyaWFsIERlc2lnbjogbWF0LWJ1dHRvbiwgbWF0LXJhaXNlZC1idXR0b24gZXRjLlxuICAgIEBJbnB1dCgpIGJ1dHRvbk1hdFR5cGU6IHN0cmluZztcbiAgICBwdWJsaWMgYnV0dG9uTWF0VHlwZUNsYXNzTmFtZTogc3RyaW5nO1xuXG5cbiAgICAvLyBhZGRpdGlvbmFsIGNzcyBjbGFzc2VzIGZvciBpbnB1dCBmaWVsZHMgb2YgaG91cnMsIG1pbnV0ZXMgYW5kIHNlY29uZHNcbiAgICBASW5wdXQoKSBpbnB1dENsYXNzZXM6IENzc0NsYXNzZXNEZWZpbml0aW9uO1xuICAgIGlucHV0Q2xhc3Nlc0NvbmY6IENzc0NsYXNzZXMgPSB7fTtcblxuXG4gICAgLy8gYWRkaXRpb25hbCBjc3MgY2xhc3NlcyBmb3IgY29udHJvbCBidXR0b25zXG4gICAgQElucHV0KCkgYnV0dG9uc0NsYXNzZXM6IENzc0NsYXNzZXNEZWZpbml0aW9uO1xuXG4gICAgLy8gYWRkaXRpb25hbCBjc3MgY2xhc3NlcyBmb3IgZGVjcmVhc2UgYnV0dG9uIG9uIHRoZSBsZWZ0IHNpZGUgb2YgdGhlIGlucHV0IGZpZWxlZFxuICAgIEBJbnB1dCgpIGJ1dHRvbkRlY3JlYXNlQ2xhc3NlczogQ3NzQ2xhc3Nlc0RlZmluaXRpb247XG5cbiAgICAvLyBhZGRpdGlvbmFsIGNzcyBjbGFzc2VzIGZvciBpbmNyZWFzZSBidXR0b24gb24gdGhlIHJpZ2h0IHNpZGUgb2YgdGhlIGlucHV0IGZpZWxlZFxuICAgIEBJbnB1dCgpIGJ1dHRvbkluY3JlYXNlQ2xhc3NlczogQ3NzQ2xhc3Nlc0RlZmluaXRpb247XG4gICAgYnV0dG9uRGVjcmVhc2VDbGFzc2VzQ29uZjogQ3NzQ2xhc3NlcyA9IHt9O1xuICAgIGJ1dHRvbkluY3JlYXNlQ2xhc3Nlc0NvbmY6IENzc0NsYXNzZXMgPSB7fTtcblxuICAgIHB1YmxpYyBjc3NJbnA6IENzc0NsYXNzZXM7XG5cblxuICAgIC8vIHBsYWNlaG9sZGVyIC8vIEZJWE1FOiBpcyB0byBzaG93IHdoZW4gdmFsdWUgaXMgbm90IHNldFxuICAgIEBJbnB1dCgpXG4gICAgZ2V0IHBsYWNlaG9sZGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcGxhY2Vob2xkZXI7XG4gICAgfVxuICAgIHNldCBwbGFjZWhvbGRlcihwbGFjZWhvbGRlcikge1xuICAgICAgICB0aGlzLl9wbGFjZWhvbGRlciA9IHBsYWNlaG9sZGVyO1xuICAgIH1cblxuXG4gICAgLy8gZW51bSBkZWZpbmluZyBvZiB0aW1lIGNoYW5nZSBtb2RlOiBMaW1pdCwgQ2lyY3VsYXIsIENpcmN1bGFyRm9yd2FyZGluZ1xuICAgIEBJbnB1dCgpIGlucHV0TW9kZTogVGltZUlucHV0TW9kZSA9IFRpbWVJbnB1dE1vZGUuQ2lyY3VsYXJGb3J3YXJkaW5nO1xuXG4gICAgQElucHV0KClcbiAgICBnZXQgdmFsdWUoKTogbW9tZW50Lk1vbWVudCB7XG4gICAgICAgIGNvbnN0IG91dCA9IG1vbWVudCh7XG4gICAgICAgICAgICB5ZWFyczogdGhpcy5faW5wdXRWYWx1ZS55ZWFyKCksXG4gICAgICAgICAgICBtb250aHM6IHRoaXMuX2lucHV0VmFsdWUubW9udGgoKSxcbiAgICAgICAgICAgIGRheXM6IHRoaXMuX2lucHV0VmFsdWUuZGF0ZSgpLFxuICAgICAgICAgICAgaG91cnM6IHRoaXMuX3RpbWVWYWx1ZS5ob3VycyxcbiAgICAgICAgICAgIG1pbnV0ZXM6IHRoaXMuX3RpbWVWYWx1ZS5taW51dGVzLFxuICAgICAgICAgICAgc2Vjb25kczogdGhpcy5fdGltZVZhbHVlLnNlY29uZHMsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cbiAgICBzZXQgdmFsdWUodmFsdWU6IG1vbWVudC5Nb21lbnQpIHtcbiAgICAgICAgdGhpcy5faW5wdXRWYWx1ZSA9ICghIXZhbHVlICYmIG1vbWVudC5pc01vbWVudCh2YWx1ZSkgJiYgdmFsdWUpIHx8IG1vbWVudCgpO1xuICAgICAgICBjb25zdCBob3VycyA9ICt0aGlzLl9pbnB1dFZhbHVlLmhvdXJzKCk7XG4gICAgICAgIGNvbnN0IG1pbnV0ZXMgPSArdGhpcy5faW5wdXRWYWx1ZS5taW51dGVzKCk7XG4gICAgICAgIGNvbnN0IHNlY29uZHMgPSArdGhpcy5faW5wdXRWYWx1ZS5zZWNvbmRzKCk7XG4gICAgICAgIHRoaXMuX3RpbWVWYWx1ZS5zZXRIb3Vycyhob3Vycykuc2V0TWludXRlcyhtaW51dGVzKS5zZXRTZWNvbmRzKHNlY29uZHMpO1xuICAgICAgICB0aGlzLmRldGVjdENoYW5naWVzKCk7XG4gICAgfVxuICAgIEBJbnB1dCgpXG4gICAgZ2V0IHJlcXVpcmVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVxdWlyZWQ7XG4gICAgfVxuICAgIHNldCByZXF1aXJlZChyZXEpIHtcbiAgICAgICAgdGhpcy5fcmVxdWlyZWQgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkocmVxKTtcbiAgICAgICAgdGhpcy5kZXRlY3RDaGFuZ2llcygpO1xuICAgIH1cbiAgICBASW5wdXQoKVxuICAgIGdldCBkaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Rpc2FibGVkO1xuICAgIH1cbiAgICBzZXQgZGlzYWJsZWQodmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fZGlzYWJsZWQgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuICAgICAgICB0aGlzLl9kaXNhYmxlZCA/IHRoaXMucGFydHMuZGlzYWJsZSgpIDogdGhpcy5wYXJ0cy5lbmFibGUoKTtcbiAgICAgICAgdGhpcy5kZXRlY3RDaGFuZ2llcygpO1xuICAgIH1cblxuICAgIC8vIG9uZSBjaGFyYWN0ZXIgdG8gc2VwYXJhdGUgaG91cnMgZnJvbSBtaW51dGVzIGFuZCBtaW51dGVzIGZyb20gc2Vjb25kczsgZGVmYXVsdCBpcyAnOidcbiAgICBASW5wdXQoKVxuICAgIGdldCBzcGxpdHRlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NwbGl0dGVyIHx8ICc6JztcbiAgICB9XG4gICAgc2V0IHNwbGl0dGVyKHZhbHVlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5fc3BsaXR0ZXIgPSAoJycgKyB2YWx1ZSkuc2xpY2UoMCk7XG4gICAgfVxuICAgIHByb3RlY3RlZCBfc3BsaXR0ZXI7XG5cbiAgICAvLyBkbyBub3Qgc2hvdyBjb250cm9sIGJ1dHRvbnM7IG5vcm1hbGx5IGJ1dHRvbnMgYXJlIHNob3duIG9uIGZvY3VzXG4gICAgQElucHV0KCkgbm9CdXR0b25zID0gZmFsc2U7XG5cbiAgICAvLyBhbHdheXMgc2hvdyBjb250cm9sIGJ1dHRvbnM7IG5vcm1hbGx5IGJ1dHRvbnMgYXJlIHNob3duIG9uIGZvY3VzXG4gICAgQElucHV0KCkgc2hvd0J1dHRvbnMgPSBmYWxzZTtcblxuICAgIC8vIGRvIG5vdCBzaG93IHNlY29uZHMgYmxvY2sgaWYgaXQgaXMgbm90IG5lY2Vzc2FyeVxuICAgIEBJbnB1dCgpIG5vU2Vjb25kcyA9IGZhbHNlO1xuXG4gICAgLy8gbWF0IGljb24gbmFtZSBmb3IgZGVzY3JlYXNlIGNvbnRyb2xsIGJ1dHRvblxuICAgIEBJbnB1dCgpIGRlY3JlYXNlQnRuSWNvbk5hbWUgPSAncmVtb3ZlJztcblxuICAgIC8vIG1hdCBpY29uIG5hbWUgZm9yIGluY3JlYXNlIGNvbnRyb2wgYnV0dG9uXG4gICAgQElucHV0KCkgaW5jcmVhc2VCdG5JY29uTmFtZSA9ICdhZGQnO1xuXG4gICAgQE91dHB1dCgpIHRpbWVDaGFuZ2U6IEV2ZW50RW1pdHRlcjxtb21lbnQuTW9tZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8XG4gICAgICAgIG1vbWVudC5Nb21lbnRcbiAgICA+KCk7XG4gICAgcHJvdGVjdGVkIF90aW1lQ2hhbmdlOiBFdmVudEVtaXR0ZXI8bW9tZW50Lk1vbWVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPFxuICAgICAgICBtb21lbnQuTW9tZW50XG4gICAgPigpO1xuXG4gICAgQEhvc3RMaXN0ZW5lcigndGltZUNoYW5nZScsIFsnJGV2ZW50J10pXG4gICAgQEhvc3RMaXN0ZW5lcignY2hhbmdlJywgWyckZXZlbnQnXSlcbiAgICBwdWJsaWMgX29uQ2hhbmdlOiAoXzogYW55KSA9PiB2b2lkID0gZnVuY3Rpb24gKF86IGFueSk6IHZvaWQgeyB9O1xuICAgIHB1YmxpYyBfb25Ub3VjaGVkOiAoXzogYW55KSA9PiB2b2lkID0gZnVuY3Rpb24gKF86IGFueSk6IHZvaWQgeyB9O1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByb3RlY3RlZCBfZm06IEZvY3VzTW9uaXRvcixcbiAgICAgICAgcHJvdGVjdGVkIF9lbFJlZjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4sXG4gICAgICAgIHByb3RlY3RlZCBfY2hEZXRlY3RvcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgICAgIEBPcHRpb25hbCgpIEBTZWxmKCkgcHVibGljIG5nQ29udHJvbDogTmdDb250cm9sXG4gICAgKSB7XG4gICAgICAgIHRoaXMuX3RpbWVWYWx1ZSA9IG5ldyBUaW1lVmFsdWUoKTtcbiAgICAgICAgaWYgKHRoaXMubmdDb250cm9sICE9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLm5nQ29udHJvbC52YWx1ZUFjY2Vzc29yID0gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9mbVxuICAgICAgICAgICAgLm1vbml0b3IodGhpcy5fZWxSZWYubmF0aXZlRWxlbWVudCwgdHJ1ZSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKG9yaWdpbikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChvcmlnaW4gPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9vblRvdWNoZWQodGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNlZCA9ICEhb3JpZ2luO1xuICAgICAgICAgICAgICAgIHRoaXMuZGV0ZWN0Q2hhbmdpZXMoKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuX2hvdXJzQ29udHJvbC52YWx1ZUNoYW5nZXNcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIGZpbHRlcigoZGF0YSkgPT4gK2RhdGEgIT09IHRoaXMuX3RpbWVWYWx1ZS5ob3VycyksXG4gICAgICAgICAgICAgICAgdGFrZVVudGlsKHRoaXMuX3Vuc3Vic2NyaWJlLmFzT2JzZXJ2YWJsZSgpKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoZGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX3RpbWVWYWx1ZS5zZXRIb3VycygrZGF0YSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fdGltZVZhbHVlLmhvdXJzQ2hhbmdlZFxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgdGFrZVVudGlsKHRoaXMuX3Vuc3Vic2NyaWJlLmFzT2JzZXJ2YWJsZSgpKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoZGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX2hvdXJzQ29udHJvbC5zZXRWYWx1ZSh0aGlzLnBhZE51bWJlcihkYXRhKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdGltZUNoYW5nZS5lbWl0KHRoaXMudmFsdWUpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5fbWludXRlc0NvbnRyb2wudmFsdWVDaGFuZ2VzXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmaWx0ZXIoKGRhdGEpID0+ICtkYXRhICE9PSB0aGlzLl90aW1lVmFsdWUubWludXRlcyksXG4gICAgICAgICAgICAgICAgdGFrZVVudGlsKHRoaXMuX3Vuc3Vic2NyaWJlLmFzT2JzZXJ2YWJsZSgpKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoZGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX3RpbWVWYWx1ZS5zZXRNaW51dGVzKCtkYXRhKTtcbiAgICAgICAgICAgIH0pO1xuIC