UNPKG

@nova-ui/bits

Version:

SolarWinds Nova Framework

150 lines 23.3 kB
// © 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==