matrix-react-sdk
Version:
SDK for matrix.org using React
385 lines (380 loc) • 67.6 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _MatrixClientPeg = require("../../MatrixClientPeg");
var _dispatcher = _interopRequireDefault(require("../../dispatcher/dispatcher"));
var _actions = require("../../dispatcher/actions");
var _languageHandler = require("../../languageHandler");
var _ContextMenu = require("./ContextMenu");
var _UserTab = require("../views/dialogs/UserTab");
var _FeedbackDialog = _interopRequireDefault(require("../views/dialogs/FeedbackDialog"));
var _Modal = _interopRequireDefault(require("../../Modal"));
var _LogoutDialog = _interopRequireWildcard(require("../views/dialogs/LogoutDialog"));
var _SettingsStore = _interopRequireDefault(require("../../settings/SettingsStore"));
var _theme = require("../../theme");
var _RovingTabIndex = require("../../accessibility/RovingTabIndex");
var _AccessibleButton = _interopRequireDefault(require("../views/elements/AccessibleButton"));
var _SdkConfig = _interopRequireDefault(require("../../SdkConfig"));
var _pages = require("../../utils/pages");
var _OwnProfileStore = require("../../stores/OwnProfileStore");
var _AsyncStore = require("../../stores/AsyncStore");
var _BaseAvatar = _interopRequireDefault(require("../views/avatars/BaseAvatar"));
var _SettingLevel = require("../../settings/SettingLevel");
var _IconizedContextMenu = _interopRequireWildcard(require("../views/context_menus/IconizedContextMenu"));
var _UIFeature = require("../../settings/UIFeature");
var _SpaceStore = _interopRequireDefault(require("../../stores/spaces/SpaceStore"));
var _spaces = require("../../stores/spaces");
var _UserIdentifier = _interopRequireDefault(require("../../customisations/UserIdentifier"));
var _PosthogTrackers = _interopRequireDefault(require("../../PosthogTrackers"));
var _live8px = require("../../../res/img/compound/live-8px.svg");
var _voiceBroadcast = require("../../voice-broadcast");
var _SDKContext = require("../../contexts/SDKContext");
var _Feedback = require("../../utils/Feedback");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
const toRightOf = rect => {
return {
left: rect.width + rect.left + 8,
top: rect.top,
chevronFace: _ContextMenu.ChevronFace.None
};
};
const below = rect => {
return {
left: rect.left,
top: rect.top + rect.height,
chevronFace: _ContextMenu.ChevronFace.None
};
};
class UserMenu extends _react.default.Component {
constructor(_props, context) {
super(_props, context);
(0, _defineProperty2.default)(this, "dispatcherRef", void 0);
(0, _defineProperty2.default)(this, "themeWatcherRef", void 0);
(0, _defineProperty2.default)(this, "dndWatcherRef", void 0);
(0, _defineProperty2.default)(this, "buttonRef", /*#__PURE__*/(0, _react.createRef)());
(0, _defineProperty2.default)(this, "onCurrentVoiceBroadcastRecordingChanged", recording => {
this.setState({
showLiveAvatarAddon: recording !== null
});
});
(0, _defineProperty2.default)(this, "onProfileUpdate", async () => {
// the store triggered an update, so force a layout update. We don't
// have any state to store here for that to magically happen.
this.forceUpdate();
});
(0, _defineProperty2.default)(this, "onSelectedSpaceUpdate", async () => {
this.setState({
selectedSpace: _SpaceStore.default.instance.activeSpaceRoom
});
});
(0, _defineProperty2.default)(this, "onThemeChanged", () => {
this.setState({
isDarkTheme: this.isUserOnDarkTheme(),
isHighContrast: this.isUserOnHighContrastTheme()
});
});
(0, _defineProperty2.default)(this, "onAction", payload => {
switch (payload.action) {
case _actions.Action.ToggleUserMenu:
if (this.state.contextMenuPosition) {
this.setState({
contextMenuPosition: null
});
} else {
if (this.buttonRef.current) this.buttonRef.current.click();
}
break;
}
});
(0, _defineProperty2.default)(this, "onOpenMenuClick", ev => {
ev.preventDefault();
ev.stopPropagation();
this.setState({
contextMenuPosition: ev.currentTarget.getBoundingClientRect()
});
});
(0, _defineProperty2.default)(this, "onContextMenu", ev => {
ev.preventDefault();
ev.stopPropagation();
this.setState({
contextMenuPosition: {
left: ev.clientX,
top: ev.clientY,
width: 20,
height: 0
}
});
});
(0, _defineProperty2.default)(this, "onCloseMenu", () => {
this.setState({
contextMenuPosition: null
});
});
(0, _defineProperty2.default)(this, "onSwitchThemeClick", ev => {
ev.preventDefault();
ev.stopPropagation();
_PosthogTrackers.default.trackInteraction("WebUserMenuThemeToggleButton", ev);
// Disable system theme matching if the user hits this button
_SettingsStore.default.setValue("use_system_theme", null, _SettingLevel.SettingLevel.DEVICE, false);
let newTheme = this.state.isDarkTheme ? "light" : "dark";
if (this.state.isHighContrast) {
const hcTheme = (0, _theme.findHighContrastTheme)(newTheme);
if (hcTheme) {
newTheme = hcTheme;
}
}
_SettingsStore.default.setValue("theme", null, _SettingLevel.SettingLevel.DEVICE, newTheme); // set at same level as Appearance tab
});
(0, _defineProperty2.default)(this, "onSettingsOpen", (ev, tabId, props) => {
ev.preventDefault();
ev.stopPropagation();
const payload = {
action: _actions.Action.ViewUserSettings,
initialTabId: tabId,
props
};
_dispatcher.default.dispatch(payload);
this.setState({
contextMenuPosition: null
}); // also close the menu
});
(0, _defineProperty2.default)(this, "onProvideFeedback", ev => {
ev.preventDefault();
ev.stopPropagation();
_Modal.default.createDialog(_FeedbackDialog.default);
this.setState({
contextMenuPosition: null
}); // also close the menu
});
(0, _defineProperty2.default)(this, "onSignOutClick", async ev => {
ev.preventDefault();
ev.stopPropagation();
if (await (0, _LogoutDialog.shouldShowLogoutDialog)(_MatrixClientPeg.MatrixClientPeg.safeGet())) {
_Modal.default.createDialog(_LogoutDialog.default);
} else {
_dispatcher.default.dispatch({
action: "logout"
});
}
this.setState({
contextMenuPosition: null
}); // also close the menu
});
(0, _defineProperty2.default)(this, "onSignInClick", () => {
_dispatcher.default.dispatch({
action: "start_login"
});
this.setState({
contextMenuPosition: null
}); // also close the menu
});
(0, _defineProperty2.default)(this, "onRegisterClick", () => {
_dispatcher.default.dispatch({
action: "start_registration"
});
this.setState({
contextMenuPosition: null
}); // also close the menu
});
(0, _defineProperty2.default)(this, "onHomeClick", ev => {
ev.preventDefault();
ev.stopPropagation();
_dispatcher.default.dispatch({
action: _actions.Action.ViewHomePage
});
this.setState({
contextMenuPosition: null
}); // also close the menu
});
(0, _defineProperty2.default)(this, "renderContextMenu", () => {
if (!this.state.contextMenuPosition) return null;
let topSection;
if (_MatrixClientPeg.MatrixClientPeg.safeGet().isGuest()) {
topSection = /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserMenu_contextMenu_header mx_UserMenu_contextMenu_guestPrompts"
}, (0, _languageHandler._t)("auth|sign_in_prompt", {}, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: this.onSignInClick
}, sub)
}), _SettingsStore.default.getValue(_UIFeature.UIFeature.Registration) ? (0, _languageHandler._t)("auth|create_account_prompt", {}, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: this.onRegisterClick
}, sub)
}) : null);
}
let homeButton;
if (this.hasHomePage) {
homeButton = /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, {
iconClassName: "mx_UserMenu_iconHome",
label: (0, _languageHandler._t)("common|home"),
onClick: this.onHomeClick
});
}
let feedbackButton;
if ((0, _Feedback.shouldShowFeedback)()) {
feedbackButton = /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, {
iconClassName: "mx_UserMenu_iconMessage",
label: (0, _languageHandler._t)("common|feedback"),
onClick: this.onProvideFeedback
});
}
const linkNewDeviceButton = /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, {
iconClassName: "mx_UserMenu_iconQr",
label: (0, _languageHandler._t)("user_menu|link_new_device"),
onClick: e => this.onSettingsOpen(e, _UserTab.UserTab.SessionManager, {
showMsc4108QrCode: true
})
});
let primaryOptionList = /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOptionList, null, homeButton, linkNewDeviceButton, /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, {
iconClassName: "mx_UserMenu_iconBell",
label: (0, _languageHandler._t)("notifications|enable_prompt_toast_title"),
onClick: e => this.onSettingsOpen(e, _UserTab.UserTab.Notifications)
}), /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, {
iconClassName: "mx_UserMenu_iconLock",
label: (0, _languageHandler._t)("room_settings|security|title"),
onClick: e => this.onSettingsOpen(e, _UserTab.UserTab.Security)
}), /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, {
iconClassName: "mx_UserMenu_iconSettings",
label: (0, _languageHandler._t)("user_menu|settings"),
onClick: e => this.onSettingsOpen(e)
}), feedbackButton, /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, {
className: "mx_IconizedContextMenu_option_red",
iconClassName: "mx_UserMenu_iconSignOut",
label: (0, _languageHandler._t)("action|sign_out"),
onClick: this.onSignOutClick
}));
if (_MatrixClientPeg.MatrixClientPeg.safeGet().isGuest()) {
primaryOptionList = /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOptionList, null, homeButton, /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, {
iconClassName: "mx_UserMenu_iconSettings",
label: (0, _languageHandler._t)("common|settings"),
onClick: e => this.onSettingsOpen(e)
}), feedbackButton);
}
const position = this.props.isPanelCollapsed ? toRightOf(this.state.contextMenuPosition) : below(this.state.contextMenuPosition);
return /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.default, (0, _extends2.default)({}, position, {
onFinished: this.onCloseMenu,
className: "mx_UserMenu_contextMenu"
}), /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserMenu_contextMenu_header"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserMenu_contextMenu_name"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "mx_UserMenu_contextMenu_displayName"
}, _OwnProfileStore.OwnProfileStore.instance.displayName), /*#__PURE__*/_react.default.createElement("span", {
className: "mx_UserMenu_contextMenu_userId"
}, _UserIdentifier.default.getDisplayUserIdentifier(_MatrixClientPeg.MatrixClientPeg.safeGet().getSafeUserId(), {
withDisplayName: true
}))), /*#__PURE__*/_react.default.createElement(_RovingTabIndex.RovingAccessibleButton, {
className: "mx_UserMenu_contextMenu_themeButton",
onClick: this.onSwitchThemeClick,
title: this.state.isDarkTheme ? (0, _languageHandler._t)("user_menu|switch_theme_light") : (0, _languageHandler._t)("user_menu|switch_theme_dark")
}, /*#__PURE__*/_react.default.createElement("img", {
src: require("../../../res/img/element-icons/roomlist/dark-light-mode.svg").default,
role: "presentation",
alt: "",
width: 16
}))), topSection, primaryOptionList);
});
this.state = {
contextMenuPosition: null,
isDarkTheme: this.isUserOnDarkTheme(),
isHighContrast: this.isUserOnHighContrastTheme(),
selectedSpace: _SpaceStore.default.instance.activeSpaceRoom,
showLiveAvatarAddon: this.context.voiceBroadcastRecordingsStore.hasCurrent()
};
_OwnProfileStore.OwnProfileStore.instance.on(_AsyncStore.UPDATE_EVENT, this.onProfileUpdate);
_SpaceStore.default.instance.on(_spaces.UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdate);
}
get hasHomePage() {
return !!(0, _pages.getHomePageUrl)(_SdkConfig.default.get(), this.context.client);
}
componentDidMount() {
this.context.voiceBroadcastRecordingsStore.on(_voiceBroadcast.VoiceBroadcastRecordingsStoreEvent.CurrentChanged, this.onCurrentVoiceBroadcastRecordingChanged);
this.dispatcherRef = _dispatcher.default.register(this.onAction);
this.themeWatcherRef = _SettingsStore.default.watchSetting("theme", null, this.onThemeChanged);
}
componentWillUnmount() {
if (this.themeWatcherRef) _SettingsStore.default.unwatchSetting(this.themeWatcherRef);
if (this.dndWatcherRef) _SettingsStore.default.unwatchSetting(this.dndWatcherRef);
if (this.dispatcherRef) _dispatcher.default.unregister(this.dispatcherRef);
_OwnProfileStore.OwnProfileStore.instance.off(_AsyncStore.UPDATE_EVENT, this.onProfileUpdate);
_SpaceStore.default.instance.off(_spaces.UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdate);
this.context.voiceBroadcastRecordingsStore.off(_voiceBroadcast.VoiceBroadcastRecordingsStoreEvent.CurrentChanged, this.onCurrentVoiceBroadcastRecordingChanged);
}
isUserOnDarkTheme() {
if (_SettingsStore.default.getValue("use_system_theme")) {
return window.matchMedia("(prefers-color-scheme: dark)").matches;
} else {
const theme = _SettingsStore.default.getValue("theme");
if (theme.startsWith("custom-")) {
return !!(0, _theme.getCustomTheme)(theme.substring("custom-".length)).is_dark;
}
return theme === "dark";
}
}
isUserOnHighContrastTheme() {
if (_SettingsStore.default.getValue("use_system_theme")) {
return window.matchMedia("(prefers-contrast: more)").matches;
} else {
const theme = _SettingsStore.default.getValue("theme");
if (theme.startsWith("custom-")) {
return false;
}
return (0, _theme.isHighContrastTheme)(theme);
}
}
render() {
const avatarSize = 32; // should match border-radius of the avatar
const userId = _MatrixClientPeg.MatrixClientPeg.safeGet().getSafeUserId();
const displayName = _OwnProfileStore.OwnProfileStore.instance.displayName || userId;
const avatarUrl = _OwnProfileStore.OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
let name;
if (!this.props.isPanelCollapsed) {
name = /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserMenu_name"
}, displayName);
}
const liveAvatarAddon = this.state.showLiveAvatarAddon ? /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserMenu_userAvatarLive",
"data-testid": "user-menu-live-vb"
}, /*#__PURE__*/_react.default.createElement(_live8px.Icon, {
className: "mx_Icon_8"
})) : null;
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserMenu"
}, /*#__PURE__*/_react.default.createElement(_ContextMenu.ContextMenuButton, {
className: "mx_UserMenu_contextMenuButton",
onClick: this.onOpenMenuClick,
ref: this.buttonRef,
label: (0, _languageHandler._t)("a11y|user_menu"),
isExpanded: !!this.state.contextMenuPosition,
onContextMenu: this.onContextMenu
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_UserMenu_userAvatar"
}, /*#__PURE__*/_react.default.createElement(_BaseAvatar.default, {
idName: userId,
name: displayName,
url: avatarUrl,
size: avatarSize + "px",
className: "mx_UserMenu_userAvatar_BaseAvatar"
}), liveAvatarAddon), name, this.renderContextMenu()), this.props.children);
}
}
exports.default = UserMenu;
(0, _defineProperty2.default)(UserMenu, "contextType", _SDKContext.SDKContext);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfTWF0cml4Q2xpZW50UGVnIiwiX2Rpc3BhdGNoZXIiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX2FjdGlvbnMiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX0NvbnRleHRNZW51IiwiX1VzZXJUYWIiLCJfRmVlZGJhY2tEaWFsb2ciLCJfTW9kYWwiLCJfTG9nb3V0RGlhbG9nIiwiX1NldHRpbmdzU3RvcmUiLCJfdGhlbWUiLCJfUm92aW5nVGFiSW5kZXgiLCJfQWNjZXNzaWJsZUJ1dHRvbiIsIl9TZGtDb25maWciLCJfcGFnZXMiLCJfT3duUHJvZmlsZVN0b3JlIiwiX0FzeW5jU3RvcmUiLCJfQmFzZUF2YXRhciIsIl9TZXR0aW5nTGV2ZWwiLCJfSWNvbml6ZWRDb250ZXh0TWVudSIsIl9VSUZlYXR1cmUiLCJfU3BhY2VTdG9yZSIsIl9zcGFjZXMiLCJfVXNlcklkZW50aWZpZXIiLCJfUG9zdGhvZ1RyYWNrZXJzIiwiX2xpdmU4cHgiLCJfdm9pY2VCcm9hZGNhc3QiLCJfU0RLQ29udGV4dCIsIl9GZWVkYmFjayIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsInRvUmlnaHRPZiIsInJlY3QiLCJsZWZ0Iiwid2lkdGgiLCJ0b3AiLCJjaGV2cm9uRmFjZSIsIkNoZXZyb25GYWNlIiwiTm9uZSIsImJlbG93IiwiaGVpZ2h0IiwiVXNlck1lbnUiLCJSZWFjdCIsIkNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicHJvcHMiLCJjb250ZXh0IiwiX2RlZmluZVByb3BlcnR5MiIsImNyZWF0ZVJlZiIsInJlY29yZGluZyIsInNldFN0YXRlIiwic2hvd0xpdmVBdmF0YXJBZGRvbiIsImZvcmNlVXBkYXRlIiwic2VsZWN0ZWRTcGFjZSIsIlNwYWNlU3RvcmUiLCJpbnN0YW5jZSIsImFjdGl2ZVNwYWNlUm9vbSIsImlzRGFya1RoZW1lIiwiaXNVc2VyT25EYXJrVGhlbWUiLCJpc0hpZ2hDb250cmFzdCIsImlzVXNlck9uSGlnaENvbnRyYXN0VGhlbWUiLCJwYXlsb2FkIiwiYWN0aW9uIiwiQWN0aW9uIiwiVG9nZ2xlVXNlck1lbnUiLCJzdGF0ZSIsImNvbnRleHRNZW51UG9zaXRpb24iLCJidXR0b25SZWYiLCJjdXJyZW50IiwiY2xpY2siLCJldiIsInByZXZlbnREZWZhdWx0Iiwic3RvcFByb3BhZ2F0aW9uIiwiY3VycmVudFRhcmdldCIsImdldEJvdW5kaW5nQ2xpZW50UmVjdCIsImNsaWVudFgiLCJjbGllbnRZIiwiUG9zdGhvZ1RyYWNrZXJzIiwidHJhY2tJbnRlcmFjdGlvbiIsIlNldHRpbmdzU3RvcmUiLCJzZXRWYWx1ZSIsIlNldHRpbmdMZXZlbCIsIkRFVklDRSIsIm5ld1RoZW1lIiwiaGNUaGVtZSIsImZpbmRIaWdoQ29udHJhc3RUaGVtZSIsInRhYklkIiwiVmlld1VzZXJTZXR0aW5ncyIsImluaXRpYWxUYWJJZCIsImRlZmF1bHREaXNwYXRjaGVyIiwiZGlzcGF0Y2giLCJNb2RhbCIsImNyZWF0ZURpYWxvZyIsIkZlZWRiYWNrRGlhbG9nIiwic2hvdWxkU2hvd0xvZ291dERpYWxvZyIsIk1hdHJpeENsaWVudFBlZyIsInNhZmVHZXQiLCJMb2dvdXREaWFsb2ciLCJWaWV3SG9tZVBhZ2UiLCJ0b3BTZWN0aW9uIiwiaXNHdWVzdCIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc05hbWUiLCJfdCIsInN1YiIsImtpbmQiLCJvbkNsaWNrIiwib25TaWduSW5DbGljayIsImdldFZhbHVlIiwiVUlGZWF0dXJlIiwiUmVnaXN0cmF0aW9uIiwib25SZWdpc3RlckNsaWNrIiwiaG9tZUJ1dHRvbiIsImhhc0hvbWVQYWdlIiwiSWNvbml6ZWRDb250ZXh0TWVudU9wdGlvbiIsImljb25DbGFzc05hbWUiLCJsYWJlbCIsIm9uSG9tZUNsaWNrIiwiZmVlZGJhY2tCdXR0b24iLCJzaG91bGRTaG93RmVlZGJhY2siLCJvblByb3ZpZGVGZWVkYmFjayIsImxpbmtOZXdEZXZpY2VCdXR0b24iLCJvblNldHRpbmdzT3BlbiIsIlVzZXJUYWIiLCJTZXNzaW9uTWFuYWdlciIsInNob3dNc2M0MTA4UXJDb2RlIiwicHJpbWFyeU9wdGlvbkxpc3QiLCJJY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdCIsIk5vdGlmaWNhdGlvbnMiLCJTZWN1cml0eSIsIm9uU2lnbk91dENsaWNrIiwicG9zaXRpb24iLCJpc1BhbmVsQ29sbGFwc2VkIiwiX2V4dGVuZHMyIiwib25GaW5pc2hlZCIsIm9uQ2xvc2VNZW51IiwiT3duUHJvZmlsZVN0b3JlIiwiZGlzcGxheU5hbWUiLCJVc2VySWRlbnRpZmllckN1c3RvbWlzYXRpb25zIiwiZ2V0RGlzcGxheVVzZXJJZGVudGlmaWVyIiwiZ2V0U2FmZVVzZXJJZCIsIndpdGhEaXNwbGF5TmFtZSIsIlJvdmluZ0FjY2Vzc2libGVCdXR0b24iLCJvblN3aXRjaFRoZW1lQ2xpY2siLCJ0aXRsZSIsInNyYyIsInJvbGUiLCJhbHQiLCJ2b2ljZUJyb2FkY2FzdFJlY29yZGluZ3NTdG9yZSIsImhhc0N1cnJlbnQiLCJvbiIsIlVQREFURV9FVkVOVCIsIm9uUHJvZmlsZVVwZGF0ZSIsIlVQREFURV9TRUxFQ1RFRF9TUEFDRSIsIm9uU2VsZWN0ZWRTcGFjZVVwZGF0ZSIsImdldEhvbWVQYWdlVXJsIiwiU2RrQ29uZmlnIiwiY2xpZW50IiwiY29tcG9uZW50RGlkTW91bnQiLCJWb2ljZUJyb2FkY2FzdFJlY29yZGluZ3NTdG9yZUV2ZW50IiwiQ3VycmVudENoYW5nZWQiLCJvbkN1cnJlbnRWb2ljZUJyb2FkY2FzdFJlY29yZGluZ0NoYW5nZWQiLCJkaXNwYXRjaGVyUmVmIiwicmVnaXN0ZXIiLCJvbkFjdGlvbiIsInRoZW1lV2F0Y2hlclJlZiIsIndhdGNoU2V0dGluZyIsIm9uVGhlbWVDaGFuZ2VkIiwiY29tcG9uZW50V2lsbFVubW91bnQiLCJ1bndhdGNoU2V0dGluZyIsImRuZFdhdGNoZXJSZWYiLCJ1bnJlZ2lzdGVyIiwib2ZmIiwid2luZG93IiwibWF0Y2hNZWRpYSIsIm1hdGNoZXMiLCJ0aGVtZSIsInN0YXJ0c1dpdGgiLCJnZXRDdXN0b21UaGVtZSIsInN1YnN0cmluZyIsImxlbmd0aCIsImlzX2RhcmsiLCJpc0hpZ2hDb250cmFzdFRoZW1lIiwicmVuZGVyIiwiYXZhdGFyU2l6ZSIsInVzZXJJZCIsImF2YXRhclVybCIsImdldEh0dHBBdmF0YXJVcmwiLCJuYW1lIiwibGl2ZUF2YXRhckFkZG9uIiwiSWNvbiIsIkNvbnRleHRNZW51QnV0dG9uIiwib25PcGVuTWVudUNsaWNrIiwicmVmIiwiaXNFeHBhbmRlZCIsIm9uQ29udGV4dE1lbnUiLCJpZE5hbWUiLCJ1cmwiLCJzaXplIiwicmVuZGVyQ29udGV4dE1lbnUiLCJjaGlsZHJlbiIsImV4cG9ydHMiLCJTREtDb250ZXh0Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc3RydWN0dXJlcy9Vc2VyTWVudS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjAsIDIwMjEgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0LCB7IGNyZWF0ZVJlZiwgUmVhY3ROb2RlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBSb29tIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuXG5pbXBvcnQgeyBNYXRyaXhDbGllbnRQZWcgfSBmcm9tIFwiLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgZGVmYXVsdERpc3BhdGNoZXIgZnJvbSBcIi4uLy4uL2Rpc3BhdGNoZXIvZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHsgQWN0aW9uUGF5bG9hZCB9IGZyb20gXCIuLi8uLi9kaXNwYXRjaGVyL3BheWxvYWRzXCI7XG5pbXBvcnQgeyBBY3Rpb24gfSBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9hY3Rpb25zXCI7XG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCB7IENoZXZyb25GYWNlLCBDb250ZXh0TWVudUJ1dHRvbiwgTWVudVByb3BzIH0gZnJvbSBcIi4vQ29udGV4dE1lbnVcIjtcbmltcG9ydCB7IFVzZXJUYWIgfSBmcm9tIFwiLi4vdmlld3MvZGlhbG9ncy9Vc2VyVGFiXCI7XG5pbXBvcnQgeyBPcGVuVG9UYWJQYXlsb2FkIH0gZnJvbSBcIi4uLy4uL2Rpc3BhdGNoZXIvcGF5bG9hZHMvT3BlblRvVGFiUGF5bG9hZFwiO1xuaW1wb3J0IEZlZWRiYWNrRGlhbG9nIGZyb20gXCIuLi92aWV3cy9kaWFsb2dzL0ZlZWRiYWNrRGlhbG9nXCI7XG5pbXBvcnQgTW9kYWwgZnJvbSBcIi4uLy4uL01vZGFsXCI7XG5pbXBvcnQgTG9nb3V0RGlhbG9nLCB7IHNob3VsZFNob3dMb2dvdXREaWFsb2cgfSBmcm9tIFwiLi4vdmlld3MvZGlhbG9ncy9Mb2dvdXREaWFsb2dcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuLi8uLi9zZXR0aW5ncy9TZXR0aW5nc1N0b3JlXCI7XG5pbXBvcnQgeyBmaW5kSGlnaENvbnRyYXN0VGhlbWUsIGdldEN1c3RvbVRoZW1lLCBpc0hpZ2hDb250cmFzdFRoZW1lIH0gZnJvbSBcIi4uLy4uL3RoZW1lXCI7XG5pbXBvcnQgeyBSb3ZpbmdBY2Nlc3NpYmxlQnV0dG9uIH0gZnJvbSBcIi4uLy4uL2FjY2Vzc2liaWxpdHkvUm92aW5nVGFiSW5kZXhcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uLCB7IEJ1dHRvbkV2ZW50IH0gZnJvbSBcIi4uL3ZpZXdzL2VsZW1lbnRzL0FjY2Vzc2libGVCdXR0b25cIjtcbmltcG9ydCBTZGtDb25maWcgZnJvbSBcIi4uLy4uL1Nka0NvbmZpZ1wiO1xuaW1wb3J0IHsgZ2V0SG9tZVBhZ2VVcmwgfSBmcm9tIFwiLi4vLi4vdXRpbHMvcGFnZXNcIjtcbmltcG9ydCB7IE93blByb2ZpbGVTdG9yZSB9IGZyb20gXCIuLi8uLi9zdG9yZXMvT3duUHJvZmlsZVN0b3JlXCI7XG5pbXBvcnQgeyBVUERBVEVfRVZFTlQgfSBmcm9tIFwiLi4vLi4vc3RvcmVzL0FzeW5jU3RvcmVcIjtcbmltcG9ydCBCYXNlQXZhdGFyIGZyb20gXCIuLi92aWV3cy9hdmF0YXJzL0Jhc2VBdmF0YXJcIjtcbmltcG9ydCB7IFNldHRpbmdMZXZlbCB9IGZyb20gXCIuLi8uLi9zZXR0aW5ncy9TZXR0aW5nTGV2ZWxcIjtcbmltcG9ydCBJY29uaXplZENvbnRleHRNZW51LCB7XG4gICAgSWNvbml6ZWRDb250ZXh0TWVudU9wdGlvbixcbiAgICBJY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdCxcbn0gZnJvbSBcIi4uL3ZpZXdzL2NvbnRleHRfbWVudXMvSWNvbml6ZWRDb250ZXh0TWVudVwiO1xuaW1wb3J0IHsgVUlGZWF0dXJlIH0gZnJvbSBcIi4uLy4uL3NldHRpbmdzL1VJRmVhdHVyZVwiO1xuaW1wb3J0IFNwYWNlU3RvcmUgZnJvbSBcIi4uLy4uL3N0b3Jlcy9zcGFjZXMvU3BhY2VTdG9yZVwiO1xuaW1wb3J0IHsgVVBEQVRFX1NFTEVDVEVEX1NQQUNFIH0gZnJvbSBcIi4uLy4uL3N0b3Jlcy9zcGFjZXNcIjtcbmltcG9ydCBVc2VySWRlbnRpZmllckN1c3RvbWlzYXRpb25zIGZyb20gXCIuLi8uLi9jdXN0b21pc2F0aW9ucy9Vc2VySWRlbnRpZmllclwiO1xuaW1wb3J0IFBvc3Rob2dUcmFja2VycyBmcm9tIFwiLi4vLi4vUG9zdGhvZ1RyYWNrZXJzXCI7XG5pbXBvcnQgeyBWaWV3SG9tZVBhZ2VQYXlsb2FkIH0gZnJvbSBcIi4uLy4uL2Rpc3BhdGNoZXIvcGF5bG9hZHMvVmlld0hvbWVQYWdlUGF5bG9hZFwiO1xuaW1wb3J0IHsgSWNvbiBhcyBMaXZlSWNvbiB9IGZyb20gXCIuLi8uLi8uLi9yZXMvaW1nL2NvbXBvdW5kL2xpdmUtOHB4LnN2Z1wiO1xuaW1wb3J0IHsgVm9pY2VCcm9hZGNhc3RSZWNvcmRpbmcsIFZvaWNlQnJvYWRjYXN0UmVjb3JkaW5nc1N0b3JlRXZlbnQgfSBmcm9tIFwiLi4vLi4vdm9pY2UtYnJvYWRjYXN0XCI7XG5pbXBvcnQgeyBTREtDb250ZXh0IH0gZnJvbSBcIi4uLy4uL2NvbnRleHRzL1NES0NvbnRleHRcIjtcbmltcG9ydCB7IHNob3VsZFNob3dGZWVkYmFjayB9IGZyb20gXCIuLi8uLi91dGlscy9GZWVkYmFja1wiO1xuXG5pbnRlcmZhY2UgSVByb3BzIHtcbiAgICBpc1BhbmVsQ29sbGFwc2VkOiBib29sZWFuO1xuICAgIGNoaWxkcmVuPzogUmVhY3ROb2RlO1xufVxuXG50eXBlIFBhcnRpYWxET01SZWN0ID0gUGljazxET01SZWN0LCBcIndpZHRoXCIgfCBcImxlZnRcIiB8IFwidG9wXCIgfCBcImhlaWdodFwiPjtcblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgY29udGV4dE1lbnVQb3NpdGlvbjogUGFydGlhbERPTVJlY3QgfCBudWxsO1xuICAgIGlzRGFya1RoZW1lOiBib29sZWFuO1xuICAgIGlzSGlnaENvbnRyYXN0OiBib29sZWFuO1xuICAgIHNlbGVjdGVkU3BhY2U/OiBSb29tIHwgbnVsbDtcbiAgICBzaG93TGl2ZUF2YXRhckFkZG9uOiBib29sZWFuO1xufVxuXG5jb25zdCB0b1JpZ2h0T2YgPSAocmVjdDogUGFydGlhbERPTVJlY3QpOiBNZW51UHJvcHMgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IHJlY3Qud2lkdGggKyByZWN0LmxlZnQgKyA4LFxuICAgICAgICB0b3A6IHJlY3QudG9wLFxuICAgICAgICBjaGV2cm9uRmFjZTogQ2hldnJvbkZhY2UuTm9uZSxcbiAgICB9O1xufTtcblxuY29uc3QgYmVsb3cgPSAocmVjdDogUGFydGlhbERPTVJlY3QpOiBNZW51UHJvcHMgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxlZnQ6IHJlY3QubGVmdCxcbiAgICAgICAgdG9wOiByZWN0LnRvcCArIHJlY3QuaGVpZ2h0LFxuICAgICAgICBjaGV2cm9uRmFjZTogQ2hldnJvbkZhY2UuTm9uZSxcbiAgICB9O1xufTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVXNlck1lbnUgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICBwdWJsaWMgc3RhdGljIGNvbnRleHRUeXBlID0gU0RLQ29udGV4dDtcbiAgICBwdWJsaWMgZGVjbGFyZSBjb250ZXh0OiBSZWFjdC5Db250ZXh0VHlwZTx0eXBlb2YgU0RLQ29udGV4dD47XG5cbiAgICBwcml2YXRlIGRpc3BhdGNoZXJSZWY/OiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB0aGVtZVdhdGNoZXJSZWY/OiBzdHJpbmc7XG4gICAgcHJpdmF0ZSByZWFkb25seSBkbmRXYXRjaGVyUmVmPzogc3RyaW5nO1xuICAgIHByaXZhdGUgYnV0dG9uUmVmOiBSZWFjdC5SZWZPYmplY3Q8SFRNTEJ1dHRvbkVsZW1lbnQ+ID0gY3JlYXRlUmVmKCk7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IElQcm9wcywgY29udGV4dDogUmVhY3QuQ29udGV4dFR5cGU8dHlwZW9mIFNES0NvbnRleHQ+KSB7XG4gICAgICAgIHN1cGVyKHByb3BzLCBjb250ZXh0KTtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgY29udGV4dE1lbnVQb3NpdGlvbjogbnVsbCxcbiAgICAgICAgICAgIGlzRGFya1RoZW1lOiB0aGlzLmlzVXNlck9uRGFya1RoZW1lKCksXG4gICAgICAgICAgICBpc0hpZ2hDb250cmFzdDogdGhpcy5pc1VzZXJPbkhpZ2hDb250cmFzdFRoZW1lKCksXG4gICAgICAgICAgICBzZWxlY3RlZFNwYWNlOiBTcGFjZVN0b3JlLmluc3RhbmNlLmFjdGl2ZVNwYWNlUm9vbSxcbiAgICAgICAgICAgIHNob3dMaXZlQXZhdGFyQWRkb246IHRoaXMuY29udGV4dC52b2ljZUJyb2FkY2FzdFJlY29yZGluZ3NTdG9yZS5oYXNDdXJyZW50KCksXG4gICAgICAgIH07XG5cbiAgICAgICAgT3duUHJvZmlsZVN0b3JlLmluc3RhbmNlLm9uKFVQREFURV9FVkVOVCwgdGhpcy5vblByb2ZpbGVVcGRhdGUpO1xuICAgICAgICBTcGFjZVN0b3JlLmluc3RhbmNlLm9uKFVQREFURV9TRUxFQ1RFRF9TUEFDRSwgdGhpcy5vblNlbGVjdGVkU3BhY2VVcGRhdGUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IGhhc0hvbWVQYWdlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gISFnZXRIb21lUGFnZVVybChTZGtDb25maWcuZ2V0KCksIHRoaXMuY29udGV4dC5jbGllbnQhKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uQ3VycmVudFZvaWNlQnJvYWRjYXN0UmVjb3JkaW5nQ2hhbmdlZCA9IChyZWNvcmRpbmc6IFZvaWNlQnJvYWRjYXN0UmVjb3JkaW5nIHwgbnVsbCk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNob3dMaXZlQXZhdGFyQWRkb246IHJlY29yZGluZyAhPT0gbnVsbCxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHB1YmxpYyBjb21wb25lbnREaWRNb3VudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jb250ZXh0LnZvaWNlQnJvYWRjYXN0UmVjb3JkaW5nc1N0b3JlLm9uKFxuICAgICAgICAgICAgVm9pY2VCcm9hZGNhc3RSZWNvcmRpbmdzU3RvcmVFdmVudC5DdXJyZW50Q2hhbmdlZCxcbiAgICAgICAgICAgIHRoaXMub25DdXJyZW50Vm9pY2VCcm9hZGNhc3RSZWNvcmRpbmdDaGFuZ2VkLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmRpc3BhdGNoZXJSZWYgPSBkZWZhdWx0RGlzcGF0Y2hlci5yZWdpc3Rlcih0aGlzLm9uQWN0aW9uKTtcbiAgICAgICAgdGhpcy50aGVtZVdhdGNoZXJSZWYgPSBTZXR0aW5nc1N0b3JlLndhdGNoU2V0dGluZyhcInRoZW1lXCIsIG51bGwsIHRoaXMub25UaGVtZUNoYW5nZWQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wb25lbnRXaWxsVW5tb3VudCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMudGhlbWVXYXRjaGVyUmVmKSBTZXR0aW5nc1N0b3JlLnVud2F0Y2hTZXR0aW5nKHRoaXMudGhlbWVXYXRjaGVyUmVmKTtcbiAgICAgICAgaWYgKHRoaXMuZG5kV2F0Y2hlclJlZikgU2V0dGluZ3NTdG9yZS51bndhdGNoU2V0dGluZyh0aGlzLmRuZFdhdGNoZXJSZWYpO1xuICAgICAgICBpZiAodGhpcy5kaXNwYXRjaGVyUmVmKSBkZWZhdWx0RGlzcGF0Y2hlci51bnJlZ2lzdGVyKHRoaXMuZGlzcGF0Y2hlclJlZik7XG4gICAgICAgIE93blByb2ZpbGVTdG9yZS5pbnN0YW5jZS5vZmYoVVBEQVRFX0VWRU5ULCB0aGlzLm9uUHJvZmlsZVVwZGF0ZSk7XG4gICAgICAgIFNwYWNlU3RvcmUuaW5zdGFuY2Uub2ZmKFVQREFURV9TRUxFQ1RFRF9TUEFDRSwgdGhpcy5vblNlbGVjdGVkU3BhY2VVcGRhdGUpO1xuICAgICAgICB0aGlzLmNvbnRleHQudm9pY2VCcm9hZGNhc3RSZWNvcmRpbmdzU3RvcmUub2ZmKFxuICAgICAgICAgICAgVm9pY2VCcm9hZGNhc3RSZWNvcmRpbmdzU3RvcmVFdmVudC5DdXJyZW50Q2hhbmdlZCxcbiAgICAgICAgICAgIHRoaXMub25DdXJyZW50Vm9pY2VCcm9hZGNhc3RSZWNvcmRpbmdDaGFuZ2VkLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgaXNVc2VyT25EYXJrVGhlbWUoKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwidXNlX3N5c3RlbV90aGVtZVwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5tYXRjaE1lZGlhKFwiKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKVwiKS5tYXRjaGVzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgdGhlbWUgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwidGhlbWVcIik7XG4gICAgICAgICAgICBpZiAodGhlbWUuc3RhcnRzV2l0aChcImN1c3RvbS1cIikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gISFnZXRDdXN0b21UaGVtZSh0aGVtZS5zdWJzdHJpbmcoXCJjdXN0b20tXCIubGVuZ3RoKSkuaXNfZGFyaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGVtZSA9PT0gXCJkYXJrXCI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGlzVXNlck9uSGlnaENvbnRyYXN0VGhlbWUoKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwidXNlX3N5c3RlbV90aGVtZVwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5tYXRjaE1lZGlhKFwiKHByZWZlcnMtY29udHJhc3Q6IG1vcmUpXCIpLm1hdGNoZXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCB0aGVtZSA9IFNldHRpbmdzU3RvcmUuZ2V0VmFsdWUoXCJ0aGVtZVwiKTtcbiAgICAgICAgICAgIGlmICh0aGVtZS5zdGFydHNXaXRoKFwiY3VzdG9tLVwiKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpc0hpZ2hDb250cmFzdFRoZW1lKHRoZW1lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25Qcm9maWxlVXBkYXRlID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAvLyB0aGUgc3RvcmUgdHJpZ2dlcmVkIGFuIHVwZGF0ZSwgc28gZm9yY2UgYSBsYXlvdXQgdXBkYXRlLiBXZSBkb24ndFxuICAgICAgICAvLyBoYXZlIGFueSBzdGF0ZSB0byBzdG9yZSBoZXJlIGZvciB0aGF0IHRvIG1hZ2ljYWxseSBoYXBwZW4uXG4gICAgICAgIHRoaXMuZm9yY2VVcGRhdGUoKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblNlbGVjdGVkU3BhY2VVcGRhdGUgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgc2VsZWN0ZWRTcGFjZTogU3BhY2VTdG9yZS5pbnN0YW5jZS5hY3RpdmVTcGFjZVJvb20sXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uVGhlbWVDaGFuZ2VkID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIGlzRGFya1RoZW1lOiB0aGlzLmlzVXNlck9uRGFya1RoZW1lKCksXG4gICAgICAgICAgICBpc0hpZ2hDb250cmFzdDogdGhpcy5pc1VzZXJPbkhpZ2hDb250cmFzdFRoZW1lKCksXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uQWN0aW9uID0gKHBheWxvYWQ6IEFjdGlvblBheWxvYWQpOiB2b2lkID0+IHtcbiAgICAgICAgc3dpdGNoIChwYXlsb2FkLmFjdGlvbikge1xuICAgICAgICAgICAgY2FzZSBBY3Rpb24uVG9nZ2xlVXNlck1lbnU6XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuY29udGV4dE1lbnVQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgY29udGV4dE1lbnVQb3NpdGlvbjogbnVsbCB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5idXR0b25SZWYuY3VycmVudCkgdGhpcy5idXR0b25SZWYuY3VycmVudC5jbGljaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwcml2YXRlIG9uT3Blbk1lbnVDbGljayA9IChldjogQnV0dG9uRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBjb250ZXh0TWVudVBvc2l0aW9uOiBldi5jdXJyZW50VGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uQ29udGV4dE1lbnUgPSAoZXY6IFJlYWN0Lk1vdXNlRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgY29udGV4dE1lbnVQb3NpdGlvbjoge1xuICAgICAgICAgICAgICAgIGxlZnQ6IGV2LmNsaWVudFgsXG4gICAgICAgICAgICAgICAgdG9wOiBldi5jbGllbnRZLFxuICAgICAgICAgICAgICAgIHdpZHRoOiAyMCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkNsb3NlTWVudSA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGNvbnRleHRNZW51UG9zaXRpb246IG51bGwgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25Td2l0Y2hUaGVtZUNsaWNrID0gKGV2OiBCdXR0b25FdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgICAgICBQb3N0aG9nVHJhY2tlcnMudHJhY2tJbnRlcmFjdGlvbihcIldlYlVzZXJNZW51VGhlbWVUb2dnbGVCdXR0b25cIiwgZXYpO1xuXG4gICAgICAgIC8vIERpc2FibGUgc3lzdGVtIHRoZW1lIG1hdGNoaW5nIGlmIHRoZSB1c2VyIGhpdHMgdGhpcyBidXR0b25cbiAgICAgICAgU2V0dGluZ3NTdG9yZS5zZXRWYWx1ZShcInVzZV9zeXN0ZW1fdGhlbWVcIiwgbnVsbCwgU2V0dGluZ0xldmVsLkRFVklDRSwgZmFsc2UpO1xuXG4gICAgICAgIGxldCBuZXdUaGVtZSA9IHRoaXMuc3RhdGUuaXNEYXJrVGhlbWUgPyBcImxpZ2h0XCIgOiBcImRhcmtcIjtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuaXNIaWdoQ29udHJhc3QpIHtcbiAgICAgICAgICAgIGNvbnN0IGhjVGhlbWUgPSBmaW5kSGlnaENvbnRyYXN0VGhlbWUobmV3VGhlbWUpO1xuICAgICAgICAgICAgaWYgKGhjVGhlbWUpIHtcbiAgICAgICAgICAgICAgICBuZXdUaGVtZSA9IGhjVGhlbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgU2V0dGluZ3NTdG9yZS5zZXRWYWx1ZShcInRoZW1lXCIsIG51bGwsIFNldHRpbmdMZXZlbC5ERVZJQ0UsIG5ld1RoZW1lKTsgLy8gc2V0IGF0IHNhbWUgbGV2ZWwgYXMgQXBwZWFyYW5jZSB0YWJcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblNldHRpbmdzT3BlbiA9IChldjogQnV0dG9uRXZlbnQsIHRhYklkPzogc3RyaW5nLCBwcm9wcz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkID0+IHtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgICAgY29uc3QgcGF5bG9hZDogT3BlblRvVGFiUGF5bG9hZCA9IHsgYWN0aW9uOiBBY3Rpb24uVmlld1VzZXJTZXR0aW5ncywgaW5pdGlhbFRhYklkOiB0YWJJZCwgcHJvcHMgfTtcbiAgICAgICAgZGVmYXVsdERpc3BhdGNoZXIuZGlzcGF0Y2gocGF5bG9hZCk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBjb250ZXh0TWVudVBvc2l0aW9uOiBudWxsIH0pOyAvLyBhbHNvIGNsb3NlIHRoZSBtZW51XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25Qcm92aWRlRmVlZGJhY2sgPSAoZXY6IEJ1dHRvbkV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhGZWVkYmFja0RpYWxvZyk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBjb250ZXh0TWVudVBvc2l0aW9uOiBudWxsIH0pOyAvLyBhbHNvIGNsb3NlIHRoZSBtZW51XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25TaWduT3V0Q2xpY2sgPSBhc3luYyAoZXY6IEJ1dHRvbkV2ZW50KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgIGlmIChhd2FpdCBzaG91bGRTaG93TG9nb3V0RGlhbG9nKE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkpKSB7XG4gICAgICAgICAgICBNb2RhbC5jcmVhdGVEaWFsb2coTG9nb3V0RGlhbG9nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlZmF1bHREaXNwYXRjaGVyLmRpc3BhdGNoKHsgYWN0aW9uOiBcImxvZ291dFwiIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGNvbnRleHRNZW51UG9zaXRpb246IG51bGwgfSk7IC8vIGFsc28gY2xvc2UgdGhlIG1lbnVcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblNpZ25JbkNsaWNrID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBkZWZhdWx0RGlzcGF0Y2hlci5kaXNwYXRjaCh7IGFjdGlvbjogXCJzdGFydF9sb2dpblwiIH0pO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgY29udGV4dE1lbnVQb3NpdGlvbjogbnVsbCB9KTsgLy8gYWxzbyBjbG9zZSB0aGUgbWVudVxuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUmVnaXN0ZXJDbGljayA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgZGVmYXVsdERpc3BhdGNoZXIuZGlzcGF0Y2goeyBhY3Rpb246IFwic3RhcnRfcmVnaXN0cmF0aW9uXCIgfSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBjb250ZXh0TWVudVBvc2l0aW9uOiBudWxsIH0pOyAvLyBhbHNvIGNsb3NlIHRoZSBtZW51XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25Ib21lQ2xpY2sgPSAoZXY6IEJ1dHRvbkV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgIGRlZmF1bHREaXNwYXRjaGVyLmRpc3BhdGNoPFZpZXdIb21lUGFnZVBheWxvYWQ+KHsgYWN0aW9uOiBBY3Rpb24uVmlld0hvbWVQYWdlIH0pO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgY29udGV4dE1lbnVQb3NpdGlvbjogbnVsbCB9KTsgLy8gYWxzbyBjbG9zZSB0aGUgbWVudVxuICAgIH07XG5cbiAgICBwcml2YXRlIHJlbmRlckNvbnRleHRNZW51ID0gKCk6IFJlYWN0LlJlYWN0Tm9kZSA9PiB7XG4gICAgICAgIGlmICghdGhpcy5zdGF0ZS5jb250ZXh0TWVudVBvc2l0aW9uKSByZXR1cm4gbnVsbDtcblxuICAgICAgICBsZXQgdG9wU2VjdGlvbjogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmlzR3Vlc3QoKSkge1xuICAgICAgICAgICAgdG9wU2VjdGlvbiA9IChcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X1VzZXJNZW51X2NvbnRleHRNZW51X2hlYWRlciBteF9Vc2VyTWVudV9jb250ZXh0TWVudV9ndWVzdFByb21wdHNcIj5cbiAgICAgICAgICAgICAgICAgICAge190KFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJhdXRofHNpZ25faW5fcHJvbXB0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhOiAoc3ViKSA9PiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uIGtpbmQ9XCJsaW5rX2lubGluZVwiIG9uQ2xpY2s9e3RoaXMub25TaWduSW5DbGlja30+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgICAgICAgIHtTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFVJRmVhdHVyZS5SZWdpc3RyYXRpb24pXG4gICAgICAgICAgICAgICAgICAgICAgICA/IF90KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJhdXRofGNyZWF0ZV9hY2NvdW50X3Byb21wdFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYTogKHN1YikgPT4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvbiBraW5kPVwibGlua19pbmxpbmVcIiBvbkNsaWNrPXt0aGlzLm9uUmVnaXN0ZXJDbGlja30+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIDogbnVsbH1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgaG9tZUJ1dHRvbjogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0aGlzLmhhc0hvbWVQYWdlKSB7XG4gICAgICAgICAgICBob21lQnV0dG9uID0gKFxuICAgICAgICAgICAgICAgIDxJY29uaXplZENvbnRleHRNZW51T3B0aW9uXG4gICAgICAgICAgICAgICAgICAgIGljb25DbGFzc05hbWU9XCJteF9Vc2VyTWVudV9pY29uSG9tZVwiXG4gICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcImNvbW1vbnxob21lXCIpfVxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uSG9tZUNsaWNrfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGZlZWRiYWNrQnV0dG9uOiBKU1guRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHNob3VsZFNob3dGZWVkYmFjaygpKSB7XG4gICAgICAgICAgICBmZWVkYmFja0J1dHRvbiA9IChcbiAgICAgICAgICAgICAgICA8SWNvbml6ZWRDb250ZXh0TWVudU9wdGlvblxuICAgICAgICAgICAgICAgICAgICBpY29uQ2xhc3NOYW1lPVwibXhfVXNlck1lbnVfaWNvbk1lc3NhZ2VcIlxuICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJjb21tb258ZmVlZGJhY2tcIil9XG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25Qcm92aWRlRmVlZGJhY2t9XG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBsaW5rTmV3RGV2aWNlQnV0dG9uID0gKFxuICAgICAgICAgICAgPEljb25pemVkQ29udGV4dE1lbnVPcHRpb25cbiAgICAgICAgICAgICAgICBpY29uQ2xhc3NOYW1lPVwibXhfVXNlck1lbnVfaWNvblFyXCJcbiAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJ1c2VyX21lbnV8bGlua19uZXdfZGV2aWNlXCIpfVxuICAgICAgICAgICAgICAgIG9uQ2xpY2s9eyhlKSA9PiB0aGlzLm9uU2V0dGluZ3NPcGVuKGUsIFVzZXJUYWIuU2Vzc2lvbk1hbmFnZXIsIHsgc2hvd01zYzQxMDhRckNvZGU6IHRydWUgfSl9XG4gICAgICAgICAgICAvPlxuICAgICAgICApO1xuXG4gICAgICAgIGxldCBwcmltYXJ5T3B0aW9uTGlzdCA9IChcbiAgICAgICAgICAgIDxJY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdD5cbiAgICAgICAgICAgICAgICB7aG9tZUJ1dHRvbn1cbiAgICAgICAgICAgICAgICB7bGlua05ld0RldmljZUJ1dHRvbn1cbiAgICAgICAgICAgICAgICA8SWNvbml6ZWRDb250ZXh0TWVudU9wdGlvblxuICAgICAgICAgICAgICAgICAgICBpY29uQ2xhc3NOYW1lPVwibXhfVXNlck1lbnVfaWNvbkJlbGxcIlxuICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJub3RpZmljYXRpb25zfGVuYWJsZV9wcm9tcHRfdG9hc3RfdGl0bGVcIil9XG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eyhlKSA9PiB0aGlzLm9uU2V0dGluZ3NPcGVuKGUsIFVzZXJUYWIuTm90aWZpY2F0aW9ucyl9XG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICA8SWNvbml6ZWRDb250ZXh0TWVudU9wdGlvblxuICAgICAgICAgICAgICAgICAgICBpY29uQ2xhc3NOYW1lPVwibXhfVXNlck1lbnVfaWNvbkxvY2tcIlxuICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fHRpdGxlXCIpfVxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXsoZSkgPT4gdGhpcy5vblNldHRpbmdzT3BlbihlLCBVc2VyVGFiLlNlY3VyaXR5KX1cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDxJY29uaXplZENvbnRleHRNZW51T3B0aW9uXG4gICAgICAgICAgICAgICAgICAgIGljb25DbGFzc05hbWU9XCJteF9Vc2VyTWVudV9pY29uU2V0dGluZ3NcIlxuICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJ1c2VyX21lbnV8c2V0dGluZ3NcIil9XG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eyhlKSA9PiB0aGlzLm9uU2V0dGluZ3NPcGVuKGUpfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAge2ZlZWRiYWNrQnV0dG9ufVxuICAgICAgICAgICAgICAgIDxJY29uaXplZENvbnRleHRNZW51T3B0aW9uXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0ljb25pemVkQ29udGV4dE1lbnVfb3B0aW9uX3JlZFwiXG4gICAgICAgICAgICAgICAgICAgIGljb25DbGFzc05hbWU9XCJteF9Vc2VyTWVudV9pY29uU2lnbk91dFwiXG4gICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcImFjdGlvbnxzaWduX291dFwiKX1cbiAgICAgICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy5vblNpZ25PdXRDbGlja31cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgPC9JY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdD5cbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5pc0d1ZXN0KCkpIHtcbiAgICAgICAgICAgIHByaW1hcnlPcHRpb25MaXN0ID0gKFxuICAgICAgICAgICAgICAgIDxJY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdD5cbiAgICAgICAgICAgICAgICAgICAge2hvbWVCdXR0b259XG4gICAgICAgICAgICAgICAgICAgIDxJY29uaXplZENvbnRleHRNZW51T3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQ2xhc3NOYW1lPVwibXhfVXNlck1lbnVfaWNvblNldHRpbmdzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcImNvbW1vbnxzZXR0aW5nc1wiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eyhlKSA9PiB0aGlzLm9uU2V0dGluZ3NPcGVuKGUpfVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICB7ZmVlZGJhY2tCdXR0b259XG4gICAgICAgICAgICAgICAgPC9JY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdD5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMucHJvcHMuaXNQYW5lbENvbGxhcHNlZFxuICAgICAgICAgICAgPyB0b1JpZ2h0T2YodGhpcy5zdGF0ZS5jb250ZXh0TWVudVBvc2l0aW9uKVxuICAgICAgICAgICAgOiBiZWxvdyh0aGlzLnN0YXRlLmNvbnRleHRNZW51UG9zaXRpb24pO1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8SWNvbml6ZWRDb250ZXh0TWVudSB7Li4ucG9zaXRpb259IG9uRmluaXNoZWQ9e3RoaXMub25DbG9zZU1lbnV9IGNsYXNzTmFtZT1cIm14X1VzZXJNZW51X2NvbnRleHRNZW51XCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9Vc2VyTWVudV9jb250ZXh0TWVudV9oZWFkZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9Vc2VyTWVudV9jb250ZXh0TWVudV9uYW1lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJteF9Vc2VyTWVudV9jb250ZXh0TWVudV9kaXNwbGF5TmFtZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtPd25Qcm9maWxlU3RvcmUuaW5zdGFuY2UuZGlzcGxheU5hbWV9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJteF9Vc2VyTWVudV9jb250ZXh0TWVudV91c2VySWRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7VXNlcklkZW50aWZpZXJDdXN0b21pc2F0aW9ucy5nZXREaXNwbGF5VXNlcklkZW50aWZpZXIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkuZ2V0U2FmZVVzZXJJZCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aXRoRGlzcGxheU5hbWU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgPFJvdmluZ0FjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X1VzZXJNZW51X2NvbnRleHRNZW51X3RoZW1lQnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25Td2l0Y2hUaGVtZUNsaWNrfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU9e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuaXNEYXJrVGhlbWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBfdChcInVzZXJfbWVudXxzd2l0Y2hfdGhlbWVfbGlnaHRcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBfdChcInVzZXJfbWVudXxzd2l0Y2hfdGhlbWVfZGFya1wiKVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aW1nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3JjPXtyZXF1aXJlKFwiLi4vLi4vLi4vcmVzL2ltZy9lbGVtZW50LWljb25zL3Jvb21saXN0L2RhcmstbGlnaHQtbW9kZS5zdmdcIikuZGVmYXVsdH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb2xlPVwicHJlc2VudGF0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHQ9XCJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoPXsxNn1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgIDwvUm92aW5nQWNjZXNzaWJsZUJ1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICB7dG9wU2VjdGlvbn1cbiAgICAgICAgICAgICAgICB7cHJpbWFyeU9wdGlvbkxpc3R9XG4gICAgICAgICAgICA8L0ljb25pemVkQ29udGV4dE1lbnU+XG4gICAgICAgICk7XG4gICAgfTtcblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgY29uc3QgYXZhdGFyU2l6ZSA9IDMyOyAvLyBzaG91bGQgbWF0Y2ggYm9yZGVyLXJhZGl1cyBvZiB0aGUgYXZhdGFyXG5cbiAgICAgICAgY29uc3QgdXNlcklkID0gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRTYWZlVXNlcklkKCk7XG4gICAgICAgIGNvbnN0IGRpc3BsYXlOYW1lID0gT3duUHJvZmlsZVN0b3JlLmluc3RhbmNlLmRpc3BsYXlOYW1lIHx8IHVzZXJJZDtcbiAgICAgICAgY29uc3QgYXZhdGFyVXJsID0gT3duUHJvZmlsZVN0b3JlLmluc3RhbmNlLmdldEh0dHBBdmF0YXJVcmwoYXZhdGFyU2l6ZSk7XG5cbiAgICAgICAgbGV0IG5hbWU6IEpTWC5FbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgICAgICBpZiAoIXRoaXMucHJvcHMuaXNQYW5lbENvbGxhcHNlZCkge1xuICAgICAgICAgICAgbmFtZSA9IDxkaXYgY2xhc3NOYW1lPVwibXhfVXNlck1lbnVfbmFtZVwiPntkaXNwbGF5TmFtZX08L2Rpdj47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBsaXZlQXZhdGFyQWRkb24gPSB0aGlzLnN0YXRlLnNob3dMaXZlQXZhdGFyQWRkb24gPyAoXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X1VzZXJNZW51X3VzZXJBdmF0YXJMaXZlXCIgZGF0YS10ZXN0aWQ9XCJ1c2VyLW1lbnUtbGl2ZS12YlwiPlxuICAgICAgICAgICAgICAgIDxMaXZlSWNvbiBjbGFzc05hbWU9XCJteF9JY29uXzhcIiAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICkgOiBudWxsO1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X1VzZXJNZW51XCI+XG4gICAgICAgICAgICAgICAgPENvbnRleHRNZW51QnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X1VzZXJNZW51X2NvbnRleHRNZW51QnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy5vbk9wZW5NZW51Q2xpY2t9XG4gICAgICAgICAgICAgICAgICAgIHJlZj17dGhpcy5idXR0b25SZWZ9XG4gICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcImExMXl8dXNlcl9tZW51XCIpfVxuICAgICAgICAgICAgICAgICAgICBpc0V4cGFuZGVkPXshIXRoaXMuc3RhdGUuY29udGV4dE1lbnVQb3NpdGlvbn1cbiAgICAgICAgICAgICAgICAgICAgb25Db250ZXh0TWVudT17dGhpcy5vbkNvbnRleHRNZW51fVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9Vc2VyTWVudV91c2VyQXZhdGFyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8QmFzZUF2YXRhclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkTmFtZT17dXNlcklkfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9e2Rpc3BsYXlOYW1lfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybD17YXZhdGFyVXJsfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9e2F2YXRhclNpemUgKyBcInB4XCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfVXNlck1lbnVfdXNlckF2YXRhcl9CYXNlQXZhdGFyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICB7bGl2ZUF2YXRhckFkZG9ufVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAge25hbWV9XG4gICAgICAgICAgICAgICAgICAgIHt0aGlzLnJlbmRlckNvbnRleHRNZW51KCl9XG4gICAgICAgICAgICAgICAgPC9Db250ZXh0TWVudUJ1dHRvbj5cblxuICAgICAgICAgICAgICAgIHt0aGlzLnByb3BzLmNoaWxkcmVufVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICk7XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFRQSxJQUFBQSxNQUFBLEdBQUFDLHVCQUFBLENBQUFDLE9BQUE7QUFHQSxJQUFBQyxnQkFBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsV0FBQSxHQUFBQyxzQkFBQSxDQUFBSCxPQUFBO0FBRUEsSUFBQUksUUFBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssZ0JBQUEsR0FBQUwsT0FBQTtBQUNBLElBQUFNLFlBQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLFFBQUEsR0FBQVAsT0FBQTtBQUVBLElBQUFRLGVBQUEsR0FBQUwsc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFTLE1BQUEsR0FBQU4sc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFVLGFBQUEsR0FBQVgsdUJBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFXLGNBQUEsR0FBQVIsc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFZLE1BQUEsR0FBQVosT0FBQTtBQUNBLElBQUFhLGVBQUEsR0FBQWIsT0FBQTtBQUNBLElBQUFjLGlCQUFBLEdBQUFYLHNCQUFBLENBQUFILE9BQUE7QUFDQSxJQUFBZSxVQUFBLEdBQUFaLHNCQUFBLENBQUFILE9BQUE7QUFDQSxJQUFBZ0IsTUFBQSxHQUFBaEIsT0FBQTtBQUNBLElBQUFpQixnQkFBQSxHQUFBakIsT0FBQTtBQUNBLElBQUFrQixXQUFBLEdBQUFsQixPQUFBO0FBQ0EsSUFBQW1CLFdBQUEsR0FBQWhCLHNCQUFBLENBQUFILE9BQUE7QUFDQSxJQUFBb0IsYUFBQSxHQUFBcEIsT0FBQTtBQUNBLElBQUFxQixvQkFBQSxHQUFBdEIsdUJBQUEsQ0FBQUMsT0FBQTtBQUlBLElBQUFzQixVQUFBLEdBQUF0QixPQUFBO0FBQ0EsSUFBQXVCLFdBQUEsR0FBQXBCLHNCQUFBLENBQUFILE9BQUE7QUFDQSxJQUFBd0IsT0FBQSxHQUFBeEIsT0FBQTtBQUNBLElBQUF5QixlQUFBLEdBQUF0QixzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQTBCLGdCQUFBLEdBQUF2QixzQkFBQSxDQUFBSCxPQUFBO0FBRUEsSUFBQTJCLFFBQUEsR0FBQTNCLE9BQUE7QUFDQSxJQUFBNEIsZUFBQSxHQ