UNPKG

ngx-material-timepicker

Version:
322 lines 32.1 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, ElementRef, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild } from '@angular/core'; import { merge } from 'rxjs'; import { NgxMaterialTimepickerService } from './services/ngx-material-timepicker.service'; import { TimeUnit } from './models/time-unit.enum'; import { animate, style, transition, trigger } from '@angular/animations'; import { NgxMaterialTimepickerEventService } from './services/ngx-material-timepicker-event.service'; import { filter } from 'rxjs/operators'; /** @enum {string} */ const AnimationState = { ENTER: 'enter', LEAVE: 'leave', }; export { AnimationState }; /** @type {?} */ const ESCAPE = 27; export class NgxMaterialTimepickerComponent { /** * @param {?} timepickerService * @param {?} eventService */ constructor(timepickerService, eventService) { this.timepickerService = timepickerService; this.eventService = eventService; this.timeUnit = TimeUnit; this.activeTimeUnit = TimeUnit.HOUR; this.isOpened = false; this.isEsc = true; this.timeSet = new EventEmitter(); this.opened = new EventEmitter(); this.closed = new EventEmitter(); this.hourSelected = new EventEmitter(); this.subscriptions = []; this.subscriptions.push(merge(this.eventService.backdropClick, this.eventService.keydownEvent.pipe(filter(e => e.keyCode === ESCAPE && this.isEsc))) .subscribe(() => this.close())); } /** * @param {?} gap * @return {?} */ set minutesGap(gap) { if (gap == null) { return; } gap = Math.floor(gap); this._minutesGap = gap <= 59 ? gap : 1; } /** * @return {?} */ get minutesGap() { return this._minutesGap; } /** * @param {?} time * @return {?} */ set defaultTime(time) { this.setDefaultTime(time); } /** * @return {?} */ get minTime() { return this.timepickerInput && this.timepickerInput.min; } /** * @return {?} */ get maxTime() { return this.timepickerInput && this.timepickerInput.max; } /** * @return {?} */ get disabled() { return this.timepickerInput && this.timepickerInput.disabled; } /** * @return {?} */ get format() { return this.timepickerInput && this.timepickerInput.format; } /** * @return {?} */ ngOnInit() { this.subscriptions.push(this.timepickerService.selectedHour .subscribe(hour => this.selectedHour = hour)); this.subscriptions.push(this.timepickerService.selectedMinute .subscribe(minute => this.selectedMinute = minute)); this.subscriptions.push(this.timepickerService.selectedPeriod .subscribe(period => this.selectedPeriod = period)); } /** * * Register an input with this timepicker. * input - The timepicker input to register with this timepicker * @param {?} input * @return {?} */ registerInput(input) { if (this.timepickerInput) { throw Error('A Timepicker can only be associated with a single input.'); } this.timepickerInput = input; } /** * @param {?} hour * @return {?} */ onHourChange(hour) { this.timepickerService.hour = hour; } /** * @param {?} hour * @return {?} */ onHourSelected(hour) { this.changeTimeUnit(TimeUnit.MINUTE); this.hourSelected.next(hour); } /** * @param {?} minute * @return {?} */ onMinuteChange(minute) { this.timepickerService.minute = minute; } /** * @param {?} period * @return {?} */ changePeriod(period) { this.timepickerService.period = period; } /** * @param {?} unit * @return {?} */ changeTimeUnit(unit) { this.activeTimeUnit = unit; } /** * @return {?} */ setTime() { this.timeSet.next(this.timepickerService.getFullTime(this.format)); this.close(); } /** * @param {?} time * @return {?} */ setDefaultTime(time) { this.timepickerService.setDefaultTimeIfAvailable(time, (/** @type {?} */ (this.minTime)), (/** @type {?} */ (this.maxTime)), this.format, this.minutesGap); } /** * @return {?} */ open() { this.isOpened = true; if (!this.disableAnimation) { this.animationState = AnimationState.ENTER; } this.opened.next(); } /** * @return {?} */ close() { if (this.disableAnimation) { this.closeTimepicker(); return; } this.animationState = AnimationState.LEAVE; } /** * @param {?} event * @return {?} */ animationDone(event) { if (event.phaseName === 'done' && event.toState === AnimationState.LEAVE) { this.closeTimepicker(); } } /** * @param {?} e * @return {?} */ onKeydown(e) { this.eventService.dispatchEvent(e); e.stopPropagation(); } /** * @return {?} */ ngOnDestroy() { this.subscriptions.forEach(subscription => subscription.unsubscribe()); } /** * @private * @return {?} */ closeTimepicker() { this.isOpened = false; this.activeTimeUnit = TimeUnit.HOUR; this.closed.next(); } } NgxMaterialTimepickerComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-material-timepicker', template: "<div class=\"timepicker-backdrop-overlay\" *ngIf=\"isOpened\" [overlay]=\"preventOverlayClick\"></div>\n<div class=\"timepicker-overlay\" *ngIf=\"isOpened\">\n <div class=\"timepicker\" [@timepicker]=\"animationState\" (@timepicker.done)=\"animationDone($event)\">\n <header class=\"timepicker__header\">\n <ngx-material-timepicker-dial [format]=\"format\" [hour]=\"selectedHour?.time\"\n [minute]=\"selectedMinute?.time\"\n [period]=\"selectedPeriod\" [activeTimeUnit]=\"activeTimeUnit\"\n [minTime]=\"minTime\" [maxTime]=\"maxTime\"\n [isEditable]=\"enableKeyboardInput\"\n [editableHintTmpl]=\"editableHintTmpl\"\n [minutesGap]=\"minutesGap\"\n (periodChanged)=\"changePeriod($event)\"\n (timeUnitChanged)=\"changeTimeUnit($event)\"\n (hourChanged)=\"onHourChange($event)\"\n (minuteChanged)=\"onMinuteChange($event)\"\n ></ngx-material-timepicker-dial>\n </header>\n <div class=\"timepicker__main-content\">\n <div class=\"timepicker__body\" [ngSwitch]=\"activeTimeUnit\">\n <div *ngSwitchCase=\"timeUnit.HOUR\">\n <ngx-material-timepicker-24-hours-face *ngIf=\"format === 24;else ampmHours\"\n (hourChange)=\"onHourChange($event)\"\n [selectedHour]=\"selectedHour\"\n [minTime]=\"minTime\"\n [maxTime]=\"maxTime\"\n [format]=\"format\"\n (hourSelected)=\"onHourSelected($event)\"></ngx-material-timepicker-24-hours-face>\n <ng-template #ampmHours>\n <ngx-material-timepicker-12-hours-face\n (hourChange)=\"onHourChange($event)\"\n [selectedHour]=\"selectedHour\"\n [period]=\"selectedPeriod\"\n [minTime]=\"minTime\"\n [maxTime]=\"maxTime\"\n (hourSelected)=\"onHourSelected($event)\"></ngx-material-timepicker-12-hours-face>\n </ng-template>\n </div>\n <ngx-material-timepicker-minutes-face *ngSwitchCase=\"timeUnit.MINUTE\"\n [selectedMinute]=\"selectedMinute\"\n [selectedHour]=\"selectedHour?.time\"\n [minTime]=\"minTime\"\n [maxTime]=\"maxTime\"\n [format]=\"format\"\n [period]=\"selectedPeriod\"\n [minutesGap]=\"minutesGap\"\n (minuteChange)=\"onMinuteChange($event)\"></ngx-material-timepicker-minutes-face>\n </div>\n <div class=\"timepicker__actions\">\n <div (click)=\"close()\">\n <!--suppress HtmlUnknownAttribute -->\n <ng-container *ngTemplateOutlet=\"cancelBtnTmpl ? cancelBtnTmpl : cancelBtnDefault\"></ng-container>\n </div>\n <div (click)=\"setTime()\">\n <!--suppress HtmlUnknownAttribute -->\n <ng-container\n *ngTemplateOutlet=\"confirmBtnTmpl ? confirmBtnTmpl : confirmBtnDefault\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n</div>\n<ng-template #cancelBtnDefault>\n <ngx-material-timepicker-button>Cancel</ngx-material-timepicker-button>\n</ng-template>\n<ng-template #confirmBtnDefault>\n <ngx-material-timepicker-button>Ok</ngx-material-timepicker-button>\n</ng-template>\n", animations: [ trigger('timepicker', [ transition(`* => ${AnimationState.ENTER}`, [ style({ transform: 'translateY(-30%)' }), animate('0.2s ease-out', style({ transform: 'translateY(0)' })) ]), transition(`${AnimationState.ENTER} => ${AnimationState.LEAVE}`, [ style({ transform: 'translateY(0)', opacity: 1 }), animate('0.2s ease-out', style({ transform: 'translateY(-30%)', opacity: 0 })) ]) ]) ], providers: [NgxMaterialTimepickerService], styles: [":host{--body-background-color:#fff;--primary-font-family:'Roboto',sans-serif;--button-color:deepskyblue;--dial-active-color:#fff;--dial-inactive-color:rgba(255, 255, 255, .5);--dial-background-color:deepskyblue;--clock-face-time-active-color:#fff;--clock-face-time-inactive-color:#6c6c6c;--clock-face-inner-time-inactive-color:#929292;--clock-face-time-disabled-color:#c5c5c5;--clock-face-background-color:#f0f0f0;--clock-hand-color:deepskyblue}.timepicker-backdrop-overlay{position:fixed;top:0;bottom:0;right:0;left:0;background-color:rgba(0,0,0,.3);z-index:999;pointer-events:auto}.timepicker-overlay{position:fixed;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:999;pointer-events:none}.timepicker{width:300px;border-radius:2px;box-shadow:rgba(0,0,0,.25) 0 14px 45px,rgba(0,0,0,.22) 0 10px 18px;outline:0;position:static;z-index:999;pointer-events:auto}.timepicker__header{padding:15px 30px;background-color:#00bfff}@supports (background-color:var(--dial-background-color)){.timepicker__header{background-color:var(--dial-background-color)}}.timepicker__body{padding:15px 5px;display:flex;justify-content:center;align-items:center;background-color:#fff}@supports (background-color:var(--body-background-color)){.timepicker__body{background-color:var(--body-background-color)}}.timepicker__actions{display:flex;justify-content:flex-end;padding:15px;background-color:#fff}@supports (background-color:var(--body-background-color)){.timepicker__actions{background-color:var(--body-background-color)}}@media (max-device-width:1023px) and (orientation:landscape){.timepicker{display:flex;width:515px}.timepicker__header{display:flex;align-items:center}.timepicker__main-content{display:flex;flex-direction:column;width:100%}.timepicker__actions{padding:5px;margin-top:-1px}}"] }] } ]; /** @nocollapse */ NgxMaterialTimepickerComponent.ctorParameters = () => [ { type: NgxMaterialTimepickerService }, { type: NgxMaterialTimepickerEventService } ]; NgxMaterialTimepickerComponent.propDecorators = { cancelBtnTmpl: [{ type: Input }], editableHintTmpl: [{ type: Input }], confirmBtnTmpl: [{ type: Input }], isEsc: [{ type: Input, args: ['ESC',] }], enableKeyboardInput: [{ type: Input }], preventOverlayClick: [{ type: Input }], disableAnimation: [{ type: Input }], minutesGap: [{ type: Input }], defaultTime: [{ type: Input }], timeSet: [{ type: Output }], opened: [{ type: Output }], closed: [{ type: Output }], hourSelected: [{ type: Output }], timepickerComponent: [{ type: ViewChild, args: ['timepickerww',] }], onKeydown: [{ type: HostListener, args: ['keydown', ['$event'],] }] }; if (false) { /** @type {?} */ NgxMaterialTimepickerComponent.prototype.selectedHour; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.selectedMinute; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.selectedPeriod; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.timeUnit; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.activeTimeUnit; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.isOpened; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.animationState; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.cancelBtnTmpl; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.editableHintTmpl; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.confirmBtnTmpl; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.isEsc; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.enableKeyboardInput; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.preventOverlayClick; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.disableAnimation; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.timeSet; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.opened; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.closed; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.hourSelected; /** @type {?} */ NgxMaterialTimepickerComponent.prototype.timepickerComponent; /** * @type {?} * @private */ NgxMaterialTimepickerComponent.prototype._minutesGap; /** * @type {?} * @private */ NgxMaterialTimepickerComponent.prototype.timepickerInput; /** * @type {?} * @private */ NgxMaterialTimepickerComponent.prototype.subscriptions; /** * @type {?} * @private */ NgxMaterialTimepickerComponent.prototype.timepickerService; /** * @type {?} * @private */ NgxMaterialTimepickerComponent.prototype.eventService; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hdGVyaWFsLXRpbWVwaWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXIvIiwic291cmNlcyI6WyJzcmMvYXBwL21hdGVyaWFsLXRpbWVwaWNrZXIvbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHNUksT0FBTyxFQUFFLEtBQUssRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDM0MsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDMUYsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxPQUFPLEVBQWtCLEtBQUssRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDMUYsT0FBTyxFQUFFLGlDQUFpQyxFQUFFLE1BQU0sa0RBQWtELENBQUM7QUFDckcsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7SUFLcEMsT0FBUSxPQUFPO0lBQ2YsT0FBUSxPQUFPOzs7O01BSWIsTUFBTSxHQUFHLEVBQUU7QUFvQmpCLE1BQU0sT0FBTyw4QkFBOEI7Ozs7O0lBaUR2QyxZQUFvQixpQkFBK0MsRUFDL0MsWUFBK0M7UUFEL0Msc0JBQWlCLEdBQWpCLGlCQUFpQixDQUE4QjtRQUMvQyxpQkFBWSxHQUFaLFlBQVksQ0FBbUM7UUE1Q25FLGFBQVEsR0FBRyxRQUFRLENBQUM7UUFDcEIsbUJBQWMsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO1FBRS9CLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFNSCxVQUFLLEdBQUcsSUFBSSxD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LGdEQUE0Qzs7SUFDNUMsc0RBQW9EOztJQUVwRCw2REFBMkQ7Ozs7O0lBRTNELHFEQUE0Qjs7Ozs7SUFDNUIseURBQTZDOzs7OztJQUM3Qyx1REFBMkM7Ozs7O0lBRS9CLDJEQUF1RDs7Ozs7SUFDdkQsc0RBQXVEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFRlbXBsYXRlUmVmLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENsb2NrRmFjZVRpbWUgfSBmcm9tICcuL21vZGVscy9jbG9jay1mYWNlLXRpbWUuaW50ZXJmYWNlJztcbmltcG9ydCB7IFRpbWVQZXJpb2QgfSBmcm9tICcuL21vZGVscy90aW1lLXBlcmlvZC5lbnVtJztcbmltcG9ydCB7IG1lcmdlLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE5neE1hdGVyaWFsVGltZXBpY2tlclNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL25neC1tYXRlcmlhbC10aW1lcGlja2VyLnNlcnZpY2UnO1xuaW1wb3J0IHsgVGltZVVuaXQgfSBmcm9tICcuL21vZGVscy90aW1lLXVuaXQuZW51bSc7XG5pbXBvcnQgeyBhbmltYXRlLCBBbmltYXRpb25FdmVudCwgc3R5bGUsIHRyYW5zaXRpb24sIHRyaWdnZXIgfSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcbmltcG9ydCB7IE5neE1hdGVyaWFsVGltZXBpY2tlckV2ZW50U2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXItZXZlbnQuc2VydmljZSc7XG5pbXBvcnQgeyBmaWx0ZXIgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBUaW1lcGlja2VyRGlyZWN0aXZlIH0gZnJvbSAnLi9kaXJlY3RpdmVzL25neC10aW1lcGlja2VyLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBEYXRlVGltZSB9IGZyb20gJ2x1eG9uJztcblxuZXhwb3J0IGVudW0gQW5pbWF0aW9uU3RhdGUge1xuICAgIEVOVEVSID0gJ2VudGVyJyxcbiAgICBMRUFWRSA9ICdsZWF2ZSdcbn1cblxuXG5jb25zdCBFU0NBUEUgPSAyNztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICduZ3gtbWF0ZXJpYWwtdGltZXBpY2tlcicsXG4gICAgdGVtcGxhdGVVcmw6ICcuL25neC1tYXRlcmlhbC10aW1lcGlja2VyLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9uZ3gtbWF0ZXJpYWwtdGltZXBpY2tlci5jb21wb25lbnQuc2NzcyddLFxuICAgIGFuaW1hdGlvbnM6IFtcbiAgICAgICAgdHJpZ2dlcigndGltZXBpY2tlcicsIFtcbiAgICAgICAgICAgIHRyYW5zaXRpb24oYCogPT4gJHtBbmltYXRpb25TdGF0ZS5FTlRFUn1gLCBbXG4gICAgICAgICAgICAgICAgc3R5bGUoe3RyYW5zZm9ybTogJ3RyYW5zbGF0ZVkoLTMwJSknfSksXG4gICAgICAgICAgICAgICAgYW5pbWF0ZSgnMC4ycyBlYXNlLW91dCcsIHN0eWxlKHt0cmFuc2Zvcm06ICd0cmFuc2xhdGVZKDApJ30pKVxuICAgICAgICAgICAgXSksXG4gICAgICAgICAgICB0cmFuc2l0aW9uKGAke0FuaW1hdGlvblN0YXRlLkVOVEVSfSA9PiAke0FuaW1hdGlvblN0YXRlLkxFQVZFfWAsIFtcbiAgICAgICAgICAgICAgICBzdHlsZSh7dHJhbnNmb3JtOiAndHJhbnNsYXRlWSgwKScsIG9wYWNpdHk6IDF9KSxcbiAgICAgICAgICAgICAgICBhbmltYXRlKCcwLjJzIGVhc2Utb3V0Jywgc3R5bGUoe3RyYW5zZm9ybTogJ3RyYW5zbGF0ZVkoLTMwJSknLCBvcGFjaXR5OiAwfSkpXG4gICAgICAgICAgICBdKVxuICAgICAgICBdKVxuICAgIF0sXG4gICAgcHJvdmlkZXJzOiBbTmd4TWF0ZXJpYWxUaW1lcGlja2VyU2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgTmd4TWF0ZXJpYWxUaW1lcGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuXG4gICAgc2VsZWN0ZWRIb3VyOiBDbG9ja0ZhY2VUaW1lO1xuICAgIHNlbGVjdGVkTWludXRlOiBDbG9ja0ZhY2VUaW1lO1xuICAgIHNlbGVjdGVkUGVyaW9kOiBUaW1lUGVyaW9kO1xuXG4gICAgdGltZVVuaXQgPSBUaW1lVW5pdDtcbiAgICBhY3RpdmVUaW1lVW5pdCA9IFRpbWVVbml0LkhPVVI7XG5cbiAgICBpc09wZW5lZCA9IGZhbHNlO1xuICAgIGFuaW1hdGlvblN0YXRlOiBBbmltYXRpb25TdGF0ZTtcblxuICAgIEBJbnB1dCgpIGNhbmNlbEJ0blRtcGw6IFRlbXBsYXRlUmVmPE5vZGU+O1xuICAgIEBJbnB1dCgpIGVkaXRhYmxlSGludFRtcGw6IFRlbXBsYXRlUmVmPE5vZGU+O1xuICAgIEBJbnB1dCgpIGNvbmZpcm1CdG5UbXBsOiBUZW1wbGF0ZVJlZjxOb2RlPjtcbiAgICBASW5wdXQoJ0VTQycpIGlzRXNjID0gdHJ1ZTtcbiAgICBASW5wdXQoKSBlbmFibGVLZXlib2FyZElucHV0OiBib29sZWFuO1xuICAgIEBJbnB1dCgpIHByZXZlbnRPdmVybGF5Q2xpY2s6IGJvb2xlYW47XG4gICAgQElucHV0KCkgZGlzYWJsZUFuaW1hdGlvbjogYm9vbGVhbjtcblxuICAgIEBJbnB1dCgpXG4gICAgc2V0IG1pbnV0ZXNHYXAoZ2FwOiBudW1iZXIpIHtcbiAgICAgICAgaWYgKGdhcCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZ2FwID0gTWF0aC5mbG9vcihnYXApO1xuICAgICAgICB0aGlzLl9taW51dGVzR2FwID0gZ2FwIDw9IDU5ID8gZ2FwIDogMTtcbiAgICB9XG5cbiAgICBnZXQgbWludXRlc0dhcCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5fbWludXRlc0dhcDtcbiAgICB9XG5cbiAgICBASW5wdXQoKVxuICAgIHNldCBkZWZhdWx0VGltZSh0aW1lOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5zZXREZWZhdWx0VGltZSh0aW1lKTtcbiAgICB9XG5cbiAgICBAT3V0cHV0KCkgdGltZVNldCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuICAgIEBPdXRwdXQoKSBvcGVuZWQgPSBuZXcgRXZlbnRFbWl0dGVyPG51bGw+KCk7XG4gICAgQE91dHB1dCgpIGNsb3NlZCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVsbD4oKTtcbiAgICBAT3V0cHV0KCkgaG91clNlbGVjdGVkID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG5cbiAgICBAVmlld0NoaWxkKCd0aW1lcGlja2Vyd3cnKSB0aW1lcGlja2VyQ29tcG9uZW50OiBFbGVtZW50UmVmO1xuXG4gICAgcHJpdmF0ZSBfbWludXRlc0dhcDogbnVtYmVyO1xuICAgIHByaXZhdGUgdGltZXBpY2tlcklucHV0OiBUaW1lcGlja2VyRGlyZWN0aXZlO1xuICAgIHByaXZhdGUgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgdGltZXBpY2tlclNlcnZpY2U6IE5neE1hdGVyaWFsVGltZXBpY2tlclNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSBldmVudFNlcnZpY2U6IE5neE1hdGVyaWFsVGltZXBpY2tlckV2ZW50U2VydmljZSkge1xuXG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKG1lcmdlKHRoaXMuZXZlbnRTZXJ2aWNlLmJhY2tkcm9wQ2xpY2ssXG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5rZXlkb3duRXZlbnQucGlwZShmaWx0ZXIoZSA9PiBlLmtleUNvZGUgPT09IEVTQ0FQRSAmJiB0aGlzLmlzRXNjKSkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuY2xvc2UoKSkpO1xuXG4gICAgfVxuXG4gICAgZ2V0IG1pblRpbWUoKTogc3RyaW5nIHwgRGF0ZVRpbWUge1xuICAgICAgICByZXR1cm4gdGhpcy50aW1lcGlja2VySW5wdXQgJiYgdGhpcy50aW1lcGlja2VySW5wdXQubWluO1xuICAgIH1cblxuICAgIGdldCBtYXhUaW1lKCk6IHN0cmluZyB8IERhdGVUaW1lIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGltZXBpY2tlcklucHV0ICYmIHRoaXMudGltZXBpY2tlcklucHV0Lm1heDtcbiAgICB9XG5cbiAgICBnZXQgZGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnRpbWVwaWNrZXJJbnB1dCAmJiB0aGlzLnRpbWVwaWNrZXJJbnB1dC5kaXNhYmxlZDtcbiAgICB9XG5cbiAgICBnZXQgZm9ybWF0KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnRpbWVwaWNrZXJJbnB1dCAmJiB0aGlzLnRpbWVwaWNrZXJJbnB1dC5mb3JtYXQ7XG4gICAgfVxuXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKHRoaXMudGltZXBpY2tlclNlcnZpY2Uuc2VsZWN0ZWRIb3VyXG4gICAgICAgICAgICAuc3Vic2NyaWJlKGhvdXIgPT4gdGhpcy5zZWxlY3RlZEhvdXIgPSBob3VyKSk7XG5cbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2godGhpcy50aW1lcGlja2VyU2VydmljZS5zZWxlY3RlZE1pbnV0ZVxuICAgICAgICAgICAgLnN1YnNjcmliZShtaW51dGUgPT4gdGhpcy5zZWxlY3RlZE1pbnV0ZSA9IG1pbnV0ZSkpO1xuXG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKHRoaXMudGltZXBpY2tlclNlcnZpY2Uuc2VsZWN0ZWRQZXJpb2RcbiAgICAgICAgICAgIC5zdWJzY3JpYmUocGVyaW9kID0+IHRoaXMuc2VsZWN0ZWRQZXJpb2QgPSBwZXJpb2QpKTtcbiAgICB9XG5cbiAgICAvKioqXG4gICAgICogUmVnaXN0ZXIgYW4gaW5wdXQgd2l0aCB0aGlzIHRpbWVwaWNrZXIuXG4gICAgICogaW5wdXQgLSBUaGUgdGltZXBpY2tlciBpbnB1dCB0byByZWdpc3RlciB3aXRoIHRoaXMgdGltZXBpY2tlclxuICAgICAqL1xuICAgIHJlZ2lzdGVySW5wdXQoaW5wdXQ6IFRpbWVwaWNrZXJEaXJlY3RpdmUpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMudGltZXBpY2tlcklucHV0KSB7XG4gICAgICAgICAgICB0aHJvdyBFcnJvcignQSBUaW1lcGlja2VyIGNhbiBvbmx5IGJlIGFzc29jaWF0ZWQgd2l0aCBhIHNpbmdsZSBpbnB1dC4nKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRpbWVwaWNrZXJJbnB1dCA9IGlucHV0O1xuICAgIH1cblxuICAgIG9uSG91ckNoYW5nZShob3VyOiBDbG9ja0ZhY2VUaW1lKTogdm9pZCB7XG4gICAgICAgIHRoaXMudGltZXBpY2tlclNlcnZpY2UuaG91ciA9IGhvdXI7XG4gICAgfVxuXG4gICAgb25Ib3VyU2VsZWN0ZWQoaG91cjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY2hhbmdlVGltZVVuaXQoVGltZVVuaXQuTUlOVVRFKTtcbiAgICAgICAgdGhpcy5ob3VyU2VsZWN0ZWQubmV4dChob3VyKTtcbiAgICB9XG5cbiAgICBvbk1pbnV0ZUNoYW5nZShtaW51dGU6IENsb2NrRmFjZVRpbWUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50aW1lcGlja2VyU2VydmljZS5taW51dGUgPSBtaW51dGU7XG4gICAgfVxuXG4gICAgY2hhbmdlUGVyaW9kKHBlcmlvZDogVGltZVBlcmlvZCk6IHZvaWQge1xuICAgICAgICB0aGlzLnRpbWVwaWNrZXJTZXJ2aWNlLnBlcmlvZCA9IHBlcmlvZDtcbiAgICB9XG5cbiAgICBjaGFuZ2VUaW1lVW5pdCh1bml0OiBUaW1lVW5pdCk6IHZvaWQge1xuICAgICAgICB0aGlzLmFjdGl2ZVRpbWVVbml0ID0gdW5pdDtcbiAgICB9XG5cbiAgICBzZXRUaW1lKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnRpbWVTZXQubmV4dCh0aGlzLnRpbWVwaWNrZXJTZXJ2aWNlLmdldEZ1bGxUaW1lKHRoaXMuZm9ybWF0KSk7XG4gICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICB9XG5cbiAgICBzZXREZWZhdWx0VGltZSh0aW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50aW1lcGlja2VyU2VydmljZS5zZXREZWZhdWx0VGltZUlmQXZhaWxhYmxlKFxuICAgICAgICAgICAgdGltZSwgdGhpcy5taW5UaW1lIGFzIERhdGVUaW1lLCB0aGlzLm1heFRpbWUgYXMgRGF0ZVRpbWUsIHRoaXMuZm9ybWF0LCB0aGlzLm1pbnV0ZXNHYXApO1xuICAgIH1cblxuICAgIG9wZW4oKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaXNPcGVuZWQgPSB0cnVlO1xuICAgICAgICBpZiAoIXRoaXMuZGlzYWJsZUFuaW1hdGlvbikge1xuICAgICAgICAgICAgdGhpcy5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLkVOVEVSO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub3BlbmVkLm5leHQoKTtcbiAgICB9XG5cbiAgICBjbG9zZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuZGlzYWJsZUFuaW1hdGlvbikge1xuICAgICAgICAgICAgdGhpcy5jbG9zZVRpbWVwaWNrZXIoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuTEVBVkU7XG4gICAgfVxuXG4gICAgYW5pbWF0aW9uRG9uZShldmVudDogQW5pbWF0aW9uRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKGV2ZW50LnBoYXNlTmFtZSA9PT0gJ2RvbmUnICYmIGV2ZW50LnRvU3RhdGUgPT09IEFuaW1hdGlvblN0YXRlLkxFQVZFKSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlVGltZXBpY2tlcigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgQEhvc3RMaXN0ZW5lcigna2V5ZG93bicsIFsnJGV2ZW50J10pXG4gICAgb25LZXlkb3duKGU6IEtleWJvYXJkRXZlbnQpIHtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChlKTtcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goc3Vic2NyaXB0aW9uID0+IHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNsb3NlVGltZXBpY2tlcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pc09wZW5lZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmFjdGl2ZVRpbWVVbml0ID0gVGltZVVuaXQuSE9VUjtcbiAgICAgICAgdGhpcy5jbG9zZWQubmV4dCgpO1xuICAgIH1cbn1cbiJdfQ==