carbon-components-angular
Version:
Next generation components
189 lines • 22.3 kB
JavaScript
import { EventEmitter, Injectable } from "@angular/core";
import { Notification } from "./notification.component";
import { Toast } from "./toast.component";
import { ActionableNotification } from "./actionable-notification.component";
import * as i0 from "@angular/core";
/**
* Provides a way to use the notification component.
*
* Notifications are displayed toward the top of the UI and do not interrupt the user’s work.
*/
export class NotificationService {
/**
* Constructs Notification Service
*/
constructor(injector, viewContainer, ngZone) {
this.injector = injector;
this.viewContainer = viewContainer;
this.ngZone = ngZone;
/**
* An array containing `ComponentRef`s to all the notifications this service instance
* is responsible for.
*
*/
this.notificationRefs = new Array();
this.onClose = new EventEmitter();
}
/**
* Shows the notification based on the `notificationObj`.
*
* @param notificationObj Can have `type`, `message`, `target`, `duration` and `smart` members.
*
* **Members:**
*
* * `type` can be one of `"info"`, `"warning"`, `"danger"`, `"success"`
* * `message` is message for notification to display
* * `target` is css selector defining an element to append notification to. If not provided,
* `showNotification()` creates a place for the notification in `body`
* * `duration` is number of ms to close the notification after. If used in combination with `smart`,
* it's added to the calculated timeout
* * `smart`, set to `true` if you want to use smart notification.
*
* **Example:**
* ```typescript
* // Info notification, saying "Sample message." added to the element with id notification-container
* // uses smart timeout with added duration of 1 second.
* {
* type: "info",
* message: "Sample message.",
* target: "#notification-container",
* duration: 1000,
* smart: true
* }
* ```
*
* @param [notificationComp=Notification] If provided, used to resolve component factory
*/
showNotification(notificationObj, notificationComp = Notification) {
const notificationRef = this.viewContainer.createComponent(notificationComp);
notificationRef.instance.notificationObj = notificationObj;
this.notificationRefs.push(notificationRef);
this.onClose = notificationRef.instance.close;
if (notificationObj.target) {
document.querySelector(notificationObj.target).appendChild(notificationRef.location.nativeElement);
}
else {
let body = document.querySelector("body");
// get or create a container for alert list
let notificationClassName = "notification-overlay";
let notificationList = body.querySelector(`.${notificationClassName}`);
if (!notificationList) {
notificationList = document.createElement("div");
notificationList.className = notificationClassName;
body.appendChild(notificationList);
}
// add the notification to the top of the list
if (notificationList.firstChild) {
notificationList.insertBefore(notificationRef.location.nativeElement, notificationList.firstChild);
}
else {
notificationList.appendChild(notificationRef.location.nativeElement);
}
}
if (notificationObj.duration && notificationObj.duration > 0) {
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
this.ngZone.run(() => {
this.close(notificationRef);
});
}, notificationObj.duration);
});
}
if (notificationObj.smart) {
this.ngZone.runOutsideAngular(() => {
// let it disappear after calculated timeout
setTimeout(() => {
this.ngZone.run(() => {
this.close(notificationRef);
});
}, this.getSmartTimeout(notificationObj));
});
}
this.onClose.subscribe(() => {
this.close(notificationRef);
});
notificationRef.instance.componentRef = notificationRef;
return notificationRef.instance;
}
showToast(notificationObj, notificationComp = Toast) {
return this.showNotification(notificationObj, notificationComp);
}
showActionable(notificationObj, notificationComp = ActionableNotification) {
return this.showNotification(notificationObj, notificationComp);
}
/**
* Programatically closes notification based on `notificationRef`.
*
* @param notificationRef `ComponentRef` of a notification or `Notification` component you wish to close
*/
close(notificationRef) {
if (notificationRef) {
if (notificationRef instanceof Notification) {
this.close(notificationRef.componentRef);
}
else {
notificationRef.destroy();
const index = this.notificationRefs.indexOf(notificationRef);
if (index !== -1) {
this.notificationRefs.splice(index, 1);
}
}
}
}
/**
* Calculates the amount of time user needs to read the message in the notification.
*
* @param notificationObj Same object used to instantiate notification.
*
* In addition to `type` and `message` members, use `duration` member to add
* some extra time (in ms) to timeout if you need to.
* @returns calculated timeout (in ms) for smart notification
*/
getSmartTimeout(notificationObj) {
// calculate timeout
let timeout = 600; // start with reaction time
// custom duration
timeout += notificationObj.duration || 0;
// message type
switch (notificationObj.type) {
case "info":
case "info-square":
case "success":
default: {
break;
}
case "danger": {
timeout += 3000;
break;
}
case "warning":
case "warning-alt": {
timeout += 1500;
break;
}
}
// message length
// average reader reads around 200 words per minute, or it takes them ~0.3s per word
// let's use 1.5 factor for below average speed readers and have 0.45s per word
let wordCount = notificationObj.message.trim().split(/\s+/).length;
timeout += wordCount * 450;
return timeout;
}
/**
* OnDestroy hook.
*
* Destroys all living notifications it is responsible for.
*
*/
ngOnDestroy() {
this.notificationRefs.forEach((ref) => {
ref.destroy();
});
}
}
NotificationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NotificationService, deps: [{ token: i0.Injector }, { token: i0.ViewContainerRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
NotificationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NotificationService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NotificationService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.ViewContainerRef }, { type: i0.NgZone }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZpY2F0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbm90aWZpY2F0aW9uL25vdGlmaWNhdGlvbi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTixZQUFZLEVBQ1osVUFBVSxFQUtWLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDMUMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0scUNBQXFDLENBQUM7O0FBRTdFOzs7O0dBSUc7QUFFSCxNQUFNLE9BQU8sbUJBQW1CO0lBUy9COztPQUVHO0lBQ0gsWUFDVyxRQUFrQixFQUNsQixhQUErQixFQUMvQixNQUFjO1FBRmQsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNsQixrQkFBYSxHQUFiLGFBQWEsQ0FBa0I7UUFDL0IsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQWR6Qjs7OztXQUlHO1FBQ0kscUJBQWdCLEdBQUcsSUFBSSxLQUFLLEVBQXFCLENBQUM7UUFDbEQsWUFBTyxHQUFzQixJQUFJLFlBQVksRUFBRSxDQUFDO0lBU3BELENBQUM7SUFFSjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0E2Qkc7SUFDSCxnQkFBZ0IsQ0FDZixlQUF1RSxFQUN2RSxnQkFBZ0IsR0FBRyxZQUFZO1FBRS9CLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDN0UsZUFBZSxDQUFDLFFBQVEsQ0FBQyxlQUFlLEdBQUcsZUFBZSxDQUFDO1FBQzNELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFNUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxlQUFlLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUU5QyxJQUFJLGVBQWUsQ0FBQyxNQUFNLEVBQUU7WUFDM0IsUUFBUSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDbkc7YUFBTTtZQUNOLElBQUksSUFBSSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7WUFFMUMsMkNBQTJDO1lBQzNDLElBQUkscUJBQXFCLEdBQUcsc0JBQXNCLENBQUM7WUFDbkQsSUFBSSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUkscUJBQXFCLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZFLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtnQkFDdEIsZ0JBQWdCLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDakQsZ0JBQWdCLENBQUMsU0FBUyxHQUFHLHFCQUFxQixDQUFDO2dCQUNuRCxJQUFJLENBQUMsV0FBVyxDQUFDLGdCQUFnQixDQUFDLENBQUM7YUFDbkM7WUFFRCw4Q0FBOEM7WUFDOUMsSUFBSSxnQkFBZ0IsQ0FBQyxVQUFVLEVBQUU7Z0JBQ2hDLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUNuRztpQkFBTTtnQkFDTixnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQzthQUNyRTtTQUNEO1FBRUQsSUFBSSxlQUFlLENBQUMsUUFBUSxJQUFJLGVBQWUsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxFQUFFO1lBQzdELElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFO2dCQUNsQyxVQUFVLENBQUMsR0FBRyxFQUFFO29CQUNmLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTt3QkFDcEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztvQkFDN0IsQ0FBQyxDQUFDLENBQUM7Z0JBQ0osQ0FBQyxFQUFFLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM5QixDQUFDLENBQUMsQ0FBQztTQUNIO1FBRUQsSUFBSSxlQUFlLENBQUMsS0FBSyxFQUFFO1lBQzFCLElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFO2dCQUNsQyw0Q0FBNEM7Z0JBQzVDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7b0JBQ2YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFO3dCQUNwQixJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO29CQUM3QixDQUFDLENBQUMsQ0FBQztnQkFDSixDQUFDLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO1lBQzNDLENBQUMsQ0FBQyxDQUFDO1NBQ0g7UUFFRCxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDM0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUM3QixDQUFDLENBQUMsQ0FBQztRQUVILGVBQWUsQ0FBQyxRQUFRLENBQUMsWUFBWSxHQUFHLGVBQWUsQ0FBQztRQUN4RCxPQUFPLGVBQWUsQ0FBQyxRQUFRLENBQUM7SUFDakMsQ0FBQztJQUVELFNBQVMsQ0FBQyxlQUFtRCxFQUFFLGdCQUFnQixHQUFHLEtBQUs7UUFDdEYsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsZUFBZSxFQUFFLGdCQUF1QixDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUVELGNBQWMsQ0FBQyxlQUFrQyxFQUFFLGdCQUFnQixHQUFHLHNCQUFzQjtRQUMzRixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLEVBQUUsZ0JBQXVCLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxlQUFvQjtRQUN6QixJQUFJLGVBQWUsRUFBRTtZQUNwQixJQUFJLGVBQWUsWUFBWSxZQUFZLEVBQUU7Z0JBQzVDLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQ3pDO2lCQUFNO2dCQUNOLGVBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDMUIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFDN0QsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLEVBQUU7b0JBQ2pCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO2lCQUN2QzthQUNEO1NBQ0Q7SUFDRixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSCxlQUFlLENBQUMsZUFBZTtRQUM5QixvQkFBb0I7UUFDcEIsSUFBSSxPQUFPLEdBQUcsR0FBRyxDQUFDLENBQUMsMkJBQTJCO1FBRTlDLGtCQUFrQjtRQUNsQixPQUFPLElBQUksZUFBZSxDQUFDLFFBQVEsSUFBSSxDQUFDLENBQUM7UUFFekMsZUFBZTtRQUNmLFFBQVEsZUFBZSxDQUFDLElBQUksRUFBRTtZQUM3QixLQUFLLE1BQU0sQ0FBQztZQUNaLEtBQUssYUFBYSxDQUFDO1lBQ25CLEtBQUssU0FBUyxDQUFDO1lBQ2YsT0FBTyxDQUFDLENBQUM7Z0JBQ1IsTUFBTTthQUNOO1lBQ0QsS0FBSyxRQUFRLENBQUMsQ0FBQztnQkFDZCxPQUFPLElBQUksSUFBSSxDQUFDO2dCQUNoQixNQUFNO2FBQ047WUFDRCxLQUFLLFNBQVMsQ0FBQztZQUNmLEtBQUssYUFBYSxDQUFDLENBQUM7Z0JBQ25CLE9BQU8sSUFBSSxJQUFJLENBQUM7Z0JBQ2hCLE1BQU07YUFDTjtTQUNEO1FBRUQsaUJBQWlCO1FBQ2pCLG9GQUFvRjtRQUNwRiwrRUFBK0U7UUFDL0UsSUFBSSxTQUFTLEdBQUcsZUFBZSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQ25FLE9BQU8sSUFBSSxTQUFTLEdBQUcsR0FBRyxDQUFDO1FBRTNCLE9BQU8sT0FBTyxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILFdBQVc7UUFDVixJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDckMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2YsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDOztnSEE5TFcsbUJBQW1CO29IQUFuQixtQkFBbUI7MkZBQW5CLG1CQUFtQjtrQkFEL0IsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENvbXBvbmVudFJlZixcblx0RXZlbnRFbWl0dGVyLFxuXHRJbmplY3RhYmxlLFxuXHRPbkRlc3Ryb3ksXG5cdE5nWm9uZSxcblx0Vmlld0NvbnRhaW5lclJlZixcblx0SW5qZWN0b3Jcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuaW1wb3J0IHsgTm90aWZpY2F0aW9uQ29udGVudCwgVG9hc3RDb250ZW50LCBBY3Rpb25hYmxlQ29udGVudCB9IGZyb20gXCIuL25vdGlmaWNhdGlvbi1jb250ZW50LmludGVyZmFjZVwiO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uIH0gZnJvbSBcIi4vbm90aWZpY2F0aW9uLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgVG9hc3QgfSBmcm9tIFwiLi90b2FzdC5jb21wb25lbnRcIjtcbmltcG9ydCB7IEFjdGlvbmFibGVOb3RpZmljYXRpb24gfSBmcm9tIFwiLi9hY3Rpb25hYmxlLW5vdGlmaWNhdGlvbi5jb21wb25lbnRcIjtcblxuLyoqXG4gKiBQcm92aWRlcyBhIHdheSB0byB1c2UgdGhlIG5vdGlmaWNhdGlvbiBjb21wb25lbnQuXG4gKlxuICogTm90aWZpY2F0aW9ucyBhcmUgZGlzcGxheWVkIHRvd2FyZCB0aGUgdG9wIG9mIHRoZSBVSSBhbmQgZG8gbm90IGludGVycnVwdCB0aGUgdXNlcuKAmXMgd29yay5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5vdGlmaWNhdGlvblNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXHQvKipcblx0ICogQW4gYXJyYXkgY29udGFpbmluZyBgQ29tcG9uZW50UmVmYHMgdG8gYWxsIHRoZSBub3RpZmljYXRpb25zIHRoaXMgc2VydmljZSBpbnN0YW5jZVxuXHQgKiBpcyByZXNwb25zaWJsZSBmb3IuXG5cdCAqXG5cdCAqL1xuXHRwdWJsaWMgbm90aWZpY2F0aW9uUmVmcyA9IG5ldyBBcnJheTxDb21wb25lbnRSZWY8YW55Pj4oKTtcblx0cHVibGljIG9uQ2xvc2U6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG5cdC8qKlxuXHQgKiBDb25zdHJ1Y3RzIE5vdGlmaWNhdGlvbiBTZXJ2aWNlXG5cdCAqL1xuXHRjb25zdHJ1Y3Rvcihcblx0XHRwcm90ZWN0ZWQgaW5qZWN0b3I6IEluamVjdG9yLFxuXHRcdHByb3RlY3RlZCB2aWV3Q29udGFpbmVyOiBWaWV3Q29udGFpbmVyUmVmLFxuXHRcdHByb3RlY3RlZCBuZ1pvbmU6IE5nWm9uZVxuXHQpIHt9XG5cblx0LyoqXG5cdCAqIFNob3dzIHRoZSBub3RpZmljYXRpb24gYmFzZWQgb24gdGhlIGBub3RpZmljYXRpb25PYmpgLlxuXHQgKlxuXHQgKiBAcGFyYW0gbm90aWZpY2F0aW9uT2JqIENhbiBoYXZlIGB0eXBlYCwgYG1lc3NhZ2VgLCBgdGFyZ2V0YCwgYGR1cmF0aW9uYCBhbmQgYHNtYXJ0YCBtZW1iZXJzLlxuXHQgKlxuXHQgKiAqKk1lbWJlcnM6Kipcblx0ICpcblx0ICogKiBgdHlwZWAgY2FuIGJlIG9uZSBvZiBgXCJpbmZvXCJgLCBgXCJ3YXJuaW5nXCJgLCBgXCJkYW5nZXJcImAsIGBcInN1Y2Nlc3NcImBcblx0ICogKiBgbWVzc2FnZWAgaXMgbWVzc2FnZSBmb3Igbm90aWZpY2F0aW9uIHRvIGRpc3BsYXlcblx0ICogKiBgdGFyZ2V0YCBpcyBjc3Mgc2VsZWN0b3IgZGVmaW5pbmcgYW4gZWxlbWVudCB0byBhcHBlbmQgbm90aWZpY2F0aW9uIHRvLiBJZiBub3QgcHJvdmlkZWQsXG5cdCAqIGBzaG93Tm90aWZpY2F0aW9uKClgIGNyZWF0ZXMgYSBwbGFjZSBmb3IgdGhlIG5vdGlmaWNhdGlvbiBpbiBgYm9keWBcblx0ICogKiBgZHVyYXRpb25gIGlzIG51bWJlciBvZiBtcyB0byBjbG9zZSB0aGUgbm90aWZpY2F0aW9uIGFmdGVyLiBJZiB1c2VkIGluIGNvbWJpbmF0aW9uIHdpdGggYHNtYXJ0YCxcblx0ICogaXQncyBhZGRlZCB0byB0aGUgY2FsY3VsYXRlZCB0aW1lb3V0XG5cdCAqICogYHNtYXJ0YCwgc2V0IHRvIGB0cnVlYCBpZiB5b3Ugd2FudCB0byB1c2Ugc21hcnQgbm90aWZpY2F0aW9uLlxuXHQgKlxuXHQgKiAqKkV4YW1wbGU6Kipcblx0ICogYGBgdHlwZXNjcmlwdFxuXHQgKiAvLyBJbmZvIG5vdGlmaWNhdGlvbiwgc2F5aW5nIFwiU2FtcGxlIG1lc3NhZ2UuXCIgYWRkZWQgdG8gdGhlIGVsZW1lbnQgd2l0aCBpZCBub3RpZmljYXRpb24tY29udGFpbmVyXG5cdCAqIC8vIHVzZXMgc21hcnQgdGltZW91dCB3aXRoIGFkZGVkIGR1cmF0aW9uIG9mIDEgc2Vjb25kLlxuXHQgKiB7XG5cdCAqXHR0eXBlOiBcImluZm9cIixcblx0ICpcdG1lc3NhZ2U6IFwiU2FtcGxlIG1lc3NhZ2UuXCIsXG5cdCAqXHR0YXJnZXQ6IFwiI25vdGlmaWNhdGlvbi1jb250YWluZXJcIixcblx0ICpcdGR1cmF0aW9uOiAxMDAwLFxuXHQgKlx0c21hcnQ6IHRydWVcblx0ICogfVxuXHQgKiBgYGBcblx0ICpcblx0ICogQHBhcmFtIFtub3RpZmljYXRpb25Db21wPU5vdGlmaWNhdGlvbl0gSWYgcHJvdmlkZWQsIHVzZWQgdG8gcmVzb2x2ZSBjb21wb25lbnQgZmFjdG9yeVxuXHQgKi9cblx0c2hvd05vdGlmaWNhdGlvbihcblx0XHRub3RpZmljYXRpb25PYmo6IE5vdGlmaWNhdGlvbkNvbnRlbnQgfCBUb2FzdENvbnRlbnQgfCBBY3Rpb25hYmxlQ29udGVudCxcblx0XHRub3RpZmljYXRpb25Db21wID0gTm90aWZpY2F0aW9uXG5cdCkge1xuXHRcdGNvbnN0IG5vdGlmaWNhdGlvblJlZiA9IHRoaXMudmlld0NvbnRhaW5lci5jcmVhdGVDb21wb25lbnQobm90aWZpY2F0aW9uQ29tcCk7XG5cdFx0bm90aWZpY2F0aW9uUmVmLmluc3RhbmNlLm5vdGlmaWNhdGlvbk9iaiA9IG5vdGlmaWNhdGlvbk9iajtcblx0XHR0aGlzLm5vdGlmaWNhdGlvblJlZnMucHVzaChub3RpZmljYXRpb25SZWYpO1xuXG5cdFx0dGhpcy5vbkNsb3NlID0gbm90aWZpY2F0aW9uUmVmLmluc3RhbmNlLmNsb3NlO1xuXG5cdFx0aWYgKG5vdGlmaWNhdGlvbk9iai50YXJnZXQpIHtcblx0XHRcdGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iobm90aWZpY2F0aW9uT2JqLnRhcmdldCkuYXBwZW5kQ2hpbGQobm90aWZpY2F0aW9uUmVmLmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsZXQgYm9keSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCJib2R5XCIpO1xuXG5cdFx0XHQvLyBnZXQgb3IgY3JlYXRlIGEgY29udGFpbmVyIGZvciBhbGVydCBsaXN0XG5cdFx0XHRsZXQgbm90aWZpY2F0aW9uQ2xhc3NOYW1lID0gXCJub3RpZmljYXRpb24tb3ZlcmxheVwiO1xuXHRcdFx0bGV0IG5vdGlmaWNhdGlvbkxpc3QgPSBib2R5LnF1ZXJ5U2VsZWN0b3IoYC4ke25vdGlmaWNhdGlvbkNsYXNzTmFtZX1gKTtcblx0XHRcdGlmICghbm90aWZpY2F0aW9uTGlzdCkge1xuXHRcdFx0XHRub3RpZmljYXRpb25MaXN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcblx0XHRcdFx0bm90aWZpY2F0aW9uTGlzdC5jbGFzc05hbWUgPSBub3RpZmljYXRpb25DbGFzc05hbWU7XG5cdFx0XHRcdGJvZHkuYXBwZW5kQ2hpbGQobm90aWZpY2F0aW9uTGlzdCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGFkZCB0aGUgbm90aWZpY2F0aW9uIHRvIHRoZSB0b3Agb2YgdGhlIGxpc3Rcblx0XHRcdGlmIChub3RpZmljYXRpb25MaXN0LmZpcnN0Q2hpbGQpIHtcblx0XHRcdFx0bm90aWZpY2F0aW9uTGlzdC5pbnNlcnRCZWZvcmUobm90aWZpY2F0aW9uUmVmLmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQsIG5vdGlmaWNhdGlvbkxpc3QuZmlyc3RDaGlsZCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRub3RpZmljYXRpb25MaXN0LmFwcGVuZENoaWxkKG5vdGlmaWNhdGlvblJlZi5sb2NhdGlvbi5uYXRpdmVFbGVtZW50KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAobm90aWZpY2F0aW9uT2JqLmR1cmF0aW9uICYmIG5vdGlmaWNhdGlvbk9iai5kdXJhdGlvbiA+IDApIHtcblx0XHRcdHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcblx0XHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcblx0XHRcdFx0XHRcdHRoaXMuY2xvc2Uobm90aWZpY2F0aW9uUmVmKTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSwgbm90aWZpY2F0aW9uT2JqLmR1cmF0aW9uKTtcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdGlmIChub3RpZmljYXRpb25PYmouc21hcnQpIHtcblx0XHRcdHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcblx0XHRcdFx0Ly8gbGV0IGl0IGRpc2FwcGVhciBhZnRlciBjYWxjdWxhdGVkIHRpbWVvdXRcblx0XHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcblx0XHRcdFx0XHRcdHRoaXMuY2xvc2Uobm90aWZpY2F0aW9uUmVmKTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSwgdGhpcy5nZXRTbWFydFRpbWVvdXQobm90aWZpY2F0aW9uT2JqKSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHR0aGlzLm9uQ2xvc2Uuc3Vic2NyaWJlKCgpID0+IHtcblx0XHRcdHRoaXMuY2xvc2Uobm90aWZpY2F0aW9uUmVmKTtcblx0XHR9KTtcblxuXHRcdG5vdGlmaWNhdGlvblJlZi5pbnN0YW5jZS5jb21wb25lbnRSZWYgPSBub3RpZmljYXRpb25SZWY7XG5cdFx0cmV0dXJuIG5vdGlmaWNhdGlvblJlZi5pbnN0YW5jZTtcblx0fVxuXG5cdHNob3dUb2FzdChub3RpZmljYXRpb25PYmo6IE5vdGlmaWNhdGlvbkNvbnRlbnQgfCBUb2FzdENvbnRlbnQsIG5vdGlmaWNhdGlvbkNvbXAgPSBUb2FzdCkge1xuXHRcdHJldHVybiB0aGlzLnNob3dOb3RpZmljYXRpb24obm90aWZpY2F0aW9uT2JqLCBub3RpZmljYXRpb25Db21wIGFzIGFueSk7XG5cdH1cblxuXHRzaG93QWN0aW9uYWJsZShub3RpZmljYXRpb25PYmo6IEFjdGlvbmFibGVDb250ZW50LCBub3RpZmljYXRpb25Db21wID0gQWN0aW9uYWJsZU5vdGlmaWNhdGlvbikge1xuXHRcdHJldHVybiB0aGlzLnNob3dOb3RpZmljYXRpb24obm90aWZpY2F0aW9uT2JqLCBub3RpZmljYXRpb25Db21wIGFzIGFueSk7XG5cdH1cblxuXHQvKipcblx0ICogUHJvZ3JhbWF0aWNhbGx5IGNsb3NlcyBub3RpZmljYXRpb24gYmFzZWQgb24gYG5vdGlmaWNhdGlvblJlZmAuXG5cdCAqXG5cdCAqIEBwYXJhbSBub3RpZmljYXRpb25SZWYgYENvbXBvbmVudFJlZmAgb2YgYSBub3RpZmljYXRpb24gb3IgYE5vdGlmaWNhdGlvbmAgY29tcG9uZW50IHlvdSB3aXNoIHRvIGNsb3NlXG5cdCAqL1xuXHRjbG9zZShub3RpZmljYXRpb25SZWY6IGFueSkge1xuXHRcdGlmIChub3RpZmljYXRpb25SZWYpIHtcblx0XHRcdGlmIChub3RpZmljYXRpb25SZWYgaW5zdGFuY2VvZiBOb3RpZmljYXRpb24pIHtcblx0XHRcdFx0dGhpcy5jbG9zZShub3RpZmljYXRpb25SZWYuY29tcG9uZW50UmVmKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG5vdGlmaWNhdGlvblJlZi5kZXN0cm95KCk7XG5cdFx0XHRcdGNvbnN0IGluZGV4ID0gdGhpcy5ub3RpZmljYXRpb25SZWZzLmluZGV4T2Yobm90aWZpY2F0aW9uUmVmKTtcblx0XHRcdFx0aWYgKGluZGV4ICE9PSAtMSkge1xuXHRcdFx0XHRcdHRoaXMubm90aWZpY2F0aW9uUmVmcy5zcGxpY2UoaW5kZXgsIDEpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENhbGN1bGF0ZXMgdGhlIGFtb3VudCBvZiB0aW1lIHVzZXIgbmVlZHMgdG8gcmVhZCB0aGUgbWVzc2FnZSBpbiB0aGUgbm90aWZpY2F0aW9uLlxuXHQgKlxuXHQgKiBAcGFyYW0gbm90aWZpY2F0aW9uT2JqIFNhbWUgb2JqZWN0IHVzZWQgdG8gaW5zdGFudGlhdGUgbm90aWZpY2F0aW9uLlxuXHQgKlxuXHQgKiBJbiBhZGRpdGlvbiB0byBgdHlwZWAgYW5kIGBtZXNzYWdlYCBtZW1iZXJzLCB1c2UgYGR1cmF0aW9uYCBtZW1iZXIgdG8gYWRkXG5cdCAqIHNvbWUgZXh0cmEgdGltZSAoaW4gbXMpIHRvIHRpbWVvdXQgaWYgeW91IG5lZWQgdG8uXG5cdCAqIEByZXR1cm5zIGNhbGN1bGF0ZWQgdGltZW91dCAoaW4gbXMpIGZvciBzbWFydCBub3RpZmljYXRpb25cblx0ICovXG5cdGdldFNtYXJ0VGltZW91dChub3RpZmljYXRpb25PYmopOiBudW1iZXIge1xuXHRcdC8vIGNhbGN1bGF0ZSB0aW1lb3V0XG5cdFx0bGV0IHRpbWVvdXQgPSA2MDA7IC8vIHN0YXJ0IHdpdGggcmVhY3Rpb24gdGltZVxuXG5cdFx0Ly8gY3VzdG9tIGR1cmF0aW9uXG5cdFx0dGltZW91dCArPSBub3RpZmljYXRpb25PYmouZHVyYXRpb24gfHwgMDtcblxuXHRcdC8vIG1lc3NhZ2UgdHlwZVxuXHRcdHN3aXRjaCAobm90aWZpY2F0aW9uT2JqLnR5cGUpIHtcblx0XHRcdGNhc2UgXCJpbmZvXCI6XG5cdFx0XHRjYXNlIFwiaW5mby1zcXVhcmVcIjpcblx0XHRcdGNhc2UgXCJzdWNjZXNzXCI6XG5cdFx0XHRkZWZhdWx0OiB7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0Y2FzZSBcImRhbmdlclwiOiB7XG5cdFx0XHRcdHRpbWVvdXQgKz0gMzAwMDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRjYXNlIFwid2FybmluZ1wiOlxuXHRcdFx0Y2FzZSBcIndhcm5pbmctYWx0XCI6IHtcblx0XHRcdFx0dGltZW91dCArPSAxNTAwO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBtZXNzYWdlIGxlbmd0aFxuXHRcdC8vIGF2ZXJhZ2UgcmVhZGVyIHJlYWRzIGFyb3VuZCAyMDAgd29yZHMgcGVyIG1pbnV0ZSwgb3IgaXQgdGFrZXMgdGhlbSB+MC4zcyBwZXIgd29yZFxuXHRcdC8vIGxldCdzIHVzZSAxLjUgZmFjdG9yIGZvciBiZWxvdyBhdmVyYWdlIHNwZWVkIHJlYWRlcnMgYW5kIGhhdmUgMC40NXMgcGVyIHdvcmRcblx0XHRsZXQgd29yZENvdW50ID0gbm90aWZpY2F0aW9uT2JqLm1lc3NhZ2UudHJpbSgpLnNwbGl0KC9cXHMrLykubGVuZ3RoO1xuXHRcdHRpbWVvdXQgKz0gd29yZENvdW50ICogNDUwO1xuXG5cdFx0cmV0dXJuIHRpbWVvdXQ7XG5cdH1cblxuXHQvKipcblx0ICogT25EZXN0cm95IGhvb2suXG5cdCAqXG5cdCAqIERlc3Ryb3lzIGFsbCBsaXZpbmcgbm90aWZpY2F0aW9ucyBpdCBpcyByZXNwb25zaWJsZSBmb3IuXG5cdCAqXG5cdCAqL1xuXHRuZ09uRGVzdHJveSgpIHtcblx0XHR0aGlzLm5vdGlmaWNhdGlvblJlZnMuZm9yRWFjaCgocmVmKSA9PiB7XG5cdFx0XHRyZWYuZGVzdHJveSgpO1xuXHRcdH0pO1xuXHR9XG59XG4iXX0=