ngx-material-timepicker-decon
Version:
Handy material design timepicker for angular DECONied
376 lines • 40.8 kB
JavaScript
/**
* @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 };
/** @enum {number} */
const KeyboardTypes = {
'NUMPAD': 0,
'CLOCK': 1,
};
export { KeyboardTypes };
KeyboardTypes[KeyboardTypes['NUMPAD']] = 'NUMPAD';
KeyboardTypes[KeyboardTypes['CLOCK']] = 'CLOCK';
/** @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.keyboardTypes = KeyboardTypes;
this.isEsc = true;
this.keyboardType = KeyboardTypes.NUMPAD;
this.keyboardTypeChanged = new EventEmitter();
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 {?}
*/
static blurAll() {
// const tmp = document.createElement('input');
// document.body.appendChild(tmp);
// tmp.focus();
// document.body.removeChild(tmp);
/** @type {?} */
const btn = document.querySelector('.hidden-button');
if (btn) {
btn.focus();
}
}
/**
* @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));
}
/**
* @param {?} type
* @return {?}
*/
changeKeyboardType(type) {
this.keyboardType = type;
this.keyboardTypeChanged.emit(type);
}
/**
*
* 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();
}
/**
* @param {?} k
* @return {?}
*/
numPadPressed(k) {
NgxMaterialTimepickerComponent.blurAll();
this.timepickerService.keyboardClick.emit(new KeyboardEvent('keypress', (/** @type {?} */ ({
ctrlKey: true,
key: k,
charCode: k === 'Backspace' ? 46 : k.charCodeAt(0),
keyCode: k === 'Backspace' ? 46 : k.charCodeAt(0)
}))));
}
}
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 <button class=\"hidden-button\"></button>\n <button class=\"change-type-button\" *ngIf=\"keyboardType === keyboardTypes.NUMPAD\" (click)=\"changeKeyboardType(keyboardTypes.CLOCK)\">\n <i class=\"decontimepicker-clock\"></i>\n </button>\n <button class=\"change-type-button\" *ngIf=\"keyboardType === keyboardTypes.CLOCK\" (click)=\"changeKeyboardType(keyboardTypes.NUMPAD)\">\n <i class=\"decontimepicker-keypad\"></i>\n </button>\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 *ngIf=\"keyboardType === keyboardTypes.CLOCK\">\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>\n <div *ngIf=\"keyboardType === keyboardTypes.NUMPAD\">\n <timepicker-numpad (keyPressed)=\"numPadPressed($event)\"></timepicker-numpad>\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}@font-face{font-family:decontimepicker;src:url(../assets/icons/decontimepicker.eot);src:url(../assets/icons/decontimepicker.eot?#iefix) format(\"embedded-opentype\"),url(../assets/icons/decontimepicker.woff) format(\"woff\"),url(../assets/icons/decontimepicker.ttf) format(\"truetype\"),url(../assets/icons/decontimepicker.svg#decontimepicker) format(\"svg\");font-weight:400;font-style:normal}[class*=decontimepicker-]:before{display:inline-block;font-family:decontimepicker;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.decontimepicker-backspace:before{content:'\\0041'}.decontimepicker-clock:before{content:'\\0042'}.decontimepicker-keypad:before{content:'\\0043'}.timepicker-overlay::ng-deep [class*=decontimepicker-]:before{display:inline-block;font-family:decontimepicker;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.timepicker-overlay::ng-deep .decontimepicker-backspace:before{content:'\\0041'}.timepicker-overlay::ng-deep .decontimepicker-clock:before{content:'\\0042'}.timepicker-overlay::ng-deep .decontimepicker-keypad:before{content:'\\0043'}.simple-keyboard{font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box;overflow:hidden;touch-action:manipulation}.simple-keyboard .hg-row{display:flex}.simple-keyboard .hg-row:not(:last-child){margin-bottom:5px}.simple-keyboard .hg-row .hg-button-container,.simple-keyboard .hg-row .hg-button:not(:last-child){margin-right:5px}.simple-keyboard .hg-row>div:last-child{margin-right:0}.simple-keyboard .hg-row .hg-button-container{display:flex}.simple-keyboard .hg-button{display:inline-block;flex-grow:1;cursor:pointer}.simple-keyboard .hg-button span{pointer-events:none}.simple-keyboard.hg-theme-default{background-color:rgba(0,0,0,.1);padding:5px;border-radius:5px}.simple-keyboard.hg-theme-default .hg-button{box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5;cursor:pointer;display:flex;align-items:center;justify-content:center}.simple-keyboard button.hg-button{border-width:0;outline:0;font-size:inherit}.simple-keyboard.hg-theme-default:not(.hg-touch-events) .hg-button:active{background:#e4e4e4}.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button{width:33.3%;height:60px;align-items:center;display:flex;justify-content:center}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadadd,.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.simple-keyboard.hg-theme-default .hg-button.hg-button-com{max-width:85px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=\".com\"]{max-width:82px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=\"@\"]{max-width:60px}.hidden-button{display:block;visibility:hidden;height:1px;width:1px;overflow:hidden;border:0;position:fixed;top:-1px;left:-1px}.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{color:#fff;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 }],
keyboardType: [{ type: Input }],
keyboardTypeChanged: [{ type: Output }],
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.keyboardTypes;
/** @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.keyboardType;
/** @type {?} */
NgxMaterialTimepickerComponent.prototype.keyboardTypeChanged;
/** @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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hdGVyaWFsLXRpbWVwaWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXItZGVjb24vIiwic291cmNlcyI6WyJzcmMvYXBwL21hdGVyaWFsLXRpbWVwaWNrZXIvbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHNUksT0FBTyxFQUFFLEtBQUssRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDM0MsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDMUYsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxPQUFPLEVBQWtCLEtBQUssRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDMUYsT0FBTyxFQUFFLGlDQUFpQyxFQUFFLE1BQU0sa0RBQWtELENBQUM7QUFDckcsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7SUFLcEMsT0FBUSxPQUFPO0lBQ2YsT0FBUSxPQUFPOzs7OztJQUdmLFdBQVE7SUFDUixVQUFPOzs7NEJBRFAsUUFBUSxLQUFSLFFBQVE7NEJBQ1IsT0FBTyxLQUFQLE9BQU87O01BR0wsTUFBTSxHQUFHLEVBQUU7QUFvQmpCLE1BQU0sT0FBTyw4QkFBOEI7Ozs7O0lBcUR2QyxZQUFvQixpQkFBK0MsRUFDL0MsWUFBK0M7UUFEL0Msc0JBQWlCLEdBQWpCLGlCQUFpQixDQUE4QjtRQUMvQyxpQkFBWSxHQUFaLFlBQVksQ0FBbUM7UUFoRG5FLGFBQVEsR0FBRyxRQUFRLENBQUM7UUFDcEIsbUJBQWMs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LGdEQUE0Qzs7SUFDNUMsZ0RBQTRDOztJQUM1QyxzREFBb0Q7O0lBRXBELDZEQUEyRDs7Ozs7SUFFM0QscURBQTRCOzs7OztJQUM1Qix5REFBNkM7Ozs7O0lBQzdDLHVEQUEyQzs7Ozs7SUFFL0IsMkRBQXVEOzs7OztJQUN2RCxzREFBdUQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyLCBJbnB1dCwgT25EZXN0cm95LCBPbkluaXQsIE91dHB1dCwgVGVtcGxhdGVSZWYsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ2xvY2tGYWNlVGltZSB9IGZyb20gJy4vbW9kZWxzL2Nsb2NrLWZhY2UtdGltZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgVGltZVBlcmlvZCB9IGZyb20gJy4vbW9kZWxzL3RpbWUtcGVyaW9kLmVudW0nO1xuaW1wb3J0IHsgbWVyZ2UsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTmd4TWF0ZXJpYWxUaW1lcGlja2VyU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvbmd4LW1hdGVyaWFsLXRpbWVwaWNrZXIuc2VydmljZSc7XG5pbXBvcnQgeyBUaW1lVW5pdCB9IGZyb20gJy4vbW9kZWxzL3RpbWUtdW5pdC5lbnVtJztcbmltcG9ydCB7IGFuaW1hdGUsIEFuaW1hdGlvbkV2ZW50LCBzdHlsZSwgdHJhbnNpdGlvbiwgdHJpZ2dlciB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHsgTmd4TWF0ZXJpYWxUaW1lcGlja2VyRXZlbnRTZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9uZ3gtbWF0ZXJpYWwtdGltZXBpY2tlci1ldmVudC5zZXJ2aWNlJztcbmltcG9ydCB7IGZpbHRlciB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFRpbWVwaWNrZXJEaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvbmd4LXRpbWVwaWNrZXIuZGlyZWN0aXZlJztcbmltcG9ydCB7IERhdGVUaW1lIH0gZnJvbSAnbHV4b24nO1xuXG5leHBvcnQgZW51bSBBbmltYXRpb25TdGF0ZSB7XG4gICAgRU5URVIgPSAnZW50ZXInLFxuICAgIExFQVZFID0gJ2xlYXZlJ1xufVxuZXhwb3J0IGVudW0gS2V5Ym9hcmRUeXBlcyB7XG4gICAgJ05VTVBBRCcsXG4gICAgJ0NMT0NLJ1xufVxuXG5jb25zdCBFU0NBUEUgPSAyNztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICduZ3gtbWF0ZXJpYWwtdGltZXBpY2tlcicsXG4gICAgdGVtcGxhdGVVcmw6ICcuL25neC1tYXRlcmlhbC10aW1lcGlja2VyLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9uZ3gtbWF0ZXJpYWwtdGltZXBpY2tlci5jb21wb25lbnQuc2NzcyddLFxuICAgIGFuaW1hdGlvbnM6IFtcbiAgICAgICAgdHJpZ2dlcigndGltZXBpY2tlcicsIFtcbiAgICAgICAgICAgIHRyYW5zaXRpb24oYCogPT4gJHtBbmltYXRpb25TdGF0ZS5FTlRFUn1gLCBbXG4gICAgICAgICAgICAgICAgc3R5bGUoe3RyYW5zZm9ybTogJ3RyYW5zbGF0ZVkoLTMwJSknfSksXG4gICAgICAgICAgICAgICAgYW5pbWF0ZSgnMC4ycyBlYXNlLW91dCcsIHN0eWxlKHt0cmFuc2Zvcm06ICd0cmFuc2xhdGVZKDApJ30pKVxuICAgICAgICAgICAgXSksXG4gICAgICAgICAgICB0cmFuc2l0aW9uKGAke0FuaW1hdGlvblN0YXRlLkVOVEVSfSA9PiAke0FuaW1hdGlvblN0YXRlLkxFQVZFfWAsIFtcbiAgICAgICAgICAgICAgICBzdHlsZSh7dHJhbnNmb3JtOiAndHJhbnNsYXRlWSgwKScsIG9wYWNpdHk6IDF9KSxcbiAgICAgICAgICAgICAgICBhbmltYXRlKCcwLjJzIGVhc2Utb3V0Jywgc3R5bGUoe3RyYW5zZm9ybTogJ3RyYW5zbGF0ZVkoLTMwJSknLCBvcGFjaXR5OiAwfSkpXG4gICAgICAgICAgICBdKVxuICAgICAgICBdKVxuICAgIF0sXG4gICAgcHJvdmlkZXJzOiBbTmd4TWF0ZXJpYWxUaW1lcGlja2VyU2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgTmd4TWF0ZXJpYWxUaW1lcGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuXG4gICAgc2VsZWN0ZWRIb3VyOiBDbG9ja0ZhY2VUaW1lO1xuICAgIHNlbGVjdGVkTWludXRlOiBDbG9ja0ZhY2VUaW1lO1xuICAgIHNlbGVjdGVkUGVyaW9kOiBUaW1lUGVyaW9kO1xuXG4gICAgdGltZVVuaXQgPSBUaW1lVW5pdDtcbiAgICBhY3RpdmVUaW1lVW5pdCA9IFRpbWVVbml0LkhPVVI7XG5cbiAgICBpc09wZW5lZCA9IGZhbHNlO1xuICAgIGFuaW1hdGlvblN0YXRlOiBBbmltYXRpb25TdGF0ZTtcblxuICAgIGtleWJvYXJkVHlwZXMgPSBLZXlib2FyZFR5cGVzO1xuXG4gICAgQElucHV0KCkgY2FuY2VsQnRuVG1wbDogVGVtcGxhdGVSZWY8Tm9kZT47XG4gICAgQElucHV0KCkgZWRpdGFibGVIaW50VG1wbDogVGVtcGxhdGVSZWY8Tm9kZT47XG4gICAgQElucHV0KCkgY29uZmlybUJ0blRtcGw6IFRlbXBsYXRlUmVmPE5vZGU+O1xuICAgIEBJbnB1dCgnRVNDJykgaXNFc2MgPSB0cnVlO1xuICAgIEBJbnB1dCgpIGVuYWJsZUtleWJvYXJkSW5wdXQ6IGJvb2xlYW47XG4gICAgQElucHV0KCkgcHJldmVudE92ZXJsYXlDbGljazogYm9vbGVhbjtcbiAgICBASW5wdXQoKSBkaXNhYmxlQW5pbWF0aW9uOiBib29sZWFuO1xuICAgIEBJbnB1dCgpIGtleWJvYXJkVHlwZTogS2V5Ym9hcmRUeXBlcyA9IEtleWJvYXJkVHlwZXMuTlVNUEFEO1xuICAgIEBPdXRwdXQoKSBrZXlib2FyZFR5cGVDaGFuZ2VkOiBFdmVudEVtaXR0ZXI8S2V5Ym9hcmRUeXBlcz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICBASW5wdXQoKVxuICAgIHNldCBtaW51dGVzR2FwKGdhcDogbnVtYmVyKSB7XG4gICAgICAgIGlmIChnYXAgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGdhcCA9IE1hdGguZmxvb3IoZ2FwKTtcbiAgICAgICAgdGhpcy5fbWludXRlc0dhcCA9IGdhcCA8PSA1OSA/IGdhcCA6IDE7XG4gICAgfVxuXG4gICAgZ2V0IG1pbnV0ZXNHYXAoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21pbnV0ZXNHYXA7XG4gICAgfVxuXG4gICAgQElucHV0KClcbiAgICBzZXQgZGVmYXVsdFRpbWUodGltZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc2V0RGVmYXVsdFRpbWUodGltZSk7XG4gICAgfVxuXG4gICAgQE91dHB1dCgpIHRpbWVTZXQgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcbiAgICBAT3V0cHV0KCkgb3BlbmVkID0gbmV3IEV2ZW50RW1pdHRlcjxudWxsPigpO1xuICAgIEBPdXRwdXQoKSBjbG9zZWQgPSBuZXcgRXZlbnRFbWl0dGVyPG51bGw+KCk7XG4gICAgQE91dHB1dCgpIGhvdXJTZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuXG4gICAgQFZpZXdDaGlsZCgndGltZXBpY2tlcnd3JykgdGltZXBpY2tlckNvbXBvbmVudDogRWxlbWVudFJlZjtcblxuICAgIHByaXZhdGUgX21pbnV0ZXNHYXA6IG51bWJlcjtcbiAgICBwcml2YXRlIHRpbWVwaWNrZXJJbnB1dDogVGltZXBpY2tlckRpcmVjdGl2ZTtcbiAgICBwcml2YXRlIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHRpbWVwaWNrZXJTZXJ2aWNlOiBOZ3hNYXRlcmlhbFRpbWVwaWNrZXJTZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByaXZhdGUgZXZlbnRTZXJ2aWNlOiBOZ3hNYXRlcmlhbFRpbWVwaWNrZXJFdmVudFNlcnZpY2UpIHtcblxuICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChtZXJnZSh0aGlzLmV2ZW50U2VydmljZS5iYWNrZHJvcENsaWNrLFxuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2Uua2V5ZG93bkV2ZW50LnBpcGUoZmlsdGVyKGUgPT4gZS5rZXlDb2RlID09PSBFU0NBUEUgJiYgdGhpcy5pc0VzYykpKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmNsb3NlKCkpKTtcblxuICAgIH1cblxuICAgIHB1YmxpYyBzdGF0aWMgYmx1ckFsbCgpIHtcbiAgICAgICAgLy8gY29uc3QgdG1wID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTtcbiAgICAgICAgLy8gZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCh0bXApO1xuICAgICAgICAvLyB0bXAuZm9jdXMoKTtcbiAgICAgICAgLy8gZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZCh0bXApO1xuICAgICAgICBjb25zdCBidG46IEhUTUxCdXR0b25FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmhpZGRlbi1idXR0b24nKTtcbiAgICAgICAgaWYgKGJ0bikge1xuICAgICAgICAgICAgYnRuLmZvY3VzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXQgbWluVGltZSgpOiBzdHJpbmcgfCBEYXRlVGltZSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRpbWVwaWNrZXJJbnB1dCAmJiB0aGlzLnRpbWVwaWNrZXJJbnB1dC5taW47XG4gICAgfVxuXG4gICAgZ2V0IG1heFRpbWUoKTogc3RyaW5nIHwgRGF0ZVRpbWUge1xuICAgICAgICByZXR1cm4gdGhpcy50aW1lcGlja2VySW5wdXQgJiYgdGhpcy50aW1lcGlja2VySW5wdXQubWF4O1xuICAgIH1cblxuICAgIGdldCBkaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGltZXBpY2tlcklucHV0ICYmIHRoaXMudGltZXBpY2tlcklucHV0LmRpc2FibGVkO1xuICAgIH1cblxuICAgIGdldCBmb3JtYXQoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGltZXBpY2tlcklucHV0ICYmIHRoaXMudGltZXBpY2tlcklucHV0LmZvcm1hdDtcbiAgICB9XG5cbiAgICBuZ09uSW5pdCgpIHtcbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2godGhpcy50aW1lcGlja2VyU2VydmljZS5zZWxlY3RlZEhvdXJcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoaG91ciA9PiB0aGlzLnNlbGVjdGVkSG91ciA9IGhvdXIpKTtcblxuICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaCh0aGlzLnRpbWVwaWNrZXJTZXJ2aWNlLnNlbGVjdGVkTWludXRlXG4gICAgICAgICAgICAuc3Vic2NyaWJlKG1pbnV0ZSA9PiB0aGlzLnNlbGVjdGVkTWludXRlID0gbWludXRlKSk7XG5cbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2godGhpcy50aW1lcGlja2VyU2VydmljZS5zZWxlY3RlZFBlcmlvZFxuICAgICAgICAgICAgLnN1YnNjcmliZShwZXJpb2QgPT4gdGhpcy5zZWxlY3RlZFBlcmlvZCA9IHBlcmlvZCkpO1xuICAgIH1cblxuICAgIGNoYW5nZUtleWJvYXJkVHlwZSh0eXBlOiBLZXlib2FyZFR5cGVzKSB7XG4gICAgICAgIHRoaXMua2V5Ym9hcmRUeXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5rZXlib2FyZFR5cGVDaGFuZ2VkLmVtaXQodHlwZSk7XG4gICAgfVxuXG4gICAgLyoqKlxuICAgICAqIFJlZ2lzdGVyIGFuIGlucHV0IHdpdGggdGhpcyB0aW1lcGlja2VyLlxuICAgICAqIGlucHV0IC0gVGhlIHRpbWVwaWNrZXIgaW5wdXQgdG8gcmVnaXN0ZXIgd2l0aCB0aGlzIHRpbWVwaWNrZXJcbiAgICAgKi9cbiAgICByZWdpc3RlcklucHV0KGlucHV0OiBUaW1lcGlja2VyRGlyZWN0aXZlKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnRpbWVwaWNrZXJJbnB1dCkge1xuICAgICAgICAgICAgdGhyb3cgRXJyb3IoJ0EgVGltZXBpY2tlciBjYW4gb25seSBiZSBhc3NvY2lhdGVkIHdpdGggYSBzaW5nbGUgaW5wdXQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50aW1lcGlja2VySW5wdXQgPSBpbnB1dDtcbiAgICB9XG5cbiAgICBvbkhvdXJDaGFuZ2UoaG91cjogQ2xvY2tGYWNlVGltZSk6IHZvaWQge1xuICAgICAgICB0aGlzLnRpbWVwaWNrZXJTZXJ2aWNlLmhvdXIgPSBob3VyO1xuICAgIH1cblxuICAgIG9uSG91clNlbGVjdGVkKGhvdXI6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmNoYW5nZVRpbWVVbml0KFRpbWVVbml0Lk1JTlVURSk7XG4gICAgICAgIHRoaXMuaG91clNlbGVjdGVkLm5leHQoaG91cik7XG4gICAgfVxuXG4gICAgb25NaW51dGVDaGFuZ2UobWludXRlOiBDbG9ja0ZhY2VUaW1lKTogdm9pZCB7XG4gICAgICAgIHRoaXMudGltZXBpY2tlclNlcnZpY2UubWludXRlID0gbWludXRlO1xuICAgIH1cblxuICAgIGNoYW5nZVBlcmlvZChwZXJpb2Q6IFRpbWVQZXJpb2QpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50aW1lcGlja2VyU2VydmljZS5wZXJpb2QgPSBwZXJpb2Q7XG4gICAgfVxuXG4gICAgY2hhbmdlVGltZVVuaXQodW5pdDogVGltZVVuaXQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hY3RpdmVUaW1lVW5pdCA9IHVuaXQ7XG4gICAgfVxuXG4gICAgc2V0VGltZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50aW1lU2V0Lm5leHQodGhpcy50aW1lcGlja2VyU2VydmljZS5nZXRGdWxsVGltZSh0aGlzLmZvcm1hdCkpO1xuICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgfVxuXG4gICAgc2V0RGVmYXVsdFRpbWUodGltZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMudGltZXBpY2tlclNlcnZpY2Uuc2V0RGVmYXVsdFRpbWVJZkF2YWlsYWJsZShcbiAgICAgICAgICAgIHRpbWUsIHRoaXMubWluVGltZSBhcyBEYXRlVGltZSwgdGhpcy5tYXhUaW1lIGFzIERhdGVUaW1lLCB0aGlzLmZvcm1hdCwgdGhpcy5taW51dGVzR2FwKTtcbiAgICB9XG5cbiAgICBvcGVuKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmlzT3BlbmVkID0gdHJ1ZTtcbiAgICAgICAgaWYgKCF0aGlzLmRpc2FibGVBbmltYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5FTlRFUjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9wZW5lZC5uZXh0KCk7XG4gICAgfVxuXG4gICAgY2xvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVBbmltYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VUaW1lcGlja2VyKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLkxFQVZFO1xuICAgIH1cblxuICAgIGFuaW1hdGlvbkRvbmUoZXZlbnQ6IEFuaW1hdGlvbkV2ZW50KTogdm9pZCB7XG4gICAgICAgIGlmIChldmVudC5waGFzZU5hbWUgPT09ICdkb25lJyAmJiBldmVudC50b1N0YXRlID09PSBBbmltYXRpb25TdGF0ZS5MRUFWRSkge1xuICAgICAgICAgICAgdGhpcy5jbG9zZVRpbWVwaWNrZXIoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24nLCBbJyRldmVudCddKVxuICAgIG9uS2V5ZG93bihlOiBLZXlib2FyZEV2ZW50KSB7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZSk7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5mb3JFYWNoKHN1YnNjcmlwdGlvbiA9PiBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjbG9zZVRpbWVwaWNrZXIoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaXNPcGVuZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hY3RpdmVUaW1lVW5pdCA9IFRpbWVVbml0LkhPVVI7XG4gICAgICAgIHRoaXMuY2xvc2VkLm5leHQoKTtcbiAgICB9XG5cbiAgICBudW1QYWRQcmVzc2VkKGs6IHN0cmluZykge1xuICAgICAgICBOZ3hNYXRlcmlhbFRpbWVwaWNrZXJDb21wb25lbnQuYmx1ckFsbCgpO1xuICAgICAgICB0aGlzLnRpbWVwaWNrZXJTZXJ2aWNlLmtleWJvYXJkQ2xpY2suZW1pdChuZXcgS2V5Ym9hcmRFdmVudCgna2V5cHJlc3MnLCA8YW55PntcbiAgICAgICAgICAgIGN0cmxLZXk6IHRydWUsXG4gICAgICAgICAgICBrZXk6IGssXG4gICAgICAgICAgICBjaGFyQ29kZTogayA9PT0gJ0JhY2tzcGFjZScgPyA0NiA6IGsuY2hhckNvZGVBdCgwKSxcbiAgICAgICAgICAgIGtleUNvZGU6IGsgPT09ICdCYWNrc3BhY2UnID8gNDYgOiBrLmNoYXJDb2RlQXQoMClcbiAgICAgICAgfSkpO1xuICAgIH1cbn1cbiJdfQ==