matrix-react-sdk
Version:
SDK for matrix.org using React
143 lines (135 loc) • 21.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _logger = require("matrix-js-sdk/src/logger");
var _SettingsStore = _interopRequireDefault(require("../SettingsStore"));
var _dispatcher = _interopRequireDefault(require("../../dispatcher/dispatcher"));
var _actions = require("../../dispatcher/actions");
var _ThemeController = _interopRequireDefault(require("../controllers/ThemeController"));
var _theme = require("../../theme");
var _SettingLevel = require("../SettingLevel");
/*
Copyright 2024 New Vector Ltd.
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
class ThemeWatcher {
constructor() {
(0, _defineProperty2.default)(this, "themeWatchRef", void 0);
(0, _defineProperty2.default)(this, "systemThemeWatchRef", void 0);
(0, _defineProperty2.default)(this, "dispatcherRef", void 0);
(0, _defineProperty2.default)(this, "preferDark", void 0);
(0, _defineProperty2.default)(this, "preferLight", void 0);
(0, _defineProperty2.default)(this, "preferHighContrast", void 0);
(0, _defineProperty2.default)(this, "currentTheme", void 0);
(0, _defineProperty2.default)(this, "onChange", () => {
this.recheck();
});
(0, _defineProperty2.default)(this, "onAction", payload => {
if (payload.action === _actions.Action.RecheckTheme) {
// XXX forceTheme
this.recheck(payload.forceTheme);
}
});
this.themeWatchRef = null;
this.systemThemeWatchRef = null;
this.dispatcherRef = null;
// we have both here as each may either match or not match, so by having both
// we can get the tristate of dark/light/unsupported
this.preferDark = global.matchMedia("(prefers-color-scheme: dark)");
this.preferLight = global.matchMedia("(prefers-color-scheme: light)");
this.preferHighContrast = global.matchMedia("(prefers-contrast: more)");
this.currentTheme = this.getEffectiveTheme();
}
start() {
this.themeWatchRef = _SettingsStore.default.watchSetting("theme", null, this.onChange);
this.systemThemeWatchRef = _SettingsStore.default.watchSetting("use_system_theme", null, this.onChange);
this.preferDark.addEventListener("change", this.onChange);
this.preferLight.addEventListener("change", this.onChange);
this.preferHighContrast.addEventListener("change", this.onChange);
this.dispatcherRef = _dispatcher.default.register(this.onAction);
}
stop() {
this.preferDark.removeEventListener("change", this.onChange);
this.preferLight.removeEventListener("change", this.onChange);
this.preferHighContrast.removeEventListener("change", this.onChange);
if (this.systemThemeWatchRef) _SettingsStore.default.unwatchSetting(this.systemThemeWatchRef);
if (this.themeWatchRef) _SettingsStore.default.unwatchSetting(this.themeWatchRef);
if (this.dispatcherRef) _dispatcher.default.unregister(this.dispatcherRef);
}
// XXX: forceTheme param added here as local echo appears to be unreliable
// https://github.com/vector-im/element-web/issues/11443
recheck(forceTheme) {
const oldTheme = this.currentTheme;
this.currentTheme = forceTheme === undefined ? this.getEffectiveTheme() : forceTheme;
if (oldTheme !== this.currentTheme) {
(0, _theme.setTheme)(this.currentTheme);
}
}
getEffectiveTheme() {
// Dev note: Much of this logic is replicated in the AppearanceUserSettingsTab
// XXX: checking the isLight flag here makes checking it in the ThemeController
// itself completely redundant since we just override the result here and we're
// now effectively just using the ThemeController as a place to store the static
// variable. The system theme setting probably ought to have an equivalent
// controller that honours the same flag, although probably better would be to
// have the theme logic in one place rather than split between however many
// different places.
if (_ThemeController.default.isLogin) return "light";
// If the user has specifically enabled the system matching option (excluding default),
// then use that over anything else. We pick the lowest possible level for the setting
// to ensure the ordering otherwise works.
const systemThemeExplicit = _SettingsStore.default.getValueAt(_SettingLevel.SettingLevel.DEVICE, "use_system_theme", null, false, true);
if (systemThemeExplicit) {
_logger.logger.log("returning explicit system theme");
const theme = this.themeBasedOnSystem();
if (theme) {
return theme;
}
}
// If the user has specifically enabled the theme (without the system matching option being
// enabled specifically and excluding the default), use that theme. We pick the lowest possible
// level for the setting to ensure the ordering otherwise works.
const themeExplicit = _SettingsStore.default.getValueAt(_SettingLevel.SettingLevel.DEVICE, "theme", null, false, true);
if (themeExplicit) {
_logger.logger.log("returning explicit theme: " + themeExplicit);
return themeExplicit;
}
// If the user hasn't really made a preference in either direction, assume the defaults of the
// settings and use those.
if (_SettingsStore.default.getValue("use_system_theme")) {
const theme = this.themeBasedOnSystem();
if (theme) {
return theme;
}
}
_logger.logger.log("returning theme value");
return _SettingsStore.default.getValue("theme");
}
themeBasedOnSystem() {
let newTheme;
if (this.preferDark.matches) {
newTheme = "dark";
} else if (this.preferLight.matches) {
newTheme = "light";
}
if (newTheme && this.preferHighContrast.matches) {
const hcTheme = (0, _theme.findHighContrastTheme)(newTheme);
if (hcTheme) {
newTheme = hcTheme;
}
}
return newTheme;
}
isSystemThemeSupported() {
return this.preferDark.matches || this.preferLight.matches;
}
}
exports.default = ThemeWatcher;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9nZ2VyIiwicmVxdWlyZSIsIl9TZXR0aW5nc1N0b3JlIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9kaXNwYXRjaGVyIiwiX2FjdGlvbnMiLCJfVGhlbWVDb250cm9sbGVyIiwiX3RoZW1lIiwiX1NldHRpbmdMZXZlbCIsIlRoZW1lV2F0Y2hlciIsImNvbnN0cnVjdG9yIiwiX2RlZmluZVByb3BlcnR5MiIsImRlZmF1bHQiLCJyZWNoZWNrIiwicGF5bG9hZCIsImFjdGlvbiIsIkFjdGlvbiIsIlJlY2hlY2tUaGVtZSIsImZvcmNlVGhlbWUiLCJ0aGVtZVdhdGNoUmVmIiwic3lzdGVtVGhlbWVXYXRjaFJlZiIsImRpc3BhdGNoZXJSZWYiLCJwcmVmZXJEYXJrIiwiZ2xvYmFsIiwibWF0Y2hNZWRpYSIsInByZWZlckxpZ2h0IiwicHJlZmVySGlnaENvbnRyYXN0IiwiY3VycmVudFRoZW1lIiwiZ2V0RWZmZWN0aXZlVGhlbWUiLCJzdGFydCIsIlNldHRpbmdzU3RvcmUiLCJ3YXRjaFNldHRpbmciLCJvbkNoYW5nZSIsImFkZEV2ZW50TGlzdGVuZXIiLCJkaXMiLCJyZWdpc3RlciIsIm9uQWN0aW9uIiwic3RvcCIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJ1bndhdGNoU2V0dGluZyIsInVucmVnaXN0ZXIiLCJvbGRUaGVtZSIsInVuZGVmaW5lZCIsInNldFRoZW1lIiwiVGhlbWVDb250cm9sbGVyIiwiaXNMb2dpbiIsInN5c3RlbVRoZW1lRXhwbGljaXQiLCJnZXRWYWx1ZUF0IiwiU2V0dGluZ0xldmVsIiwiREVWSUNFIiwibG9nZ2VyIiwibG9nIiwidGhlbWUiLCJ0aGVtZUJhc2VkT25TeXN0ZW0iLCJ0aGVtZUV4cGxpY2l0IiwiZ2V0VmFsdWUiLCJuZXdUaGVtZSIsIm1hdGNoZXMiLCJoY1RoZW1lIiwiZmluZEhpZ2hDb250cmFzdFRoZW1lIiwiaXNTeXN0ZW1UaGVtZVN1cHBvcnRlZCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2V0dGluZ3Mvd2F0Y2hlcnMvVGhlbWVXYXRjaGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE5LCAyMDIwIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5Db3B5cmlnaHQgMjAxOSBNaWNoYWVsIFRlbGF0eW5za2kgPDd0M2NoZ3V5QGdtYWlsLmNvbT5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuXG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IGRpcyBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBBY3Rpb24gfSBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9hY3Rpb25zXCI7XG5pbXBvcnQgVGhlbWVDb250cm9sbGVyIGZyb20gXCIuLi9jb250cm9sbGVycy9UaGVtZUNvbnRyb2xsZXJcIjtcbmltcG9ydCB7IGZpbmRIaWdoQ29udHJhc3RUaGVtZSwgc2V0VGhlbWUgfSBmcm9tIFwiLi4vLi4vdGhlbWVcIjtcbmltcG9ydCB7IEFjdGlvblBheWxvYWQgfSBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9wYXlsb2Fkc1wiO1xuaW1wb3J0IHsgU2V0dGluZ0xldmVsIH0gZnJvbSBcIi4uL1NldHRpbmdMZXZlbFwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUaGVtZVdhdGNoZXIge1xuICAgIHByaXZhdGUgdGhlbWVXYXRjaFJlZjogc3RyaW5nIHwgbnVsbDtcbiAgICBwcml2YXRlIHN5c3RlbVRoZW1lV2F0Y2hSZWY6IHN0cmluZyB8IG51bGw7XG4gICAgcHJpdmF0ZSBkaXNwYXRjaGVyUmVmOiBzdHJpbmcgfCBudWxsO1xuXG4gICAgcHJpdmF0ZSBwcmVmZXJEYXJrOiBNZWRpYVF1ZXJ5TGlzdDtcbiAgICBwcml2YXRlIHByZWZlckxpZ2h0OiBNZWRpYVF1ZXJ5TGlzdDtcbiAgICBwcml2YXRlIHByZWZlckhpZ2hDb250cmFzdDogTWVkaWFRdWVyeUxpc3Q7XG5cbiAgICBwcml2YXRlIGN1cnJlbnRUaGVtZTogc3RyaW5nO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnRoZW1lV2F0Y2hSZWYgPSBudWxsO1xuICAgICAgICB0aGlzLnN5c3RlbVRoZW1lV2F0Y2hSZWYgPSBudWxsO1xuICAgICAgICB0aGlzLmRpc3BhdGNoZXJSZWYgPSBudWxsO1xuXG4gICAgICAgIC8vIHdlIGhhdmUgYm90aCBoZXJlIGFzIGVhY2ggbWF5IGVpdGhlciBtYXRjaCBvciBub3QgbWF0Y2gsIHNvIGJ5IGhhdmluZyBib3RoXG4gICAgICAgIC8vIHdlIGNhbiBnZXQgdGhlIHRyaXN0YXRlIG9mIGRhcmsvbGlnaHQvdW5zdXBwb3J0ZWRcbiAgICAgICAgdGhpcy5wcmVmZXJEYXJrID0gKDxhbnk+Z2xvYmFsKS5tYXRjaE1lZGlhKFwiKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKVwiKTtcbiAgICAgICAgdGhpcy5wcmVmZXJMaWdodCA9ICg8YW55Pmdsb2JhbCkubWF0Y2hNZWRpYShcIihwcmVmZXJzLWNvbG9yLXNjaGVtZTogbGlnaHQpXCIpO1xuICAgICAgICB0aGlzLnByZWZlckhpZ2hDb250cmFzdCA9ICg8YW55Pmdsb2JhbCkubWF0Y2hNZWRpYShcIihwcmVmZXJzLWNvbnRyYXN0OiBtb3JlKVwiKTtcblxuICAgICAgICB0aGlzLmN1cnJlbnRUaGVtZSA9IHRoaXMuZ2V0RWZmZWN0aXZlVGhlbWUoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhcnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMudGhlbWVXYXRjaFJlZiA9IFNldHRpbmdzU3RvcmUud2F0Y2hTZXR0aW5nKFwidGhlbWVcIiwgbnVsbCwgdGhpcy5vbkNoYW5nZSk7XG4gICAgICAgIHRoaXMuc3lzdGVtVGhlbWVXYXRjaFJlZiA9IFNldHRpbmdzU3RvcmUud2F0Y2hTZXR0aW5nKFwidXNlX3N5c3RlbV90aGVtZVwiLCBudWxsLCB0aGlzLm9uQ2hhbmdlKTtcbiAgICAgICAgdGhpcy5wcmVmZXJEYXJrLmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgdGhpcy5vbkNoYW5nZSk7XG4gICAgICAgIHRoaXMucHJlZmVyTGlnaHQuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCB0aGlzLm9uQ2hhbmdlKTtcbiAgICAgICAgdGhpcy5wcmVmZXJIaWdoQ29udHJhc3QuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCB0aGlzLm9uQ2hhbmdlKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyUmVmID0gZGlzLnJlZ2lzdGVyKHRoaXMub25BY3Rpb24pO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnByZWZlckRhcmsucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCB0aGlzLm9uQ2hhbmdlKTtcbiAgICAgICAgdGhpcy5wcmVmZXJMaWdodC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2hhbmdlXCIsIHRoaXMub25DaGFuZ2UpO1xuICAgICAgICB0aGlzLnByZWZlckhpZ2hDb250cmFzdC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2hhbmdlXCIsIHRoaXMub25DaGFuZ2UpO1xuICAgICAgICBpZiAodGhpcy5zeXN0ZW1UaGVtZVdhdGNoUmVmKSBTZXR0aW5nc1N0b3JlLnVud2F0Y2hTZXR0aW5nKHRoaXMuc3lzdGVtVGhlbWVXYXRjaFJlZik7XG4gICAgICAgIGlmICh0aGlzLnRoZW1lV2F0Y2hSZWYpIFNldHRpbmdzU3RvcmUudW53YXRjaFNldHRpbmcodGhpcy50aGVtZVdhdGNoUmVmKTtcbiAgICAgICAgaWYgKHRoaXMuZGlzcGF0Y2hlclJlZikgZGlzLnVucmVnaXN0ZXIodGhpcy5kaXNwYXRjaGVyUmVmKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uQ2hhbmdlID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnJlY2hlY2soKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkFjdGlvbiA9IChwYXlsb2FkOiBBY3Rpb25QYXlsb2FkKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChwYXlsb2FkLmFjdGlvbiA9PT0gQWN0aW9uLlJlY2hlY2tUaGVtZSkge1xuICAgICAgICAgICAgLy8gWFhYIGZvcmNlVGhlbWVcbiAgICAgICAgICAgIHRoaXMucmVjaGVjayhwYXlsb2FkLmZvcmNlVGhlbWUpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8vIFhYWDogZm9yY2VUaGVtZSBwYXJhbSBhZGRlZCBoZXJlIGFzIGxvY2FsIGVjaG8gYXBwZWFycyB0byBiZSB1bnJlbGlhYmxlXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3ZlY3Rvci1pbS9lbGVtZW50LXdlYi9pc3N1ZXMvMTE0NDNcbiAgICBwdWJsaWMgcmVjaGVjayhmb3JjZVRoZW1lPzogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG9sZFRoZW1lID0gdGhpcy5jdXJyZW50VGhlbWU7XG4gICAgICAgIHRoaXMuY3VycmVudFRoZW1lID0gZm9yY2VUaGVtZSA9PT0gdW5kZWZpbmVkID8gdGhpcy5nZXRFZmZlY3RpdmVUaGVtZSgpIDogZm9yY2VUaGVtZTtcbiAgICAgICAgaWYgKG9sZFRoZW1lICE9PSB0aGlzLmN1cnJlbnRUaGVtZSkge1xuICAgICAgICAgICAgc2V0VGhlbWUodGhpcy5jdXJyZW50VGhlbWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGdldEVmZmVjdGl2ZVRoZW1lKCk6IHN0cmluZyB7XG4gICAgICAgIC8vIERldiBub3RlOiBNdWNoIG9mIHRoaXMgbG9naWMgaXMgcmVwbGljYXRlZCBpbiB0aGUgQXBwZWFyYW5jZVVzZXJTZXR0aW5nc1RhYlxuXG4gICAgICAgIC8vIFhYWDogY2hlY2tpbmcgdGhlIGlzTGlnaHQgZmxhZyBoZXJlIG1ha2VzIGNoZWNraW5nIGl0IGluIHRoZSBUaGVtZUNvbnRyb2xsZXJcbiAgICAgICAgLy8gaXRzZWxmIGNvbXBsZXRlbHkgcmVkdW5kYW50IHNpbmNlIHdlIGp1c3Qgb3ZlcnJpZGUgdGhlIHJlc3VsdCBoZXJlIGFuZCB3ZSdyZVxuICAgICAgICAvLyBub3cgZWZmZWN0aXZlbHkganVzdCB1c2luZyB0aGUgVGhlbWVDb250cm9sbGVyIGFzIGEgcGxhY2UgdG8gc3RvcmUgdGhlIHN0YXRpY1xuICAgICAgICAvLyB2YXJpYWJsZS4gVGhlIHN5c3RlbSB0aGVtZSBzZXR0aW5nIHByb2JhYmx5IG91Z2h0IHRvIGhhdmUgYW4gZXF1aXZhbGVudFxuICAgICAgICAvLyBjb250cm9sbGVyIHRoYXQgaG9ub3VycyB0aGUgc2FtZSBmbGFnLCBhbHRob3VnaCBwcm9iYWJseSBiZXR0ZXIgd291bGQgYmUgdG9cbiAgICAgICAgLy8gaGF2ZSB0aGUgdGhlbWUgbG9naWMgaW4gb25lIHBsYWNlIHJhdGhlciB0aGFuIHNwbGl0IGJldHdlZW4gaG93ZXZlciBtYW55XG4gICAgICAgIC8vIGRpZmZlcmVudCBwbGFjZXMuXG4gICAgICAgIGlmIChUaGVtZUNvbnRyb2xsZXIuaXNMb2dpbikgcmV0dXJuIFwibGlnaHRcIjtcblxuICAgICAgICAvLyBJZiB0aGUgdXNlciBoYXMgc3BlY2lmaWNhbGx5IGVuYWJsZWQgdGhlIHN5c3RlbSBtYXRjaGluZyBvcHRpb24gKGV4Y2x1ZGluZyBkZWZhdWx0KSxcbiAgICAgICAgLy8gdGhlbiB1c2UgdGhhdCBvdmVyIGFueXRoaW5nIGVsc2UuIFdlIHBpY2sgdGhlIGxvd2VzdCBwb3NzaWJsZSBsZXZlbCBmb3IgdGhlIHNldHRpbmdcbiAgICAgICAgLy8gdG8gZW5zdXJlIHRoZSBvcmRlcmluZyBvdGhlcndpc2Ugd29ya3MuXG4gICAgICAgIGNvbnN0IHN5c3RlbVRoZW1lRXhwbGljaXQgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlQXQoXG4gICAgICAgICAgICBTZXR0aW5nTGV2ZWwuREVWSUNFLFxuICAgICAgICAgICAgXCJ1c2Vfc3lzdGVtX3RoZW1lXCIsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICB0cnVlLFxuICAgICAgICApO1xuICAgICAgICBpZiAoc3lzdGVtVGhlbWVFeHBsaWNpdCkge1xuICAgICAgICAgICAgbG9nZ2VyLmxvZyhcInJldHVybmluZyBleHBsaWNpdCBzeXN0ZW0gdGhlbWVcIik7XG4gICAgICAgICAgICBjb25zdCB0aGVtZSA9IHRoaXMudGhlbWVCYXNlZE9uU3lzdGVtKCk7XG4gICAgICAgICAgICBpZiAodGhlbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhlbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgdXNlciBoYXMgc3BlY2lmaWNhbGx5IGVuYWJsZWQgdGhlIHRoZW1lICh3aXRob3V0IHRoZSBzeXN0ZW0gbWF0Y2hpbmcgb3B0aW9uIGJlaW5nXG4gICAgICAgIC8vIGVuYWJsZWQgc3BlY2lmaWNhbGx5IGFuZCBleGNsdWRpbmcgdGhlIGRlZmF1bHQpLCB1c2UgdGhhdCB0aGVtZS4gV2UgcGljayB0aGUgbG93ZXN0IHBvc3NpYmxlXG4gICAgICAgIC8vIGxldmVsIGZvciB0aGUgc2V0dGluZyB0byBlbnN1cmUgdGhlIG9yZGVyaW5nIG90aGVyd2lzZSB3b3Jrcy5cbiAgICAgICAgY29uc3QgdGhlbWVFeHBsaWNpdCA9IFNldHRpbmdzU3RvcmUuZ2V0VmFsdWVBdChTZXR0aW5nTGV2ZWwuREVWSUNFLCBcInRoZW1lXCIsIG51bGwsIGZhbHNlLCB0cnVlKTtcbiAgICAgICAgaWYgKHRoZW1lRXhwbGljaXQpIHtcbiAgICAgICAgICAgIGxvZ2dlci5sb2coXCJyZXR1cm5pbmcgZXhwbGljaXQgdGhlbWU6IFwiICsgdGhlbWVFeHBsaWNpdCk7XG4gICAgICAgICAgICByZXR1cm4gdGhlbWVFeHBsaWNpdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHRoZSB1c2VyIGhhc24ndCByZWFsbHkgbWFkZSBhIHByZWZlcmVuY2UgaW4gZWl0aGVyIGRpcmVjdGlvbiwgYXNzdW1lIHRoZSBkZWZhdWx0cyBvZiB0aGVcbiAgICAgICAgLy8gc2V0dGluZ3MgYW5kIHVzZSB0aG9zZS5cbiAgICAgICAgaWYgKFNldHRpbmdzU3RvcmUuZ2V0VmFsdWUoXCJ1c2Vfc3lzdGVtX3RoZW1lXCIpKSB7XG4gICAgICAgICAgICBjb25zdCB0aGVtZSA9IHRoaXMudGhlbWVCYXNlZE9uU3lzdGVtKCk7XG4gICAgICAgICAgICBpZiAodGhlbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhlbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbG9nZ2VyLmxvZyhcInJldHVybmluZyB0aGVtZSB2YWx1ZVwiKTtcbiAgICAgICAgcmV0dXJuIFNldHRpbmdzU3RvcmUuZ2V0VmFsdWUoXCJ0aGVtZVwiKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHRoZW1lQmFzZWRPblN5c3RlbSgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgbmV3VGhlbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHRoaXMucHJlZmVyRGFyay5tYXRjaGVzKSB7XG4gICAgICAgICAgICBuZXdUaGVtZSA9IFwiZGFya1wiO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMucHJlZmVyTGlnaHQubWF0Y2hlcykge1xuICAgICAgICAgICAgbmV3VGhlbWUgPSBcImxpZ2h0XCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5ld1RoZW1lICYmIHRoaXMucHJlZmVySGlnaENvbnRyYXN0Lm1hdGNoZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGhjVGhlbWUgPSBmaW5kSGlnaENvbnRyYXN0VGhlbWUobmV3VGhlbWUpO1xuICAgICAgICAgICAgaWYgKGhjVGhlbWUpIHtcbiAgICAgICAgICAgICAgICBuZXdUaGVtZSA9IGhjVGhlbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ld1RoZW1lO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc1N5c3RlbVRoZW1lU3VwcG9ydGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5wcmVmZXJEYXJrLm1hdGNoZXMgfHwgdGhpcy5wcmVmZXJMaWdodC5tYXRjaGVzO1xuICAgIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQSxJQUFBQSxPQUFBLEdBQUFDLE9BQUE7QUFFQSxJQUFBQyxjQUFBLEdBQUFDLHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBRyxXQUFBLEdBQUFELHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBSSxRQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxnQkFBQSxHQUFBSCxzQkFBQSxDQUFBRixPQUFBO0FBQ0EsSUFBQU0sTUFBQSxHQUFBTixPQUFBO0FBRUEsSUFBQU8sYUFBQSxHQUFBUCxPQUFBO0FBakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBWWUsTUFBTVEsWUFBWSxDQUFDO0VBV3ZCQyxXQUFXQSxDQUFBLEVBQUc7SUFBQSxJQUFBQyxnQkFBQSxDQUFBQyxPQUFBO0lBQUEsSUFBQUQsZ0JBQUEsQ0FBQUMsT0FBQTtJQUFBLElBQUFELGdCQUFBLENBQUFDLE9BQUE7SUFBQSxJQUFBRCxnQkFBQSxDQUFBQyxPQUFBO0lBQUEsSUFBQUQsZ0JBQUEsQ0FBQUMsT0FBQTtJQUFBLElBQUFELGdCQUFBLENBQUFDLE9BQUE7SUFBQSxJQUFBRCxnQkFBQSxDQUFBQyxPQUFBO0lBQUEsSUFBQUQsZ0JBQUEsQ0FBQUMsT0FBQSxvQkFnQ0YsTUFBWTtNQUMzQixJQUFJLENBQUNDLE9BQU8sQ0FBQyxDQUFDO0lBQ2xCLENBQUM7SUFBQSxJQUFBRixnQkFBQSxDQUFB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