@nova-ui/bits
Version:
SolarWinds Nova Framework
150 lines • 23.3 kB
JavaScript
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { DOCUMENT } from "@angular/common";
import { Inject, Injectable, RendererFactory2 } from "@angular/core";
import { ActivatedRoute, NavigationEnd, Router } from "@angular/router";
import { BehaviorSubject } from "rxjs";
import { filter, map } from "rxjs/operators";
import * as i0 from "@angular/core";
import * as i1 from "@angular/router";
/** @dynamic */
export class ThemeSwitchService {
constructor(rendererFactory, router, _route, document) {
this.rendererFactory = rendererFactory;
this.router = router;
this._route = _route;
this.document = document;
/** @ignore BehaviorSubject indicating whether we should display theme switcher */
this.showThemeSwitcherSubject = new BehaviorSubject(false);
/** BehaviorSubject indicating whether dark mode is enabled */
this.isDarkModeEnabledSubject = new BehaviorSubject(null);
/** Should route be refreshed after theme switching */
this.withRefreshRoute = false;
this.darkModePreferenceHandler = (event) => {
const isDarkModeEnabled = typeof event === "boolean" ? event : event.matches;
const isDarkPrevColorMode = this.isDarkModeEnabledSubject.getValue();
const demoContainerElement = this.document.children[0];
/** Adding class "dark-nova-theme" to html element we make dark mode, otherwise - light mode */
this.renderer[isDarkModeEnabled ? "addClass" : "removeClass"](demoContainerElement, "dark-nova-theme");
/**
* Reiniting route in case when theme is switching forced
* It allows to avoid reiniting route while application is started
*/
if (isDarkPrevColorMode !== null &&
isDarkPrevColorMode !== isDarkModeEnabled &&
this.withRefreshRoute) {
this.reInitRoute();
}
this.isDarkModeEnabledSubject.next(isDarkModeEnabled);
};
/** Getting renderer instance */
this.renderer = this.rendererFactory.createRenderer(null, null);
this.router.events
.pipe(filter((event) => event instanceof NavigationEnd), map(() => {
let route = this._route.root;
while (route.firstChild) {
route = route.firstChild;
}
return route;
}))
.subscribe((route) => {
const showThemeSwitcher = (route.snapshot.data || {})
.showThemeSwitcher;
if (typeof showThemeSwitcher === "undefined") {
return;
}
this.showThemeSwitcherSubject.next(showThemeSwitcher);
if (showThemeSwitcher) {
/** Case when route is changed on the same page (see on breadcrumb component docs page) */
if (typeof this.isDarkModeEnabledSubject.getValue() ===
"boolean") {
this.darkThemePreference = window.matchMedia("(prefers-color-scheme: dark)");
return;
}
this.enableColorSchemePreferenceHandling();
}
else {
/** Reset to light theme */
this.darkModePreferenceHandler(false);
this.disableColorSchemePreferenceHandling();
}
});
}
/**
* Use this method to manually toggle your app between light and dark theme
*
* @param isDarkModeEnabled Use true for dark theme and false for light theme
*/
setDarkTheme(isDarkModeEnabled) {
this.darkModePreferenceHandler(isDarkModeEnabled);
}
/**
* Use this method to configure the service to synchronize your app's theme with the user's
* light/dark mode system preference
*/
enableColorSchemePreferenceHandling() {
this.darkThemePreference = window.matchMedia("(prefers-color-scheme: dark)");
/** First call to set initial theme */
this.darkModePreferenceHandler(this.darkThemePreference.matches);
/** If browser supports subscribing to MediaQueryList event we do it */
if (typeof this.darkThemePreference.addEventListener === "function") {
this.darkThemePreference.addEventListener("change", this.darkModePreferenceHandler);
}
}
/**
* Use this method to disable synchronization of your app's theme with the user's light/dark mode
* system preference
*/
disableColorSchemePreferenceHandling() {
if (this.darkThemePreference &&
typeof this.darkThemePreference.removeEventListener === "function") {
this.darkThemePreference.removeEventListener("change", this.darkModePreferenceHandler);
}
}
reInitRoute() {
/**
* Logic for refreshing route
*/
const scrolledElement = this.document.children[0];
const currentScrollTopPosition = scrolledElement.scrollTop;
const originalShouldReuseRoute = this.router.routeReuseStrategy.shouldReuseRoute;
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.router.navigated = false;
this.router.navigate([this.router.url]).then(() => {
this.router.routeReuseStrategy.shouldReuseRoute =
originalShouldReuseRoute;
/** After reiniting route we should restore scroll position */
setTimeout(() => (scrolledElement.scrollTop = currentScrollTopPosition));
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ThemeSwitchService, deps: [{ token: i0.RendererFactory2 }, { token: i1.Router }, { token: i1.ActivatedRoute }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ThemeSwitchService, providedIn: "root" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ThemeSwitchService, decorators: [{
type: Injectable,
args: [{
providedIn: "root",
}]
}], ctorParameters: () => [{ type: i0.RendererFactory2 }, { type: i1.Router }, { type: i1.ActivatedRoute }, { type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
export default ThemeSwitchService;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhlbWUtc3dpdGNoLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvdGhlbWUtc3dpdGNoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseURBQXlEO0FBQ3pELEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLDREQUE0RDtBQUM1RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsaUJBQWlCO0FBRWpCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBYSxnQkFBZ0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRixPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7OztBQUU3QyxlQUFlO0FBSWYsTUFBTSxPQUFPLGtCQUFrQjtJQWlCM0IsWUFDWSxlQUFpQyxFQUNqQyxNQUFjLEVBQ2QsTUFBc0IsRUFDSixRQUFrQjtRQUhwQyxvQkFBZSxHQUFmLGVBQWUsQ0FBa0I7UUFDakMsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFdBQU0sR0FBTixNQUFNLENBQWdCO1FBQ0osYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQXBCaEQsa0ZBQWtGO1FBQzNFLDZCQUF3QixHQUMzQixJQUFJLGVBQWUsQ0FBVSxLQUFLLENBQUMsQ0FBQztR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QUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDOUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxnQkFBZ0I7Z0JBQzNDLHdCQUF3QixDQUFDO1lBRTdCLDhEQUE4RDtZQUM5RCxVQUFVLENBQ04sR0FBRyxFQUFFLENBQUMsQ0FBQyxlQUFlLENBQUMsU0FBUyxHQUFHLHdCQUF3QixDQUFDLENBQy9ELENBQUM7UUFDTixDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7K0dBcktRLGtCQUFrQixzR0FxQmYsUUFBUTttSEFyQlgsa0JBQWtCLGNBRmYsTUFBTTs7NEZBRVQsa0JBQWtCO2tCQUg5QixVQUFVO21CQUFDO29CQUNSLFVBQVUsRUFBRSxNQUFNO2lCQUNyQjs7MEJBc0JRLE1BQU07MkJBQUMsUUFBUTs7QUFtSnhCLGVBQWUsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUsIFJlbmRlcmVyMiwgUmVuZGVyZXJGYWN0b3J5MiB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgTmF2aWdhdGlvbkVuZCwgUm91dGVyIH0gZnJvbSBcIkBhbmd1bGFyL3JvdXRlclwiO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IGZpbHRlciwgbWFwIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCI7XG5cbi8qKiBAZHluYW1pYyAqL1xuQEluamVjdGFibGUoe1xuICAgIHByb3ZpZGVkSW46IFwicm9vdFwiLFxufSlcbmV4cG9ydCBjbGFzcyBUaGVtZVN3aXRjaFNlcnZpY2Uge1xuICAgIC8qKiBAaWdub3JlIEJlaGF2aW9yU3ViamVjdCBpbmRpY2F0aW5nIHdoZXRoZXIgd2Ugc2hvdWxkIGRpc3BsYXkgdGhlbWUgc3dpdGNoZXIgKi9cbiAgICBwdWJsaWMgc2hvd1RoZW1lU3dpdGNoZXJTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4gPVxuICAgICAgICBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcblxuICAgIC8qKiBCZWhhdmlvclN1YmplY3QgaW5kaWNhdGluZyB3aGV0aGVyIGRhcmsgbW9kZSBpcyBlbmFibGVkICovXG4gICAgcHVibGljIGlzRGFya01vZGVFbmFibGVkU3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4gfCBudWxsPiA9XG4gICAgICAgIG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbiB8IG51bGw+KG51bGwpO1xuXG4gICAgLyoqIFNob3VsZCByb3V0ZSBiZSByZWZyZXNoZWQgYWZ0ZXIgdGhlbWUgc3dpdGNoaW5nICovXG4gICAgcHVibGljIHdpdGhSZWZyZXNoUm91dGU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBLZWVwIGluZm9ybWF0aW9uIGFib3V0IHByZWZlcnJlZCBkYXJrIGNvbG9yIHNjaGVtZSBvbiBPUyAqL1xuICAgIHByaXZhdGUgZGFya1RoZW1lUHJlZmVyZW5jZTogTWVkaWFRdWVyeUxpc3Q7XG5cbiAgICBwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjI7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSByZW5kZXJlckZhY3Rvcnk6IFJlbmRlcmVyRmFjdG9yeTIsXG4gICAgICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXG4gICAgICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICAgICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnRcbiAgICApIHtcbiAgICAgICAgLyoqIEdldHRpbmcgcmVuZGVyZXIgaW5zdGFuY2UgKi9cbiAgICAgICAgdGhpcy5yZW5kZXJlciA9IHRoaXMucmVuZGVyZXJGYWN0b3J5LmNyZWF0ZVJlbmRlcmVyKG51bGwsIG51bGwpO1xuXG4gICAgICAgIHRoaXMucm91dGVyLmV2ZW50c1xuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgZmlsdGVyKChldmVudCkgPT4gZXZlbnQgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uRW5kKSxcbiAgICAgICAgICAgICAgICBtYXAoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBsZXQgcm91dGUgPSB0aGlzLl9yb3V0ZS5yb290O1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAocm91dGUuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm91dGUgPSByb3V0ZS5maXJzdENoaWxkO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb3V0ZTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgocm91dGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzaG93VGhlbWVTd2l0Y2hlciA9IChyb3V0ZS5zbmFwc2hvdC5kYXRhIHx8IHt9KVxuICAgICAgICAgICAgICAgICAgICAuc2hvd1RoZW1lU3dpdGNoZXI7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNob3dUaGVtZVN3aXRjaGVyID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNob3dUaGVtZVN3aXRjaGVyU3ViamVjdC5uZXh0KHNob3dUaGVtZVN3aXRjaGVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChzaG93VGhlbWVTd2l0Y2hlcikge1xuICAgICAgICAgICAgICAgICAgICAvKiogQ2FzZSB3aGVuIHJvdXRlIGlzIGNoYW5nZWQgb24gdGhlIHNhbWUgcGFnZSAoc2VlIG9uIGJyZWFkY3J1bWIgY29tcG9uZW50IGRvY3MgcGFnZSkgKi9cbiAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW9mIHRoaXMuaXNEYXJrTW9kZUVuYWJsZWRTdWJqZWN0LmdldFZhbHVlKCkgPT09XG4gICAgICAgICAgICAgICAgICAgICAgICBcImJvb2xlYW5cIlxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGFya1RoZW1lUHJlZmVyZW5jZSA9IHdpbmRvdy5tYXRjaE1lZGlhKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmFibGVDb2xvclNjaGVtZVByZWZlcmVuY2VIYW5kbGluZygpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8qKiBSZXNldCB0byBsaWdodCB0aGVtZSAqL1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhcmtNb2RlUHJlZmVyZW5jZUhhbmRsZXIoZmFsc2UpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZUNvbG9yU2NoZW1lUHJlZmVyZW5jZUhhbmRsaW5nKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlIHRoaXMgbWV0aG9kIHRvIG1hbnVhbGx5IHRvZ2dsZSB5b3VyIGFwcCBiZXR3ZWVuIGxpZ2h0IGFuZCBkYXJrIHRoZW1lXG4gICAgICpcbiAgICAgKiBAcGFyYW0gaXNEYXJrTW9kZUVuYWJsZWQgVXNlIHRydWUgZm9yIGRhcmsgdGhlbWUgYW5kIGZhbHNlIGZvciBsaWdodCB0aGVtZVxuICAgICAqL1xuICAgIHB1YmxpYyBzZXREYXJrVGhlbWUoaXNEYXJrTW9kZUVuYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kYXJrTW9kZVByZWZlcmVuY2VIYW5kbGVyKGlzRGFya01vZGVFbmFibGVkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2UgdGhpcyBtZXRob2QgdG8gY29uZmlndXJlIHRoZSBzZXJ2aWNlIHRvIHN5bmNocm9uaXplIHlvdXIgYXBwJ3MgdGhlbWUgd2l0aCB0aGUgdXNlcidzXG4gICAgICogbGlnaHQvZGFyayBtb2RlIHN5c3RlbSBwcmVmZXJlbmNlXG4gICAgICovXG4gICAgcHVibGljIGVuYWJsZUNvbG9yU2NoZW1lUHJlZmVyZW5jZUhhbmRsaW5nKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRhcmtUaGVtZVByZWZlcmVuY2UgPSB3aW5kb3cubWF0Y2hNZWRpYShcbiAgICAgICAgICAgIFwiKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKVwiXG4gICAgICAgICk7XG5cbiAgICAgICAgLyoqIEZpcnN0IGNhbGwgdG8gc2V0IGluaXRpYWwgdGhlbWUgKi9cbiAgICAgICAgdGhpcy5kYXJrTW9kZVByZWZlcmVuY2VIYW5kbGVyKHRoaXMuZGFya1RoZW1lUHJlZmVyZW5jZS5tYXRjaGVzKTtcblxuICAgICAgICAvKiogSWYgYnJvd3NlciBzdXBwb3J0cyBzdWJzY3JpYmluZyB0byBNZWRpYVF1ZXJ5TGlzdCBldmVudCB3ZSBkbyBpdCAqL1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZGFya1RoZW1lUHJlZmVyZW5jZS5hZGRFdmVudExpc3RlbmVyID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHRoaXMuZGFya1RoZW1lUHJlZmVyZW5jZS5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICAgICAgIFwiY2hhbmdlXCIsXG4gICAgICAgICAgICAgICAgdGhpcy5kYXJrTW9kZVByZWZlcmVuY2VIYW5kbGVyXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlIHRoaXMgbWV0aG9kIHRvIGRpc2FibGUgc3luY2hyb25pemF0aW9uIG9mIHlvdXIgYXBwJ3MgdGhlbWUgd2l0aCB0aGUgdXNlcidzIGxpZ2h0L2RhcmsgbW9kZVxuICAgICAqIHN5c3RlbSBwcmVmZXJlbmNlXG4gICAgICovXG4gICAgcHVibGljIGRpc2FibGVDb2xvclNjaGVtZVByZWZlcmVuY2VIYW5kbGluZygpOiB2b2lkIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5kYXJrVGhlbWVQcmVmZXJlbmNlICYmXG4gICAgICAgICAgICB0eXBlb2YgdGhpcy5kYXJrVGhlbWVQcmVmZXJlbmNlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuZGFya1RoZW1lUHJlZmVyZW5jZS5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgICAgICAgICAgIFwiY2hhbmdlXCIsXG4gICAgICAgICAgICAgICAgdGhpcy5kYXJrTW9kZVByZWZlcmVuY2VIYW5kbGVyXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBkYXJrTW9kZVByZWZlcmVuY2VIYW5kbGVyID0gKFxuICAgICAgICBldmVudDogTWVkaWFRdWVyeUxpc3RFdmVudCB8IGJvb2xlYW5cbiAgICApID0+IHtcbiAgICAgICAgY29uc3QgaXNEYXJrTW9kZUVuYWJsZWQgPVxuICAgICAgICAgICAgdHlwZW9mIGV2ZW50ID09PSBcImJvb2xlYW5cIiA/IGV2ZW50IDogZXZlbnQubWF0Y2hlcztcbiAgICAgICAgY29uc3QgaXNEYXJrUHJldkNvbG9yTW9kZSA9IHRoaXMuaXNEYXJrTW9kZUVuYWJsZWRTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgICAgIGNvbnN0IGRlbW9Db250YWluZXJFbGVtZW50ID0gdGhpcy5kb2N1bWVudC5jaGlsZHJlblswXTtcblxuICAgICAgICAvKiogQWRkaW5nIGNsYXNzIFwiZGFyay1ub3ZhLXRoZW1lXCIgdG8gaHRtbCBlbGVtZW50IHdlIG1ha2UgZGFyayBtb2RlLCBvdGhlcndpc2UgLSBsaWdodCBtb2RlICovXG4gICAgICAgIHRoaXMucmVuZGVyZXJbaXNEYXJrTW9kZUVuYWJsZWQgPyBcImFkZENsYXNzXCIgOiBcInJlbW92ZUNsYXNzXCJdKFxuICAgICAgICAgICAgZGVtb0NvbnRhaW5lckVsZW1lbnQsXG4gICAgICAgICAgICBcImRhcmstbm92YS10aGVtZVwiXG4gICAgICAgICk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJlaW5pdGluZyByb3V0ZSBpbiBjYXNlIHdoZW4gdGhlbWUgaXMgc3dpdGNoaW5nIGZvcmNlZFxuICAgICAgICAgKiBJdCBhbGxvd3MgdG8gYXZvaWQgcmVpbml0aW5nIHJvdXRlIHdoaWxlIGFwcGxpY2F0aW9uIGlzIHN0YXJ0ZWRcbiAgICAgICAgICovXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGlzRGFya1ByZXZDb2xvck1vZGUgIT09IG51bGwgJiZcbiAgICAgICAgICAgIGlzRGFya1ByZXZDb2xvck1vZGUgIT09IGlzRGFya01vZGVFbmFibGVkICYmXG4gICAgICAgICAgICB0aGlzLndpdGhSZWZyZXNoUm91dGVcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnJlSW5pdFJvdXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmlzRGFya01vZGVFbmFibGVkU3ViamVjdC5uZXh0KGlzRGFya01vZGVFbmFibGVkKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSByZUluaXRSb3V0ZSgpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIExvZ2ljIGZvciByZWZyZXNoaW5nIHJvdXRlXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdCBzY3JvbGxlZEVsZW1lbnQgPSB0aGlzLmRvY3VtZW50LmNoaWxkcmVuWzBdO1xuICAgICAgICBjb25zdCBjdXJyZW50U2Nyb2xsVG9wUG9zaXRpb24gPSBzY3JvbGxlZEVsZW1lbnQuc2Nyb2xsVG9wO1xuICAgICAgICBjb25zdCBvcmlnaW5hbFNob3VsZFJldXNlUm91dGUgPVxuICAgICAgICAgICAgdGhpcy5yb3V0ZXIucm91dGVSZXVzZVN0cmF0ZWd5LnNob3VsZFJldXNlUm91dGU7XG5cbiAgICAgICAgdGhpcy5yb3V0ZXIucm91dGVSZXVzZVN0cmF0ZWd5LnNob3VsZFJldXNlUm91dGUgPSAoKSA9PiBmYWxzZTtcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGVkID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW3RoaXMucm91dGVyLnVybF0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5yb3V0ZXIucm91dGVSZXVzZVN0cmF0ZWd5LnNob3VsZFJldXNlUm91dGUgPVxuICAgICAgICAgICAgICAgIG9yaWdpbmFsU2hvdWxkUmV1c2VSb3V0ZTtcblxuICAgICAgICAgICAgLyoqIEFmdGVyIHJlaW5pdGluZyByb3V0ZSB3ZSBzaG91bGQgcmVzdG9yZSBzY3JvbGwgcG9zaXRpb24gKi9cbiAgICAgICAgICAgIHNldFRpbWVvdXQoXG4gICAgICAgICAgICAgICAgKCkgPT4gKHNjcm9sbGVkRWxlbWVudC5zY3JvbGxUb3AgPSBjdXJyZW50U2Nyb2xsVG9wUG9zaXRpb24pXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFRoZW1lU3dpdGNoU2VydmljZTtcbiJdfQ==