UNPKG

matrix-react-sdk

Version:
370 lines (353 loc) 54 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.ModalManagerEvent = exports.ModalManager = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _reactDom = _interopRequireDefault(require("react-dom")); var _classnames = _interopRequireDefault(require("classnames")); var _utils = require("matrix-js-sdk/src/utils"); var _matrix = require("matrix-js-sdk/src/matrix"); var _compoundWeb = require("@vector-im/compound-web"); var _dispatcher = _interopRequireWildcard(require("./dispatcher/dispatcher")); var _AsyncWrapper = _interopRequireDefault(require("./AsyncWrapper")); 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 The Matrix.org Foundation C.I.C. Copyright 2015, 2016 OpenMarket Ltd SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ const DIALOG_CONTAINER_ID = "mx_Dialog_Container"; const STATIC_DIALOG_CONTAINER_ID = "mx_Dialog_StaticContainer"; // Type which accepts a React Component which looks like a Modal (accepts an onFinished prop) // Generic type which returns the props of the Modal component with the onFinished being optional. let ModalManagerEvent = exports.ModalManagerEvent = /*#__PURE__*/function (ModalManagerEvent) { ModalManagerEvent["Opened"] = "opened"; ModalManagerEvent["Closed"] = "closed"; return ModalManagerEvent; }({}); class ModalManager extends _matrix.TypedEventEmitter { static getOrCreateContainer() { let container = document.getElementById(DIALOG_CONTAINER_ID); if (!container) { container = document.createElement("div"); container.id = DIALOG_CONTAINER_ID; document.body.appendChild(container); } return container; } static getOrCreateStaticContainer() { let container = document.getElementById(STATIC_DIALOG_CONTAINER_ID); if (!container) { container = document.createElement("div"); container.id = STATIC_DIALOG_CONTAINER_ID; document.body.appendChild(container); } return container; } constructor() { super(); // We never unregister this, but the Modal class is a singleton so there would // never be an opportunity to do so anyway, except in the entirely theoretical // scenario of instantiating a non-singleton instance of the Modal class. (0, _defineProperty2.default)(this, "counter", 0); // The modal to prioritise over all others. If this is set, only show // this modal. Remove all other modals from the stack when this modal // is closed. (0, _defineProperty2.default)(this, "priorityModal", null); // The modal to keep open underneath other modals if possible. Useful // for cases like Settings where the modal should remain open while the // user is prompted for more information/errors. (0, _defineProperty2.default)(this, "staticModal", null); // A list of the modals we have stacked up, with the most recent at [0] // Neither the static nor priority modal will be in this list. (0, _defineProperty2.default)(this, "modals", []); (0, _defineProperty2.default)(this, "onAction", payload => { if (payload.action === "logout") { this.forceCloseAllModals(); } }); (0, _defineProperty2.default)(this, "onBackgroundClick", () => { const modal = this.getCurrentModal(); if (!modal) { return; } // we want to pass a reason to the onBeforeClose // callback, but close is currently defined to // pass all number of arguments to the onFinished callback // so, pass the reason to close through a member variable modal.closeReason = "backgroundClick"; modal.close(); modal.closeReason = undefined; }); _dispatcher.defaultDispatcher.register(this.onAction); } toggleCurrentDialogVisibility() { const modal = this.getCurrentModal(); if (!modal) return; modal.hidden = !modal.hidden; } hasDialogs() { return !!this.priorityModal || !!this.staticModal || this.modals.length > 0; } createDialog(Element, props, className, isPriorityModal = false, isStaticModal = false, options = {}) { return this.createDialogAsync(Promise.resolve(Element), props, className, isPriorityModal, isStaticModal, options); } appendDialog(Element, props, className) { return this.appendDialogAsync(Promise.resolve(Element), props, className); } /** * DEPRECATED. * This is used only for tests. They should be using forceCloseAllModals but that * caused a chunk of tests to fail, so for now they continue to use this. * * @param reason either "backgroundClick" or undefined * @return whether a modal was closed */ closeCurrentModal(reason) { const modal = this.getCurrentModal(); if (!modal) { return false; } modal.closeReason = reason; modal.close(); return true; } /** * Forces closes all open modals. The modals onBeforeClose function will not be * run and the modal will not have a chance to prevent closing. Intended for * situations like the user logging out of the app. */ forceCloseAllModals() { for (const modal of this.modals) { modal.deferred?.resolve([]); if (modal.onFinished) modal.onFinished.apply(null); this.emitClosed(); } this.modals = []; this.reRender(); } buildModal(prom, props, className, options) { const modal = { onFinished: props?.onFinished, onBeforeClose: options?.onBeforeClose, className, // these will be set below but we need an object reference to pass to getCloseFn before we can do that elem: null }; // never call this from onFinished() otherwise it will loop const [closeDialog, onFinishedProm] = this.getCloseFn(modal, props); // don't attempt to reuse the same AsyncWrapper for different dialogs, // otherwise we'll get confused. const modalCount = this.counter++; // FIXME: If a dialog uses getDefaultProps it clobbers the onFinished // property set here so you can't close the dialog from a button click! modal.elem = /*#__PURE__*/_react.default.createElement(_AsyncWrapper.default, (0, _extends2.default)({ key: modalCount, prom: prom }, props, { onFinished: closeDialog })); modal.close = closeDialog; return { modal, closeDialog, onFinishedProm }; } getCloseFn(modal, props) { modal.deferred = (0, _utils.defer)(); return [async (...args) => { if (modal.beforeClosePromise) { await modal.beforeClosePromise; } else if (modal.onBeforeClose) { modal.beforeClosePromise = modal.onBeforeClose(modal.closeReason); const shouldClose = await modal.beforeClosePromise; modal.beforeClosePromise = undefined; if (!shouldClose) { return; } } modal.deferred?.resolve(args); if (props?.onFinished) props.onFinished.apply(null, args); const i = this.modals.indexOf(modal); if (i >= 0) { this.modals.splice(i, 1); } if (this.priorityModal === modal) { this.priorityModal = null; // XXX: This is destructive this.modals = []; } if (this.staticModal === modal) { this.staticModal = null; // XXX: This is destructive this.modals = []; } this.reRender(); this.emitClosed(); }, modal.deferred.promise]; } /** * @callback onBeforeClose * @param {string?} reason either "backgroundClick" or null * @return {Promise<bool>} whether the dialog should close */ /** * Open a modal view. * * This can be used to display a react component which is loaded as an asynchronous * webpack component. To do this, set 'loader' as: * * (cb) => { * require(['<module>'], cb); * } * * @param {Promise} prom a promise which resolves with a React component * which will be displayed as the modal view. * * @param {Object} props properties to pass to the displayed * component. (We will also pass an 'onFinished' property.) * * @param {String} className CSS class to apply to the modal wrapper * * @param {boolean} isPriorityModal if true, this modal will be displayed regardless * of other modals that are currently in the stack. * Also, when closed, all modals will be removed * from the stack. * @param {boolean} isStaticModal if true, this modal will be displayed under other * modals in the stack. When closed, all modals will * also be removed from the stack. This is not compatible * with being a priority modal. Only one modal can be * static at a time. * @param {Object} options? extra options for the dialog * @param {onBeforeClose} options.onBeforeClose a callback to decide whether to close the dialog * @returns {object} Object with 'close' parameter being a function that will close the dialog */ createDialogAsync(prom, props, className, isPriorityModal = false, isStaticModal = false, options = {}) { const beforeModal = this.getCurrentModal(); const { modal, closeDialog, onFinishedProm } = this.buildModal(prom, props, className, options); if (isPriorityModal) { // XXX: This is destructive this.priorityModal = modal; } else if (isStaticModal) { // This is intentionally destructive this.staticModal = modal; } else { this.modals.unshift(modal); } this.reRender(); this.emitIfChanged(beforeModal); return { close: closeDialog, finished: onFinishedProm }; } appendDialogAsync(prom, props, className) { const beforeModal = this.getCurrentModal(); const { modal, closeDialog, onFinishedProm } = this.buildModal(prom, props, className, {}); this.modals.push(modal); this.reRender(); this.emitIfChanged(beforeModal); return { close: closeDialog, finished: onFinishedProm }; } emitIfChanged(beforeModal) { if (beforeModal !== this.getCurrentModal()) { this.emit(ModalManagerEvent.Opened); } } /** * Emit the closed event * @private */ emitClosed() { this.emit(ModalManagerEvent.Closed); } getCurrentModal() { return this.priorityModal ? this.priorityModal : this.modals[0] || this.staticModal; } async reRender() { // TODO: We should figure out how to remove this weird sleep. It also makes testing harder // // await next tick because sometimes ReactDOM can race with itself and cause the modal to wrongly stick around await (0, _utils.sleep)(0); if (this.modals.length === 0 && !this.priorityModal && !this.staticModal) { // If there is no modal to render, make all of Element available // to screen reader users again _dispatcher.default.dispatch({ action: "aria_unhide_main_app" }); _reactDom.default.unmountComponentAtNode(ModalManager.getOrCreateContainer()); _reactDom.default.unmountComponentAtNode(ModalManager.getOrCreateStaticContainer()); return; } // Hide the content outside the modal to screen reader users // so they won't be able to navigate into it and act on it using // screen reader specific features _dispatcher.default.dispatch({ action: "aria_hide_main_app" }); if (this.staticModal) { const classes = (0, _classnames.default)("mx_Dialog_wrapper mx_Dialog_staticWrapper", this.staticModal.className); const staticDialog = /*#__PURE__*/_react.default.createElement(_compoundWeb.TooltipProvider, null, /*#__PURE__*/_react.default.createElement("div", { className: classes }, /*#__PURE__*/_react.default.createElement(_compoundWeb.Glass, { className: "mx_Dialog_border" }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_Dialog" }, this.staticModal.elem)), /*#__PURE__*/_react.default.createElement("div", { "data-testid": "dialog-background", className: "mx_Dialog_background mx_Dialog_staticBackground", onClick: this.onBackgroundClick }))); _reactDom.default.render(staticDialog, ModalManager.getOrCreateStaticContainer()); } else { // This is safe to call repeatedly if we happen to do that _reactDom.default.unmountComponentAtNode(ModalManager.getOrCreateStaticContainer()); } const modal = this.getCurrentModal(); if (modal !== this.staticModal && !modal.hidden) { const classes = (0, _classnames.default)("mx_Dialog_wrapper", modal.className, { mx_Dialog_wrapperWithStaticUnder: this.staticModal }); const dialog = /*#__PURE__*/_react.default.createElement(_compoundWeb.TooltipProvider, null, /*#__PURE__*/_react.default.createElement("div", { className: classes }, /*#__PURE__*/_react.default.createElement(_compoundWeb.Glass, { className: "mx_Dialog_border" }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_Dialog" }, modal.elem)), /*#__PURE__*/_react.default.createElement("div", { "data-testid": "dialog-background", className: "mx_Dialog_background", onClick: this.onBackgroundClick }))); setTimeout(() => _reactDom.default.render(dialog, ModalManager.getOrCreateContainer()), 0); } else { // This is safe to call repeatedly if we happen to do that _reactDom.default.unmountComponentAtNode(ModalManager.getOrCreateContainer()); } } } exports.ModalManager = ModalManager; if (!window.singletonModalManager) { window.singletonModalManager = new ModalManager(); } var _default = exports.default = window.singletonModalManager; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9yZWFjdERvbSIsIl9jbGFzc25hbWVzIiwiX3V0aWxzIiwiX21hdHJpeCIsIl9jb21wb3VuZFdlYiIsIl9kaXNwYXRjaGVyIiwiX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQiLCJfQXN5bmNXcmFwcGVyIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0IiwiRElBTE9HX0NPTlRBSU5FUl9JRCIsIlNUQVRJQ19ESUFMT0dfQ09OVEFJTkVSX0lEIiwiTW9kYWxNYW5hZ2VyRXZlbnQiLCJleHBvcnRzIiwiTW9kYWxNYW5hZ2VyIiwiVHlwZWRFdmVudEVtaXR0ZXIiLCJnZXRPckNyZWF0ZUNvbnRhaW5lciIsImNvbnRhaW5lciIsImRvY3VtZW50IiwiZ2V0RWxlbWVudEJ5SWQiLCJjcmVhdGVFbGVtZW50IiwiaWQiLCJib2R5IiwiYXBwZW5kQ2hpbGQiLCJnZXRPckNyZWF0ZVN0YXRpY0NvbnRhaW5lciIsImNvbnN0cnVjdG9yIiwiX2RlZmluZVByb3BlcnR5MiIsInBheWxvYWQiLCJhY3Rpb24iLCJmb3JjZUNsb3NlQWxsTW9kYWxzIiwibW9kYWwiLCJnZXRDdXJyZW50TW9kYWwiLCJjbG9zZVJlYXNvbiIsImNsb3NlIiwidW5kZWZpbmVkIiwiZGVmYXVsdERpc3BhdGNoZXIiLCJyZWdpc3RlciIsIm9uQWN0aW9uIiwidG9nZ2xlQ3VycmVudERpYWxvZ1Zpc2liaWxpdHkiLCJoaWRkZW4iLCJoYXNEaWFsb2dzIiwicHJpb3JpdHlNb2RhbCIsInN0YXRpY01vZGFsIiwibW9kYWxzIiwibGVuZ3RoIiwiY3JlYXRlRGlhbG9nIiwiRWxlbWVudCIsInByb3BzIiwiY2xhc3NOYW1lIiwiaXNQcmlvcml0eU1vZGFsIiwiaXNTdGF0aWNNb2RhbCIsIm9wdGlvbnMiLCJjcmVhdGVEaWFsb2dBc3luYyIsIlByb21pc2UiLCJyZXNvbHZlIiwiYXBwZW5kRGlhbG9nIiwiYXBwZW5kRGlhbG9nQXN5bmMiLCJjbG9zZUN1cnJlbnRNb2RhbCIsInJlYXNvbiIsImRlZmVycmVkIiwib25GaW5pc2hlZCIsImFwcGx5IiwiZW1pdENsb3NlZCIsInJlUmVuZGVyIiwiYnVpbGRNb2RhbCIsInByb20iLCJvbkJlZm9yZUNsb3NlIiwiZWxlbSIsImNsb3NlRGlhbG9nIiwib25GaW5pc2hlZFByb20iLCJnZXRDbG9zZUZuIiwibW9kYWxDb3VudCIsImNvdW50ZXIiLCJfZXh0ZW5kczIiLCJrZXkiLCJkZWZlciIsImFyZ3MiLCJiZWZvcmVDbG9zZVByb21pc2UiLCJzaG91bGRDbG9zZSIsImluZGV4T2YiLCJzcGxpY2UiLCJwcm9taXNlIiwiYmVmb3JlTW9kYWwiLCJ1bnNoaWZ0IiwiZW1pdElmQ2hhbmdlZCIsImZpbmlzaGVkIiwicHVzaCIsImVtaXQiLCJPcGVuZWQiLCJDbG9zZWQiLCJzbGVlcCIsImRpcyIsImRpc3BhdGNoIiwiUmVhY3RET00iLCJ1bm1vdW50Q29tcG9uZW50QXROb2RlIiwiY2xhc3NlcyIsImNsYXNzTmFtZXMiLCJzdGF0aWNEaWFsb2ciLCJUb29sdGlwUHJvdmlkZXIiLCJHbGFzcyIsIm9uQ2xpY2siLCJvbkJhY2tncm91bmRDbGljayIsInJlbmRlciIsIm14X0RpYWxvZ193cmFwcGVyV2l0aFN0YXRpY1VuZGVyIiwiZGlhbG9nIiwic2V0VGltZW91dCIsIndpbmRvdyIsInNpbmdsZXRvbk1vZGFsTWFuYWdlciIsIl9kZWZhdWx0Il0sInNvdXJjZXMiOlsiLi4vc3JjL01vZGFsLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAyMCBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuQ29weXJpZ2h0IDIwMTUsIDIwMTYgT3Blbk1hcmtldCBMdGRcblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IFJlYWN0RE9NIGZyb20gXCJyZWFjdC1kb21cIjtcbmltcG9ydCBjbGFzc05hbWVzIGZyb20gXCJjbGFzc25hbWVzXCI7XG5pbXBvcnQgeyBJRGVmZXJyZWQsIGRlZmVyLCBzbGVlcCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy91dGlsc1wiO1xuaW1wb3J0IHsgVHlwZWRFdmVudEVtaXR0ZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBHbGFzcywgVG9vbHRpcFByb3ZpZGVyIH0gZnJvbSBcIkB2ZWN0b3ItaW0vY29tcG91bmQtd2ViXCI7XG5cbmltcG9ydCBkaXMsIHsgZGVmYXVsdERpc3BhdGNoZXIgfSBmcm9tIFwiLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXJcIjtcbmltcG9ydCBBc3luY1dyYXBwZXIgZnJvbSBcIi4vQXN5bmNXcmFwcGVyXCI7XG5pbXBvcnQgeyBEZWZhdWx0aXplIH0gZnJvbSBcIi4vQHR5cGVzL2NvbW1vblwiO1xuaW1wb3J0IHsgQWN0aW9uUGF5bG9hZCB9IGZyb20gXCIuL2Rpc3BhdGNoZXIvcGF5bG9hZHNcIjtcblxuY29uc3QgRElBTE9HX0NPTlRBSU5FUl9JRCA9IFwibXhfRGlhbG9nX0NvbnRhaW5lclwiO1xuY29uc3QgU1RBVElDX0RJQUxPR19DT05UQUlORVJfSUQgPSBcIm14X0RpYWxvZ19TdGF0aWNDb250YWluZXJcIjtcblxuLy8gVHlwZSB3aGljaCBhY2NlcHRzIGEgUmVhY3QgQ29tcG9uZW50IHdoaWNoIGxvb2tzIGxpa2UgYSBNb2RhbCAoYWNjZXB0cyBhbiBvbkZpbmlzaGVkIHByb3ApXG5leHBvcnQgdHlwZSBDb21wb25lbnRUeXBlID1cbiAgICB8IFJlYWN0LkNvbXBvbmVudFR5cGU8e1xuICAgICAgICAgIG9uRmluaXNoZWQoLi4uYXJnczogYW55KTogdm9pZDtcbiAgICAgIH0+XG4gICAgfCBSZWFjdC5Db21wb25lbnRUeXBlPGFueT47XG5cbi8vIEdlbmVyaWMgdHlwZSB3aGljaCByZXR1cm5zIHRoZSBwcm9wcyBvZiB0aGUgTW9kYWwgY29tcG9uZW50IHdpdGggdGhlIG9uRmluaXNoZWQgYmVpbmcgb3B0aW9uYWwuXG5leHBvcnQgdHlwZSBDb21wb25lbnRQcm9wczxDIGV4dGVuZHMgQ29tcG9uZW50VHlwZT4gPSBEZWZhdWx0aXplPFxuICAgIE9taXQ8UmVhY3QuQ29tcG9uZW50UHJvcHM8Qz4sIFwib25GaW5pc2hlZFwiPixcbiAgICBDW1wiZGVmYXVsdFByb3BzXCJdXG4+ICZcbiAgICBQYXJ0aWFsPFBpY2s8UmVhY3QuQ29tcG9uZW50UHJvcHM8Qz4sIFwib25GaW5pc2hlZFwiPj47XG5cbmV4cG9ydCBpbnRlcmZhY2UgSU1vZGFsPEMgZXh0ZW5kcyBDb21wb25lbnRUeXBlPiB7XG4gICAgZWxlbTogUmVhY3QuUmVhY3ROb2RlO1xuICAgIGNsYXNzTmFtZT86IHN0cmluZztcbiAgICBiZWZvcmVDbG9zZVByb21pc2U/OiBQcm9taXNlPGJvb2xlYW4+O1xuICAgIGNsb3NlUmVhc29uPzogTW9kYWxDbG9zZVJlYXNvbjtcbiAgICBvbkJlZm9yZUNsb3NlPyhyZWFzb24/OiBNb2RhbENsb3NlUmVhc29uKTogUHJvbWlzZTxib29sZWFuPjtcbiAgICBvbkZpbmlzaGVkOiBDb21wb25lbnRQcm9wczxDPltcIm9uRmluaXNoZWRcIl07XG4gICAgY2xvc2UoLi4uYXJnczogUGFyYW1ldGVyczxDb21wb25lbnRQcm9wczxDPltcIm9uRmluaXNoZWRcIl0+KTogdm9pZDtcbiAgICBoaWRkZW4/OiBib29sZWFuO1xuICAgIGRlZmVycmVkPzogSURlZmVycmVkPFBhcmFtZXRlcnM8Q29tcG9uZW50UHJvcHM8Qz5bXCJvbkZpbmlzaGVkXCJdPj47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUhhbmRsZTxDIGV4dGVuZHMgQ29tcG9uZW50VHlwZT4ge1xuICAgIGZpbmlzaGVkOiBQcm9taXNlPFBhcmFtZXRlcnM8Q29tcG9uZW50UHJvcHM8Qz5bXCJvbkZpbmlzaGVkXCJdPj47XG4gICAgY2xvc2UoLi4uYXJnczogUGFyYW1ldGVyczxDb21wb25lbnRQcm9wczxDPltcIm9uRmluaXNoZWRcIl0+KTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIElPcHRpb25zPEMgZXh0ZW5kcyBDb21wb25lbnRUeXBlPiB7XG4gICAgb25CZWZvcmVDbG9zZT86IElNb2RhbDxDPltcIm9uQmVmb3JlQ2xvc2VcIl07XG59XG5cbmV4cG9ydCBlbnVtIE1vZGFsTWFuYWdlckV2ZW50IHtcbiAgICBPcGVuZWQgPSBcIm9wZW5lZFwiLFxuICAgIENsb3NlZCA9IFwiY2xvc2VkXCIsXG59XG5cbnR5cGUgSGFuZGxlck1hcCA9IHtcbiAgICBbTW9kYWxNYW5hZ2VyRXZlbnQuT3BlbmVkXTogKCkgPT4gdm9pZDtcbiAgICBbTW9kYWxNYW5hZ2VyRXZlbnQuQ2xvc2VkXTogKCkgPT4gdm9pZDtcbn07XG5cbnR5cGUgTW9kYWxDbG9zZVJlYXNvbiA9IFwiYmFja2dyb3VuZENsaWNrXCI7XG5cbmV4cG9ydCBjbGFzcyBNb2RhbE1hbmFnZXIgZXh0ZW5kcyBUeXBlZEV2ZW50RW1pdHRlcjxNb2RhbE1hbmFnZXJFdmVudCwgSGFuZGxlck1hcD4ge1xuICAgIHByaXZhdGUgY291bnRlciA9IDA7XG4gICAgLy8gVGhlIG1vZGFsIHRvIHByaW9yaXRpc2Ugb3ZlciBhbGwgb3RoZXJzLiBJZiB0aGlzIGlzIHNldCwgb25seSBzaG93XG4gICAgLy8gdGhpcyBtb2RhbC4gUmVtb3ZlIGFsbCBvdGhlciBtb2RhbHMgZnJvbSB0aGUgc3RhY2sgd2hlbiB0aGlzIG1vZGFsXG4gICAgLy8gaXMgY2xvc2VkLlxuICAgIHByaXZhdGUgcHJpb3JpdHlNb2RhbDogSU1vZGFsPGFueT4gfCBudWxsID0gbnVsbDtcbiAgICAvLyBUaGUgbW9kYWwgdG8ga2VlcCBvcGVuIHVuZGVybmVhdGggb3RoZXIgbW9kYWxzIGlmIHBvc3NpYmxlLiBVc2VmdWxcbiAgICAvLyBmb3IgY2FzZXMgbGlrZSBTZXR0aW5ncyB3aGVyZSB0aGUgbW9kYWwgc2hvdWxkIHJlbWFpbiBvcGVuIHdoaWxlIHRoZVxuICAgIC8vIHVzZXIgaXMgcHJvbXB0ZWQgZm9yIG1vcmUgaW5mb3JtYXRpb24vZXJyb3JzLlxuICAgIHByaXZhdGUgc3RhdGljTW9kYWw6IElNb2RhbDxhbnk+IHwgbnVsbCA9IG51bGw7XG4gICAgLy8gQSBsaXN0IG9mIHRoZSBtb2RhbHMgd2UgaGF2ZSBzdGFja2VkIHVwLCB3aXRoIHRoZSBtb3N0IHJlY2VudCBhdCBbMF1cbiAgICAvLyBOZWl0aGVyIHRoZSBzdGF0aWMgbm9yIHByaW9yaXR5IG1vZGFsIHdpbGwgYmUgaW4gdGhpcyBsaXN0LlxuICAgIHByaXZhdGUgbW9kYWxzOiBJTW9kYWw8YW55PltdID0gW107XG5cbiAgICBwcml2YXRlIHN0YXRpYyBnZXRPckNyZWF0ZUNvbnRhaW5lcigpOiBIVE1MRWxlbWVudCB7XG4gICAgICAgIGxldCBjb250YWluZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChESUFMT0dfQ09OVEFJTkVSX0lEKTtcblxuICAgICAgICBpZiAoIWNvbnRhaW5lcikge1xuICAgICAgICAgICAgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgICAgIGNvbnRhaW5lci5pZCA9IERJQUxPR19DT05UQUlORVJfSUQ7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGNvbnRhaW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29udGFpbmVyO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGdldE9yQ3JlYXRlU3RhdGljQ29udGFpbmVyKCk6IEhUTUxFbGVtZW50IHtcbiAgICAgICAgbGV0IGNvbnRhaW5lciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFNUQVRJQ19ESUFMT0dfQ09OVEFJTkVSX0lEKTtcblxuICAgICAgICBpZiAoIWNvbnRhaW5lcikge1xuICAgICAgICAgICAgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgICAgIGNvbnRhaW5lci5pZCA9IFNUQVRJQ19ESUFMT0dfQ09OVEFJTkVSX0lEO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChjb250YWluZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbnRhaW5lcjtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgLy8gV2UgbmV2ZXIgdW5yZWdpc3RlciB0aGlzLCBidXQgdGhlIE1vZGFsIGNsYXNzIGlzIGEgc2luZ2xldG9uIHNvIHRoZXJlIHdvdWxkXG4gICAgICAgIC8vIG5ldmVyIGJlIGFuIG9wcG9ydHVuaXR5IHRvIGRvIHNvIGFueXdheSwgZXhjZXB0IGluIHRoZSBlbnRpcmVseSB0aGVvcmV0aWNhbFxuICAgICAgICAvLyBzY2VuYXJpbyBvZiBpbnN0YW50aWF0aW5nIGEgbm9uLXNpbmdsZXRvbiBpbnN0YW5jZSBvZiB0aGUgTW9kYWwgY2xhc3MuXG4gICAgICAgIGRlZmF1bHREaXNwYXRjaGVyLnJlZ2lzdGVyKHRoaXMub25BY3Rpb24pO1xuICAgIH1cblxuICAgIHByaXZhdGUgb25BY3Rpb24gPSAocGF5bG9hZDogQWN0aW9uUGF5bG9hZCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAocGF5bG9hZC5hY3Rpb24gPT09IFwibG9nb3V0XCIpIHtcbiAgICAgICAgICAgIHRoaXMuZm9yY2VDbG9zZUFsbE1vZGFscygpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHB1YmxpYyB0b2dnbGVDdXJyZW50RGlhbG9nVmlzaWJpbGl0eSgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgbW9kYWwgPSB0aGlzLmdldEN1cnJlbnRNb2RhbCgpO1xuICAgICAgICBpZiAoIW1vZGFsKSByZXR1cm47XG4gICAgICAgIG1vZGFsLmhpZGRlbiA9ICFtb2RhbC5oaWRkZW47XG4gICAgfVxuXG4gICAgcHVibGljIGhhc0RpYWxvZ3MoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAhIXRoaXMucHJpb3JpdHlNb2RhbCB8fCAhIXRoaXMuc3RhdGljTW9kYWwgfHwgdGhpcy5tb2RhbHMubGVuZ3RoID4gMDtcbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlYXRlRGlhbG9nPEMgZXh0ZW5kcyBDb21wb25lbnRUeXBlPihcbiAgICAgICAgRWxlbWVudDogQyxcbiAgICAgICAgcHJvcHM/OiBDb21wb25lbnRQcm9wczxDPixcbiAgICAgICAgY2xhc3NOYW1lPzogc3RyaW5nLFxuICAgICAgICBpc1ByaW9yaXR5TW9kYWwgPSBmYWxzZSxcbiAgICAgICAgaXNTdGF0aWNNb2RhbCA9IGZhbHNlLFxuICAgICAgICBvcHRpb25zOiBJT3B0aW9uczxDPiA9IHt9LFxuICAgICk6IElIYW5kbGU8Qz4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVEaWFsb2dBc3luYzxDPihcbiAgICAgICAgICAgIFByb21pc2UucmVzb2x2ZShFbGVtZW50KSxcbiAgICAgICAgICAgIHByb3BzLFxuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgaXNQcmlvcml0eU1vZGFsLFxuICAgICAgICAgICAgaXNTdGF0aWNNb2RhbCxcbiAgICAgICAgICAgIG9wdGlvbnMsXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGFwcGVuZERpYWxvZzxDIGV4dGVuZHMgQ29tcG9uZW50VHlwZT4oXG4gICAgICAgIEVsZW1lbnQ6IEMsXG4gICAgICAgIHByb3BzPzogQ29tcG9uZW50UHJvcHM8Qz4sXG4gICAgICAgIGNsYXNzTmFtZT86IHN0cmluZyxcbiAgICApOiBJSGFuZGxlPEM+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXBwZW5kRGlhbG9nQXN5bmM8Qz4oUHJvbWlzZS5yZXNvbHZlKEVsZW1lbnQpLCBwcm9wcywgY2xhc3NOYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBERVBSRUNBVEVELlxuICAgICAqIFRoaXMgaXMgdXNlZCBvbmx5IGZvciB0ZXN0cy4gVGhleSBzaG91bGQgYmUgdXNpbmcgZm9yY2VDbG9zZUFsbE1vZGFscyBidXQgdGhhdFxuICAgICAqIGNhdXNlZCBhIGNodW5rIG9mIHRlc3RzIHRvIGZhaWwsIHNvIGZvciBub3cgdGhleSBjb250aW51ZSB0byB1c2UgdGhpcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByZWFzb24gZWl0aGVyIFwiYmFja2dyb3VuZENsaWNrXCIgb3IgdW5kZWZpbmVkXG4gICAgICogQHJldHVybiB3aGV0aGVyIGEgbW9kYWwgd2FzIGNsb3NlZFxuICAgICAqL1xuICAgIHB1YmxpYyBjbG9zZUN1cnJlbnRNb2RhbChyZWFzb24/OiBNb2RhbENsb3NlUmVhc29uKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IG1vZGFsID0gdGhpcy5nZXRDdXJyZW50TW9kYWwoKTtcbiAgICAgICAgaWYgKCFtb2RhbCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIG1vZGFsLmNsb3NlUmVhc29uID0gcmVhc29uO1xuICAgICAgICBtb2RhbC5jbG9zZSgpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgY2xvc2VzIGFsbCBvcGVuIG1vZGFscy4gVGhlIG1vZGFscyBvbkJlZm9yZUNsb3NlIGZ1bmN0aW9uIHdpbGwgbm90IGJlXG4gICAgICogcnVuIGFuZCB0aGUgbW9kYWwgd2lsbCBub3QgaGF2ZSBhIGNoYW5jZSB0byBwcmV2ZW50IGNsb3NpbmcuIEludGVuZGVkIGZvclxuICAgICAqIHNpdHVhdGlvbnMgbGlrZSB0aGUgdXNlciBsb2dnaW5nIG91dCBvZiB0aGUgYXBwLlxuICAgICAqL1xuICAgIHB1YmxpYyBmb3JjZUNsb3NlQWxsTW9kYWxzKCk6IHZvaWQge1xuICAgICAgICBmb3IgKGNvbnN0IG1vZGFsIG9mIHRoaXMubW9kYWxzKSB7XG4gICAgICAgICAgICBtb2RhbC5kZWZlcnJlZD8ucmVzb2x2ZShbXSk7XG4gICAgICAgICAgICBpZiAobW9kYWwub25GaW5pc2hlZCkgbW9kYWwub25GaW5pc2hlZC5hcHBseShudWxsKTtcbiAgICAgICAgICAgIHRoaXMuZW1pdENsb3NlZCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tb2RhbHMgPSBbXTtcbiAgICAgICAgdGhpcy5yZVJlbmRlcigpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGRNb2RhbDxDIGV4dGVuZHMgQ29tcG9uZW50VHlwZT4oXG4gICAgICAgIHByb206IFByb21pc2U8Qz4sXG4gICAgICAgIHByb3BzPzogQ29tcG9uZW50UHJvcHM8Qz4sXG4gICAgICAgIGNsYXNzTmFtZT86IHN0cmluZyxcbiAgICAgICAgb3B0aW9ucz86IElPcHRpb25zPEM+LFxuICAgICk6IHtcbiAgICAgICAgbW9kYWw6IElNb2RhbDxDPjtcbiAgICAgICAgY2xvc2VEaWFsb2c6IElIYW5kbGU8Qz5bXCJjbG9zZVwiXTtcbiAgICAgICAgb25GaW5pc2hlZFByb206IElIYW5kbGU8Qz5bXCJmaW5pc2hlZFwiXTtcbiAgICB9IHtcbiAgICAgICAgY29uc3QgbW9kYWwgPSB7XG4gICAgICAgICAgICBvbkZpbmlzaGVkOiBwcm9wcz8ub25GaW5pc2hlZCxcbiAgICAgICAgICAgIG9uQmVmb3JlQ2xvc2U6IG9wdGlvbnM/Lm9uQmVmb3JlQ2xvc2UsXG4gICAgICAgICAgICBjbGFzc05hbWUsXG5cbiAgICAgICAgICAgIC8vIHRoZXNlIHdpbGwgYmUgc2V0IGJlbG93IGJ1dCB3ZSBuZWVkIGFuIG9iamVjdCByZWZlcmVuY2UgdG8gcGFzcyB0byBnZXRDbG9zZUZuIGJlZm9yZSB3ZSBjYW4gZG8gdGhhdFxuICAgICAgICAgICAgZWxlbTogbnVsbCxcbiAgICAgICAgfSBhcyBJTW9kYWw8Qz47XG5cbiAgICAgICAgLy8gbmV2ZXIgY2FsbCB0aGlzIGZyb20gb25GaW5pc2hlZCgpIG90aGVyd2lzZSBpdCB3aWxsIGxvb3BcbiAgICAgICAgY29uc3QgW2Nsb3NlRGlhbG9nLCBvbkZpbmlzaGVkUHJvbV0gPSB0aGlzLmdldENsb3NlRm48Qz4obW9kYWwsIHByb3BzKTtcblxuICAgICAgICAvLyBkb24ndCBhdHRlbXB0IHRvIHJldXNlIHRoZSBzYW1lIEFzeW5jV3JhcHBlciBmb3IgZGlmZmVyZW50IGRpYWxvZ3MsXG4gICAgICAgIC8vIG90aGVyd2lzZSB3ZSdsbCBnZXQgY29uZnVzZWQuXG4gICAgICAgIGNvbnN0IG1vZGFsQ291bnQgPSB0aGlzLmNvdW50ZXIrKztcblxuICAgICAgICAvLyBGSVhNRTogSWYgYSBkaWFsb2cgdXNlcyBnZXREZWZhdWx0UHJvcHMgaXQgY2xvYmJlcnMgdGhlIG9uRmluaXNoZWRcbiAgICAgICAgLy8gcHJvcGVydHkgc2V0IGhlcmUgc28geW91IGNhbid0IGNsb3NlIHRoZSBkaWFsb2cgZnJvbSBhIGJ1dHRvbiBjbGljayFcbiAgICAgICAgbW9kYWwuZWxlbSA9IDxBc3luY1dyYXBwZXIga2V5PXttb2RhbENvdW50fSBwcm9tPXtwcm9tfSB7Li4ucHJvcHN9IG9uRmluaXNoZWQ9e2Nsb3NlRGlhbG9nfSAvPjtcbiAgICAgICAgbW9kYWwuY2xvc2UgPSBjbG9zZURpYWxvZztcblxuICAgICAgICByZXR1cm4geyBtb2RhbCwgY2xvc2VEaWFsb2csIG9uRmluaXNoZWRQcm9tIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDbG9zZUZuPEMgZXh0ZW5kcyBDb21wb25lbnRUeXBlPihcbiAgICAgICAgbW9kYWw6IElNb2RhbDxDPixcbiAgICAgICAgcHJvcHM/OiBDb21wb25lbnRQcm9wczxDPixcbiAgICApOiBbSUhhbmRsZTxDPltcImNsb3NlXCJdLCBJSGFuZGxlPEM+W1wiZmluaXNoZWRcIl1dIHtcbiAgICAgICAgbW9kYWwuZGVmZXJyZWQgPSBkZWZlcjxQYXJhbWV0ZXJzPENvbXBvbmVudFByb3BzPEM+W1wib25GaW5pc2hlZFwiXT4+KCk7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBhc3luYyAoLi4uYXJnczogUGFyYW1ldGVyczxDb21wb25lbnRQcm9wczxDPltcIm9uRmluaXNoZWRcIl0+KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKG1vZGFsLmJlZm9yZUNsb3NlUHJvbWlzZSkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBtb2RhbC5iZWZvcmVDbG9zZVByb21pc2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtb2RhbC5vbkJlZm9yZUNsb3NlKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZGFsLmJlZm9yZUNsb3NlUHJvbWlzZSA9IG1vZGFsLm9uQmVmb3JlQ2xvc2UobW9kYWwuY2xvc2VSZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzaG91bGRDbG9zZSA9IGF3YWl0IG1vZGFsLmJlZm9yZUNsb3NlUHJvbWlzZTtcbiAgICAgICAgICAgICAgICAgICAgbW9kYWwuYmVmb3JlQ2xvc2VQcm9taXNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXNob3VsZENsb3NlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbW9kYWwuZGVmZXJyZWQ/LnJlc29sdmUoYXJncyk7XG4gICAgICAgICAgICAgICAgaWYgKHByb3BzPy5vbkZpbmlzaGVkKSBwcm9wcy5vbkZpbmlzaGVkLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGkgPSB0aGlzLm1vZGFscy5pbmRleE9mKG1vZGFsKTtcbiAgICAgICAgICAgICAgICBpZiAoaSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubW9kYWxzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wcmlvcml0eU1vZGFsID09PSBtb2RhbCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnByaW9yaXR5TW9kYWwgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFhYWDogVGhpcyBpcyBkZXN0cnVjdGl2ZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLm1vZGFscyA9IFtdO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRpY01vZGFsID09PSBtb2RhbCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRpY01vZGFsID0gbnVsbDtcblxuICAgICAgICAgICAgICAgICAgICAvLyBYWFg6IFRoaXMgaXMgZGVzdHJ1Y3RpdmVcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb2RhbHMgPSBbXTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnJlUmVuZGVyKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0Q2xvc2VkKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbW9kYWwuZGVmZXJyZWQucHJvbWlzZSxcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAY2FsbGJhY2sgb25CZWZvcmVDbG9zZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nP30gcmVhc29uIGVpdGhlciBcImJhY2tncm91bmRDbGlja1wiIG9yIG51bGxcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPGJvb2w+fSB3aGV0aGVyIHRoZSBkaWFsb2cgc2hvdWxkIGNsb3NlXG4gICAgICovXG5cbiAgICAvKipcbiAgICAgKiBPcGVuIGEgbW9kYWwgdmlldy5cbiAgICAgKlxuICAgICAqIFRoaXMgY2FuIGJlIHVzZWQgdG8gZGlzcGxheSBhIHJlYWN0IGNvbXBvbmVudCB3aGljaCBpcyBsb2FkZWQgYXMgYW4gYXN5bmNocm9ub3VzXG4gICAgICogd2VicGFjayBjb21wb25lbnQuIFRvIGRvIHRoaXMsIHNldCAnbG9hZGVyJyBhczpcbiAgICAgKlxuICAgICAqICAgKGNiKSA9PiB7XG4gICAgICogICAgICAgcmVxdWlyZShbJzxtb2R1bGU+J10sIGNiKTtcbiAgICAgKiAgIH1cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7UHJvbWlzZX0gcHJvbSAgIGEgcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aXRoIGEgUmVhY3QgY29tcG9uZW50XG4gICAgICogICB3aGljaCB3aWxsIGJlIGRpc3BsYXllZCBhcyB0aGUgbW9kYWwgdmlldy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAgIHByb3BlcnRpZXMgdG8gcGFzcyB0byB0aGUgZGlzcGxheWVkXG4gICAgICogICAgY29tcG9uZW50LiAoV2Ugd2lsbCBhbHNvIHBhc3MgYW4gJ29uRmluaXNoZWQnIHByb3BlcnR5LilcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBjbGFzc05hbWUgICBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gdGhlIG1vZGFsIHdyYXBwZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNQcmlvcml0eU1vZGFsIGlmIHRydWUsIHRoaXMgbW9kYWwgd2lsbCBiZSBkaXNwbGF5ZWQgcmVnYXJkbGVzc1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mIG90aGVyIG1vZGFscyB0aGF0IGFyZSBjdXJyZW50bHkgaW4gdGhlIHN0YWNrLlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFsc28sIHdoZW4gY2xvc2VkLCBhbGwgbW9kYWxzIHdpbGwgYmUgcmVtb3ZlZFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb20gdGhlIHN0YWNrLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNTdGF0aWNNb2RhbCAgaWYgdHJ1ZSwgdGhpcyBtb2RhbCB3aWxsIGJlIGRpc3BsYXllZCB1bmRlciBvdGhlclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kYWxzIGluIHRoZSBzdGFjay4gV2hlbiBjbG9zZWQsIGFsbCBtb2RhbHMgd2lsbFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxzbyBiZSByZW1vdmVkIGZyb20gdGhlIHN0YWNrLiBUaGlzIGlzIG5vdCBjb21wYXRpYmxlXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aXRoIGJlaW5nIGEgcHJpb3JpdHkgbW9kYWwuIE9ubHkgb25lIG1vZGFsIGNhbiBiZVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGljIGF0IGEgdGltZS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucz8gZXh0cmEgb3B0aW9ucyBmb3IgdGhlIGRpYWxvZ1xuICAgICAqIEBwYXJhbSB7b25CZWZvcmVDbG9zZX0gb3B0aW9ucy5vbkJlZm9yZUNsb3NlIGEgY2FsbGJhY2sgdG8gZGVjaWRlIHdoZXRoZXIgdG8gY2xvc2UgdGhlIGRpYWxvZ1xuICAgICAqIEByZXR1cm5zIHtvYmplY3R9IE9iamVjdCB3aXRoICdjbG9zZScgcGFyYW1ldGVyIGJlaW5nIGEgZnVuY3Rpb24gdGhhdCB3aWxsIGNsb3NlIHRoZSBkaWFsb2dcbiAgICAgKi9cbiAgICBwdWJsaWMgY3JlYXRlRGlhbG9nQXN5bmM8QyBleHRlbmRzIENvbXBvbmVudFR5cGU+KFxuICAgICAgICBwcm9tOiBQcm9taXNlPEM+LFxuICAgICAgICBwcm9wcz86IENvbXBvbmVudFByb3BzPEM+LFxuICAgICAgICBjbGFzc05hbWU/OiBzdHJpbmcsXG4gICAgICAgIGlzUHJpb3JpdHlNb2RhbCA9IGZhbHNlLFxuICAgICAgICBpc1N0YXRpY01vZGFsID0gZmFsc2UsXG4gICAgICAgIG9wdGlvbnM6IElPcHRpb25zPEM+ID0ge30sXG4gICAgKTogSUhhbmRsZTxDPiB7XG4gICAgICAgIGNvbnN0IGJlZm9yZU1vZGFsID0gdGhpcy5nZXRDdXJyZW50TW9kYWwoKTtcbiAgICAgICAgY29uc3QgeyBtb2RhbCwgY2xvc2VEaWFsb2csIG9uRmluaXNoZWRQcm9tIH0gPSB0aGlzLmJ1aWxkTW9kYWw8Qz4ocHJvbSwgcHJvcHMsIGNsYXNzTmFtZSwgb3B0aW9ucyk7XG4gICAgICAgIGlmIChpc1ByaW9yaXR5TW9kYWwpIHtcbiAgICAgICAgICAgIC8vIFhYWDogVGhpcyBpcyBkZXN0cnVjdGl2ZVxuICAgICAgICAgICAgdGhpcy5wcmlvcml0eU1vZGFsID0gbW9kYWw7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNTdGF0aWNNb2RhbCkge1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBpbnRlbnRpb25hbGx5IGRlc3RydWN0aXZlXG4gICAgICAgICAgICB0aGlzLnN0YXRpY01vZGFsID0gbW9kYWw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm1vZGFscy51bnNoaWZ0KG1vZGFsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVSZW5kZXIoKTtcbiAgICAgICAgdGhpcy5lbWl0SWZDaGFuZ2VkKGJlZm9yZU1vZGFsKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY2xvc2U6IGNsb3NlRGlhbG9nLFxuICAgICAgICAgICAgZmluaXNoZWQ6IG9uRmluaXNoZWRQcm9tLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXBwZW5kRGlhbG9nQXN5bmM8QyBleHRlbmRzIENvbXBvbmVudFR5cGU+KFxuICAgICAgICBwcm9tOiBQcm9taXNlPEM+LFxuICAgICAgICBwcm9wcz86IENvbXBvbmVudFByb3BzPEM+LFxuICAgICAgICBjbGFzc05hbWU/OiBzdHJpbmcsXG4gICAgKTogSUhhbmRsZTxDPiB7XG4gICAgICAgIGNvbnN0IGJlZm9yZU1vZGFsID0gdGhpcy5nZXRDdXJyZW50TW9kYWwoKTtcbiAgICAgICAgY29uc3QgeyBtb2RhbCwgY2xvc2VEaWFsb2csIG9uRmluaXNoZWRQcm9tIH0gPSB0aGlzLmJ1aWxkTW9kYWw8Qz4ocHJvbSwgcHJvcHMsIGNsYXNzTmFtZSwge30pO1xuXG4gICAgICAgIHRoaXMubW9kYWxzLnB1c2gobW9kYWwpO1xuXG4gICAgICAgIHRoaXMucmVSZW5kZXIoKTtcbiAgICAgICAgdGhpcy5lbWl0SWZDaGFuZ2VkKGJlZm9yZU1vZGFsKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY2xvc2U6IGNsb3NlRGlhbG9nLFxuICAgICAgICAgICAgZmluaXNoZWQ6IG9uRmluaXNoZWRQcm9tLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgZW1pdElmQ2hhbmdlZChiZWZvcmVNb2RhbD86IElNb2RhbDxhbnk+KTogdm9pZCB7XG4gICAgICAgIGlmIChiZWZvcmVNb2RhbCAhPT0gdGhpcy5nZXRDdXJyZW50TW9kYWwoKSkge1xuICAgICAgICAgICAgdGhpcy5lbWl0KE1vZGFsTWFuYWdlckV2ZW50Lk9wZW5lZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbWl0IHRoZSBjbG9zZWQgZXZlbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHByaXZhdGUgZW1pdENsb3NlZCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lbWl0KE1vZGFsTWFuYWdlckV2ZW50LkNsb3NlZCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkJhY2tncm91bmRDbGljayA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgY29uc3QgbW9kYWwgPSB0aGlzLmdldEN1cnJlbnRNb2RhbCgpO1xuICAgICAgICBpZiAoIW1vZGFsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2Ugd2FudCB0byBwYXNzIGEgcmVhc29uIHRvIHRoZSBvbkJlZm9yZUNsb3NlXG4gICAgICAgIC8vIGNhbGxiYWNrLCBidXQgY2xvc2UgaXMgY3VycmVudGx5IGRlZmluZWQgdG9cbiAgICAgICAgLy8gcGFzcyBhbGwgbnVtYmVyIG9mIGFyZ3VtZW50cyB0byB0aGUgb25GaW5pc2hlZCBjYWxsYmFja1xuICAgICAgICAvLyBzbywgcGFzcyB0aGUgcmVhc29uIHRvIGNsb3NlIHRocm91Z2ggYSBtZW1iZXIgdmFyaWFibGVcbiAgICAgICAgbW9kYWwuY2xvc2VSZWFzb24gPSBcImJhY2tncm91bmRDbGlja1wiO1xuICAgICAgICBtb2RhbC5jbG9zZSgpO1xuICAgICAgICBtb2RhbC5jbG9zZVJlYXNvbiA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBnZXRDdXJyZW50TW9kYWwoKTogSU1vZGFsPGFueT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5wcmlvcml0eU1vZGFsID8gdGhpcy5wcmlvcml0eU1vZGFsIDogdGhpcy5tb2RhbHNbMF0gfHwgdGhpcy5zdGF0aWNNb2RhbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlUmVuZGVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICAvLyBUT0RPOiBXZSBzaG91bGQgZmlndXJlIG91dCBob3cgdG8gcmVtb3ZlIHRoaXMgd2VpcmQgc2xlZXAuIEl0IGFsc28gbWFrZXMgdGVzdGluZyBoYXJkZXJcbiAgICAgICAgLy9cbiAgICAgICAgLy8gYXdhaXQgbmV4dCB0aWNrIGJlY2F1c2Ugc29tZXRpbWVzIFJlYWN0RE9NIGNhbiByYWNlIHdpdGggaXRzZWxmIGFuZCBjYXVzZSB0aGUgbW9kYWwgdG8gd3JvbmdseSBzdGljayBhcm91bmRcbiAgICAgICAgYXdhaXQgc2xlZXAoMCk7XG5cbiAgICAgICAgaWYgKHRoaXMubW9kYWxzLmxlbmd0aCA9PT0gMCAmJiAhdGhpcy5wcmlvcml0eU1vZGFsICYmICF0aGlzLnN0YXRpY01vZGFsKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBubyBtb2RhbCB0byByZW5kZXIsIG1ha2UgYWxsIG9mIEVsZW1lbnQgYXZhaWxhYmxlXG4gICAgICAgICAgICAvLyB0byBzY3JlZW4gcmVhZGVyIHVzZXJzIGFnYWluXG4gICAgICAgICAgICBkaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIGFjdGlvbjogXCJhcmlhX3VuaGlkZV9tYWluX2FwcFwiLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBSZWFjdERPTS51bm1vdW50Q29tcG9uZW50QXROb2RlKE1vZGFsTWFuYWdlci5nZXRPckNyZWF0ZUNvbnRhaW5lcigpKTtcbiAgICAgICAgICAgIFJlYWN0RE9NLnVubW91bnRDb21wb25lbnRBdE5vZGUoTW9kYWxNYW5hZ2VyLmdldE9yQ3JlYXRlU3RhdGljQ29udGFpbmVyKCkpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGlkZSB0aGUgY29udGVudCBvdXRzaWRlIHRoZSBtb2RhbCB0byBzY3JlZW4gcmVhZGVyIHVzZXJzXG4gICAgICAgIC8vIHNvIHRoZXkgd29uJ3QgYmUgYWJsZSB0byBuYXZpZ2F0ZSBpbnRvIGl0IGFuZCBhY3Qgb24gaXQgdXNpbmdcbiAgICAgICAgLy8gc2NyZWVuIHJlYWRlciBzcGVjaWZpYyBmZWF0dXJlc1xuICAgICAgICBkaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgYWN0aW9uOiBcImFyaWFfaGlkZV9tYWluX2FwcFwiLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5zdGF0aWNNb2RhbCkge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NlcyA9IGNsYXNzTmFtZXMoXCJteF9EaWFsb2dfd3JhcHBlciBteF9EaWFsb2dfc3RhdGljV3JhcHBlclwiLCB0aGlzLnN0YXRpY01vZGFsLmNsYXNzTmFtZSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHN0YXRpY0RpYWxvZyA9IChcbiAgICAgICAgICAgICAgICA8VG9vbHRpcFByb3ZpZGVyPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT17Y2xhc3Nlc30+XG4gICAgICAgICAgICAgICAgICAgICAgICA8R2xhc3MgY2xhc3NOYW1lPVwibXhfRGlhbG9nX2JvcmRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfRGlhbG9nXCI+e3RoaXMuc3RhdGljTW9kYWwuZWxlbX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvR2xhc3M+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS10ZXN0aWQ9XCJkaWFsb2ctYmFja2dyb3VuZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfRGlhbG9nX2JhY2tncm91bmQgbXhfRGlhbG9nX3N0YXRpY0JhY2tncm91bmRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25CYWNrZ3JvdW5kQ2xpY2t9XG4gICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L1Rvb2x0aXBQcm92aWRlcj5cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIFJlYWN0RE9NLnJlbmRlcihzdGF0aWNEaWFsb2csIE1vZGFsTWFuYWdlci5nZXRPckNyZWF0ZVN0YXRpY0NvbnRhaW5lcigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgc2FmZSB0byBjYWxsIHJlcGVhdGVkbHkgaWYgd2UgaGFwcGVuIHRvIGRvIHRoYXRcbiAgICAgICAgICAgIFJlYWN0RE9NLnVubW91bnRDb21wb25lbnRBdE5vZGUoTW9kYWxNYW5hZ2VyLmdldE9yQ3JlYXRlU3RhdGljQ29udGFpbmVyKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbW9kYWwgPSB0aGlzLmdldEN1cnJlbnRNb2RhbCgpO1xuICAgICAgICBpZiAobW9kYWwgIT09IHRoaXMuc3RhdGljTW9kYWwgJiYgIW1vZGFsLmhpZGRlbikge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NlcyA9IGNsYXNzTmFtZXMoXCJteF9EaWFsb2dfd3JhcHBlclwiLCBtb2RhbC5jbGFzc05hbWUsIHtcbiAgICAgICAgICAgICAgICBteF9EaWFsb2dfd3JhcHBlcldpdGhTdGF0aWNVbmRlcjogdGhpcy5zdGF0aWNNb2RhbCxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjb25zdCBkaWFsb2cgPSAoXG4gICAgICAgICAgICAgICAgPFRvb2x0aXBQcm92aWRlcj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9e2NsYXNzZXN9PlxuICAgICAgICAgICAgICAgICAgICAgICAgPEdsYXNzIGNsYXNzTmFtZT1cIm14X0RpYWxvZ19ib3JkZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0RpYWxvZ1wiPnttb2RhbC5lbGVtfTwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9HbGFzcz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLXRlc3RpZD1cImRpYWxvZy1iYWNrZ3JvdW5kXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9EaWFsb2dfYmFja2dyb3VuZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy5vbkJhY2tncm91bmRDbGlja31cbiAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvVG9vbHRpcFByb3ZpZGVyPlxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiBSZWFjdERPTS5yZW5kZXIoZGlhbG9nLCBNb2RhbE1hbmFnZXIuZ2V0T3JDcmVhdGVDb250YWluZXIoKSksIDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBzYWZlIHRvIGNhbGwgcmVwZWF0ZWRseSBpZiB3ZSBoYXBwZW4gdG8gZG8gdGhhdFxuICAgICAgICAgICAgUmVhY3RET00udW5tb3VudENvbXBvbmVudEF0Tm9kZShNb2RhbE1hbmFnZXIuZ2V0T3JDcmVhdGVDb250YWluZXIoKSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmlmICghd2luZG93LnNpbmdsZXRvbk1vZGFsTWFuYWdlcikge1xuICAgIHdpbmRvdy5zaW5nbGV0b25Nb2RhbE1hbmFnZXIgPSBuZXcgTW9kYWxNYW5hZ2VyKCk7XG59XG5leHBvcnQgZGVmYXVsdCB3aW5kb3cuc2luZ2xldG9uTW9kYWxNYW5hZ2VyO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFTQSxJQUFBQSxNQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxTQUFBLEdBQUFGLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRSxXQUFBLEdBQUFILHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRyxNQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxPQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxZQUFBLEdBQUFMLE9BQUE7QUFFQSxJQUFBTSxXQUFBLEdBQUFDLHVCQUFBLENBQUFQLE9BQUE7QUFDQSxJQUFBUSxhQUFBLEdBQUFULHNCQUFBLENBQUFDLE9BQUE7QUFBMEMsU0FBQVMseUJBQUFDLENBQUEsNkJBQUFDLE9BQUEsbUJBQUFDLENBQUEsT0FBQUQsT0FBQSxJQUFBRSxDQUFBLE9BQUFGLE9BQUEsWUFBQUYsd0JBQUEsWUFBQUEsQ0FBQUMsQ0FBQSxXQUFBQSxDQUFBLEdBQUFHLENB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