UNPKG

matrix-react-sdk

Version:
308 lines (257 loc) 39.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _react = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _event = require("matrix-js-sdk/src/models/event"); var _languageHandler = require("../../../languageHandler"); var sdk = _interopRequireWildcard(require("../../../index")); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var _ContextMenu = require("../../structures/ContextMenu"); var _EventUtils = require("../../../utils/EventUtils"); var _RoomContext = _interopRequireDefault(require("../../../contexts/RoomContext")); var _Toolbar = _interopRequireDefault(require("../../../accessibility/Toolbar")); var _RovingTabIndex = require("../../../accessibility/RovingTabIndex"); var _replaceableComponent = require("../../../utils/replaceableComponent"); var _MessageContextMenu = require("../context_menus/MessageContextMenu"); var _Resend = _interopRequireDefault(require("../../../Resend")); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _dec, _class, _class2, _temp; const OptionsButton = ({ mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange }) => { const [menuDisplayed, button, openMenu, closeMenu] = (0, _ContextMenu.useContextMenu)(); const [onFocus, isActive, ref] = (0, _RovingTabIndex.useRovingTabIndex)(button); (0, _react.useEffect)(() => { onFocusChange(menuDisplayed); }, [onFocusChange, menuDisplayed]); let contextMenu; if (menuDisplayed) { const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu'); const tile = getTile && getTile(); const replyThread = getReplyThread && getReplyThread(); const buttonRect = button.current.getBoundingClientRect(); contextMenu = /*#__PURE__*/_react.default.createElement(_ContextMenu.ContextMenu, (0, _extends2.default)({}, (0, _ContextMenu.aboveLeftOf)(buttonRect), { onFinished: closeMenu }), /*#__PURE__*/_react.default.createElement(MessageContextMenu, { mxEvent: mxEvent, permalinkCreator: permalinkCreator, eventTileOps: tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined, collapseReplyThread: replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined, onFinished: closeMenu })); } return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_ContextMenu.ContextMenuTooltipButton, { className: "mx_MessageActionBar_maskButton mx_MessageActionBar_optionsButton", title: (0, _languageHandler._t)("Options"), onClick: openMenu, isExpanded: menuDisplayed, inputRef: ref, onFocus: onFocus, tabIndex: isActive ? 0 : -1 }), contextMenu); }; const ReactButton = ({ mxEvent, reactions, onFocusChange }) => { const [menuDisplayed, button, openMenu, closeMenu] = (0, _ContextMenu.useContextMenu)(); const [onFocus, isActive, ref] = (0, _RovingTabIndex.useRovingTabIndex)(button); (0, _react.useEffect)(() => { onFocusChange(menuDisplayed); }, [onFocusChange, menuDisplayed]); let contextMenu; if (menuDisplayed) { const buttonRect = button.current.getBoundingClientRect(); const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker'); contextMenu = /*#__PURE__*/_react.default.createElement(_ContextMenu.ContextMenu, (0, _extends2.default)({}, (0, _ContextMenu.aboveLeftOf)(buttonRect), { onFinished: closeMenu, managed: false }), /*#__PURE__*/_react.default.createElement(ReactionPicker, { mxEvent: mxEvent, reactions: reactions, onFinished: closeMenu })); } return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_ContextMenu.ContextMenuTooltipButton, { className: "mx_MessageActionBar_maskButton mx_MessageActionBar_reactButton", title: (0, _languageHandler._t)("React"), onClick: openMenu, isExpanded: menuDisplayed, inputRef: ref, onFocus: onFocus, tabIndex: isActive ? 0 : -1 }), contextMenu); }; let MessageActionBar = (_dec = (0, _replaceableComponent.replaceableComponent)("views.messages.MessageActionBar"), _dec(_class = (_temp = _class2 = class MessageActionBar extends _react.default.PureComponent { constructor(...args) { super(...args); (0, _defineProperty2.default)(this, "onDecrypted", () => { // When an event decrypts, it is likely to change the set of available // actions, so we force an update to check again. this.forceUpdate(); }); (0, _defineProperty2.default)(this, "onBeforeRedaction", () => { // When an event is redacted, we can't edit it so update the available actions. this.forceUpdate(); }); (0, _defineProperty2.default)(this, "onSent", () => { // When an event is sent and echoed the possible actions change. this.forceUpdate(); }); (0, _defineProperty2.default)(this, "onFocusChange", focused => { if (!this.props.onFocusChange) { return; } this.props.onFocusChange(focused); }); (0, _defineProperty2.default)(this, "onReplyClick", ev => { _dispatcher.default.dispatch({ action: 'reply_to_event', event: this.props.mxEvent }); }); (0, _defineProperty2.default)(this, "onEditClick", ev => { _dispatcher.default.dispatch({ action: 'edit_event', event: this.props.mxEvent }); }); (0, _defineProperty2.default)(this, "onResendClick", ev => { this.runActionOnFailedEv(tarEv => _Resend.default.resend(tarEv)); }); (0, _defineProperty2.default)(this, "onCancelClick", ev => { this.runActionOnFailedEv(tarEv => _Resend.default.removeFromQueue(tarEv), testEv => (0, _MessageContextMenu.canCancel)(testEv.status)); }); } componentDidMount() { if (this.props.mxEvent.status && this.props.mxEvent.status !== _event.EventStatus.SENT) { this.props.mxEvent.on("Event.status", this.onSent); } const client = _MatrixClientPeg.MatrixClientPeg.get(); client.decryptEventIfNeeded(this.props.mxEvent); if (this.props.mxEvent.isBeingDecrypted()) { this.props.mxEvent.once("Event.decrypted", this.onDecrypted); } this.props.mxEvent.on("Event.beforeRedaction", this.onBeforeRedaction); } componentWillUnmount() { this.props.mxEvent.off("Event.status", this.onSent); this.props.mxEvent.off("Event.decrypted", this.onDecrypted); this.props.mxEvent.off("Event.beforeRedaction", this.onBeforeRedaction); } /** * Runs a given fn on the set of possible events to test. The first event * that passes the checkFn will have fn executed on it. Both functions take * a MatrixEvent object. If no particular conditions are needed, checkFn can * be null/undefined. If no functions pass the checkFn, no action will be * taken. * @param {Function} fn The execution function. * @param {Function} checkFn The test function. */ runActionOnFailedEv(fn, checkFn) { if (!checkFn) checkFn = () => true; const mxEvent = this.props.mxEvent; const editEvent = mxEvent.replacingEvent(); const redactEvent = mxEvent.localRedactionEvent(); const tryOrder = [redactEvent, editEvent, mxEvent]; for (const ev of tryOrder) { if (ev && checkFn(ev)) { fn(ev); break; } } } render() { const toolbarOpts = []; if ((0, _EventUtils.canEditContent)(this.props.mxEvent)) { toolbarOpts.push( /*#__PURE__*/_react.default.createElement(_RovingTabIndex.RovingAccessibleTooltipButton, { className: "mx_MessageActionBar_maskButton mx_MessageActionBar_editButton", title: (0, _languageHandler._t)("Edit"), onClick: this.onEditClick, key: "edit" })); } const cancelSendingButton = /*#__PURE__*/_react.default.createElement(_RovingTabIndex.RovingAccessibleTooltipButton, { className: "mx_MessageActionBar_maskButton mx_MessageActionBar_cancelButton", title: (0, _languageHandler._t)("Delete"), onClick: this.onCancelClick, key: "cancel" }); // We show a different toolbar for failed events, so detect that first. const mxEvent = this.props.mxEvent; const editStatus = mxEvent.replacingEvent() && mxEvent.replacingEvent().status; const redactStatus = mxEvent.localRedactionEvent() && mxEvent.localRedactionEvent().status; const allowCancel = (0, _MessageContextMenu.canCancel)(mxEvent.status) || (0, _MessageContextMenu.canCancel)(editStatus) || (0, _MessageContextMenu.canCancel)(redactStatus); const isFailed = [mxEvent.status, editStatus, redactStatus].includes("not_sent"); if (allowCancel && isFailed) { // The resend button needs to appear ahead of the edit button, so insert to the // start of the opts toolbarOpts.splice(0, 0, /*#__PURE__*/_react.default.createElement(_RovingTabIndex.RovingAccessibleTooltipButton, { className: "mx_MessageActionBar_maskButton mx_MessageActionBar_resendButton", title: (0, _languageHandler._t)("Retry"), onClick: this.onResendClick, key: "resend" })); // The delete button should appear last, so we can just drop it at the end toolbarOpts.push(cancelSendingButton); } else { if ((0, _EventUtils.isContentActionable)(this.props.mxEvent)) { // Like the resend button, the react and reply buttons need to appear before the edit. // The only catch is we do the reply button first so that we can make sure the react // button is the very first button without having to do length checks for `splice()`. if (this.context.canReply) { toolbarOpts.splice(0, 0, /*#__PURE__*/_react.default.createElement(_RovingTabIndex.RovingAccessibleTooltipButton, { className: "mx_MessageActionBar_maskButton mx_MessageActionBar_replyButton", title: (0, _languageHandler._t)("Reply"), onClick: this.onReplyClick, key: "reply" })); } if (this.context.canReact) { toolbarOpts.splice(0, 0, /*#__PURE__*/_react.default.createElement(ReactButton, { mxEvent: this.props.mxEvent, reactions: this.props.reactions, onFocusChange: this.onFocusChange, key: "react" })); } } if (allowCancel) { toolbarOpts.push(cancelSendingButton); } // The menu button should be last, so dump it there. toolbarOpts.push( /*#__PURE__*/_react.default.createElement(OptionsButton, { mxEvent: this.props.mxEvent, getReplyThread: this.props.getReplyThread, getTile: this.props.getTile, permalinkCreator: this.props.permalinkCreator, onFocusChange: this.onFocusChange, key: "menu" })); } // aria-live=off to not have this read out automatically as navigating around timeline, gets repetitive. return /*#__PURE__*/_react.default.createElement(_Toolbar.default, { className: "mx_MessageActionBar", "aria-label": (0, _languageHandler._t)("Message Actions"), "aria-live": "off" }, toolbarOpts); } }, (0, _defineProperty2.default)(_class2, "propTypes", { mxEvent: _propTypes.default.object.isRequired, // The Relations model from the JS SDK for reactions to `mxEvent` reactions: _propTypes.default.object, permalinkCreator: _propTypes.default.object, getTile: _propTypes.default.func, getReplyThread: _propTypes.default.func, onFocusChange: _propTypes.default.func }), (0, _defineProperty2.default)(_class2, "contextType", _RoomContext.default), _temp)) || _class); exports.default = MessageActionBar; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL21lc3NhZ2VzL01lc3NhZ2VBY3Rpb25CYXIuanMiXSwibmFtZXMiOlsiT3B0aW9uc0J1dHRvbiIsIm14RXZlbnQiLCJnZXRUaWxlIiwiZ2V0UmVwbHlUaHJlYWQiLCJwZXJtYWxpbmtDcmVhdG9yIiwib25Gb2N1c0NoYW5nZSIsIm1lbnVEaXNwbGF5ZWQiLCJidXR0b24iLCJvcGVuTWVudSIsImNsb3NlTWVudSIsIm9uRm9jdXMiLCJpc0FjdGl2ZSIsInJlZiIsImNvbnRleHRNZW51IiwiTWVzc2FnZUNvbnRleHRNZW51Iiwic2RrIiwiZ2V0Q29tcG9uZW50IiwidGlsZSIsInJlcGx5VGhyZWFkIiwiYnV0dG9uUmVjdCIsImN1cnJlbnQiLCJnZXRCb3VuZGluZ0NsaWVudFJlY3QiLCJnZXRFdmVudFRpbGVPcHMiLCJ1bmRlZmluZWQiLCJjYW5Db2xsYXBzZSIsImNvbGxhcHNlIiwiUmVhY3RCdXR0b24iLCJyZWFjdGlvbnMiLCJSZWFjdGlvblBpY2tlciIsIk1lc3NhZ2VBY3Rpb25CYXIiLCJSZWFjdCIsIlB1cmVDb21wb25lbnQiLCJmb3JjZVVwZGF0ZSIsImZvY3VzZWQiLCJwcm9wcyIsImV2IiwiZGlzIiwiZGlzcGF0Y2giLCJhY3Rpb24iLCJldmVudCIsInJ1bkFjdGlvbk9uRmFpbGVkRXYiLCJ0YXJFdiIsIlJlc2VuZCIsInJlc2VuZCIsInJlbW92ZUZyb21RdWV1ZSIsInRlc3RFdiIsInN0YXR1cyIsImNvbXBvbmVudERpZE1vdW50IiwiRXZlbnRTdGF0dXMiLCJTRU5UIiwib24iLCJvblNlbnQiLCJjbGllbnQiLCJNYXRyaXhDbGllbnRQZWciLCJnZXQiLCJkZWNyeXB0RXZlbnRJZk5lZWRlZCIsImlzQmVpbmdEZWNyeXB0ZWQiLCJvbmNlIiwib25EZWNyeXB0ZWQiLCJvbkJlZm9yZVJlZGFjdGlvbiIsImNvbXBvbmVudFdpbGxVbm1vdW50Iiwib2ZmIiwiZm4iLCJjaGVja0ZuIiwiZWRpdEV2ZW50IiwicmVwbGFjaW5nRXZlbnQiLCJyZWRhY3RFdmVudCIsImxvY2FsUmVkYWN0aW9uRXZlbnQiLCJ0cnlPcmRlciIsInJlbmRlciIsInRvb2xiYXJPcHRzIiwicHVzaCIsIm9uRWRpdENsaWNrIiwiY2FuY2VsU2VuZGluZ0J1dHRvbiIsIm9uQ2FuY2VsQ2xpY2siLCJlZGl0U3RhdHVzIiwicmVkYWN0U3RhdHVzIiwiYWxsb3dDYW5jZWwiLCJpc0ZhaWxlZCIsImluY2x1ZGVzIiwic3BsaWNlIiwib25SZXNlbmRDbGljayIsImNvbnRleHQiLCJjYW5SZXBseSIsIm9uUmVwbHlDbGljayIsImNhblJlYWN0IiwiUHJvcFR5cGVzIiwib2JqZWN0IiwiaXNSZXF1aXJlZCIsImZ1bmMiLCJSb29tQ29udGV4dCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBa0JBOztBQUNBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBRUEsTUFBTUEsYUFBYSxHQUFHLENBQUM7QUFBQ0MsRUFBQUEsT0FBRDtBQUFVQyxFQUFBQSxPQUFWO0FBQW1CQyxFQUFBQSxjQUFuQjtBQUFtQ0MsRUFBQUEsZ0JBQW5DO0FBQXFEQyxFQUFBQTtBQUFyRCxDQUFELEtBQXlFO0FBQzNGLFFBQU0sQ0FBQ0MsYUFBRCxFQUFnQkMsTUFBaEIsRUFBd0JDLFFBQXhCLEVBQWtDQyxTQUFsQyxJQUErQyxrQ0FBckQ7QUFDQSxRQUFNLENBQUNDLE9BQUQsRUFBVUMsUUFBVixFQUFvQkMsR0FBcEIsSUFBMkIsdUNBQWtCTCxNQUFsQixDQUFqQztBQUNBLHdCQUFVLE1BQU07QUFDWkYsSUFBQUEsYUFBYSxDQUFDQyxhQUFELENBQWI7QUFDSCxHQUZELEVBRUcsQ0FBQ0QsYUFBRCxFQUFnQkMsYUFBaEIsQ0FGSDtBQUlBLE1BQUlPLFdBQUo7O0FBQ0EsTUFBSVAsYUFBSixFQUFtQjtBQUNmLFVBQU1RLGtCQUFrQixHQUFHQyxHQUFH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U0FBUyxFQUFDLHFCQUFuQjtBQUF5QyxvQkFBWSx5QkFBRyxpQkFBSCxDQUFyRDtBQUE0RSxtQkFBVTtBQUF0RixPQUNGaUUsV0FERSxDQUFQO0FBR0g7O0FBdkw2RCxDLHNEQUMzQztBQUNmckUsRUFBQUEsT0FBTyxFQUFFcUYsbUJBQVVDLE1BQVYsQ0FBaUJDLFVBRFg7QUFFZjtBQUNBN0QsRUFBQUEsU0FBUyxFQUFFMkQsbUJBQVVDLE1BSE47QUFJZm5GLEVBQUFBLGdCQUFnQixFQUFFa0YsbUJBQVVDLE1BSmI7QUFLZnJGLEVBQUFBLE9BQU8sRUFBRW9GLG1CQUFVRyxJQUxKO0FBTWZ0RixFQUFBQSxjQUFjLEVBQUVtRixtQkFBVUcsSUFOWDtBQU9mcEYsRUFBQUEsYUFBYSxFQUFFaUYsbUJBQVVHO0FBUFYsQyx5REFVRUMsb0IiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMTkgTmV3IFZlY3RvciBMdGRcbkNvcHlyaWdodCAyMDE5IE1pY2hhZWwgVGVsYXR5bnNraSA8N3QzY2hndXlAZ21haWwuY29tPlxuQ29weXJpZ2h0IDIwMTksIDIwMjAgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VFZmZlY3R9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBQcm9wVHlwZXMgZnJvbSAncHJvcC10eXBlcyc7XG5pbXBvcnQgeyBFdmVudFN0YXR1cyB9IGZyb20gJ21hdHJpeC1qcy1zZGsvc3JjL21vZGVscy9ldmVudCc7XG5cbmltcG9ydCB7IF90IH0gZnJvbSAnLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyJztcbmltcG9ydCAqIGFzIHNkayBmcm9tICcuLi8uLi8uLi9pbmRleCc7XG5pbXBvcnQgZGlzIGZyb20gJy4uLy4uLy4uL2Rpc3BhdGNoZXIvZGlzcGF0Y2hlcic7XG5pbXBvcnQge2Fib3ZlTGVmdE9mLCBDb250ZXh0TWVudSwgQ29udGV4dE1lbnVUb29sdGlwQnV0dG9uLCB1c2VDb250ZXh0TWVudX0gZnJvbSAnLi4vLi4vc3RydWN0dXJlcy9Db250ZXh0TWVudSc7XG5pbXBvcnQgeyBpc0NvbnRlbnRBY3Rpb25hYmxlLCBjYW5FZGl0Q29udGVudCB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL0V2ZW50VXRpbHMnO1xuaW1wb3J0IFJvb21Db250ZXh0IGZyb20gXCIuLi8uLi8uLi9jb250ZXh0cy9Sb29tQ29udGV4dFwiO1xuaW1wb3J0IFRvb2xiYXIgZnJvbSBcIi4uLy4uLy4uL2FjY2Vzc2liaWxpdHkvVG9vbGJhclwiO1xuaW1wb3J0IHtSb3ZpbmdBY2Nlc3NpYmxlVG9vbHRpcEJ1dHRvbiwgdXNlUm92aW5nVGFiSW5kZXh9IGZyb20gXCIuLi8uLi8uLi9hY2Nlc3NpYmlsaXR5L1JvdmluZ1RhYkluZGV4XCI7XG5pbXBvcnQge3JlcGxhY2VhYmxlQ29tcG9uZW50fSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvcmVwbGFjZWFibGVDb21wb25lbnRcIjtcbmltcG9ydCB7Y2FuQ2FuY2VsfSBmcm9tIFwiLi4vY29udGV4dF9tZW51cy9NZXNzYWdlQ29udGV4dE1lbnVcIjtcbmltcG9ydCBSZXNlbmQgZnJvbSBcIi4uLy4uLy4uL1Jlc2VuZFwiO1xuaW1wb3J0IHsgTWF0cml4Q2xpZW50UGVnIH0gZnJvbSBcIi4uLy4uLy4uL01hdHJpeENsaWVudFBlZ1wiO1xuXG5jb25zdCBPcHRpb25zQnV0dG9uID0gKHtteEV2ZW50LCBnZXRUaWxlLCBnZXRSZXBseVRocmVhZCwgcGVybWFsaW5rQ3JlYXRvciwgb25Gb2N1c0NoYW5nZX0pID0+IHtcbiAgICBjb25zdCBbbWVudURpc3BsYXllZCwgYnV0dG9uLCBvcGVuTWVudSwgY2xvc2VNZW51XSA9IHVzZUNvbnRleHRNZW51KCk7XG4gICAgY29uc3QgW29uRm9jdXMsIGlzQWN0aXZlLCByZWZdID0gdXNlUm92aW5nVGFiSW5kZXgoYnV0dG9uKTtcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBvbkZvY3VzQ2hhbmdlKG1lbnVEaXNwbGF5ZWQpO1xuICAgIH0sIFtvbkZvY3VzQ2hhbmdlLCBtZW51RGlzcGxheWVkXSk7XG5cbiAgICBsZXQgY29udGV4dE1lbnU7XG4gICAgaWYgKG1lbnVEaXNwbGF5ZWQpIHtcbiAgICAgICAgY29uc3QgTWVzc2FnZUNvbnRleHRNZW51ID0gc2RrLmdldENvbXBvbmVudCgnY29udGV4dF9tZW51cy5NZXNzYWdlQ29udGV4dE1lbnUnKTtcblxuICAgICAgICBjb25zdCB0aWxlID0gZ2V0VGlsZSAmJiBnZXRUaWxlKCk7XG4gICAgICAgIGNvbnN0IHJlcGx5VGhyZWFkID0gZ2V0UmVwbHlUaHJlYWQgJiYgZ2V0UmVwbHlUaHJlYWQoKTtcblxuICAgICAgICBjb25zdCBidXR0b25SZWN0ID0gYnV0dG9uLmN1cnJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnRleHRNZW51ID0gPENvbnRleHRNZW51IHsuLi5hYm92ZUxlZnRPZihidXR0b25SZWN0KX0gb25GaW5pc2hlZD17Y2xvc2VNZW51fT5cbiAgICAgICAgICAgIDxNZXNzYWdlQ29udGV4dE1lbnVcbiAgICAgICAgICAgICAgICBteEV2ZW50PXtteEV2ZW50fVxuICAgICAgICAgICAgICAgIHBlcm1hbGlua0NyZWF0b3I9e3Blcm1hbGlua0NyZWF0b3J9XG4gICAgICAgICAgICAgICAgZXZlbnRUaWxlT3BzPXt0aWxlICYmIHRpbGUuZ2V0RXZlbnRUaWxlT3BzID8gdGlsZS5nZXRFdmVudFRpbGVPcHMoKSA6IHVuZGVmaW5lZH1cbiAgICAgICAgICAgICAgICBjb2xsYXBzZVJlcGx5VGhyZWFkPXtyZXBseVRocmVhZCAmJiByZXBseVRocmVhZC5jYW5Db2xsYXBzZSgpID8gcmVwbHlUaHJlYWQuY29sbGFwc2UgOiB1bmRlZmluZWR9XG4gICAgICAgICAgICAgICAgb25GaW5pc2hlZD17Y2xvc2VNZW51fVxuICAgICAgICAgICAgLz5cbiAgICAgICAgPC9Db250ZXh0TWVudT47XG4gICAgfVxuXG4gICAgcmV0dXJuIDxSZWFjdC5GcmFnbWVudD5cbiAgICAgICAgPENvbnRleHRNZW51VG9vbHRpcEJ1dHRvblxuICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfTWVzc2FnZUFjdGlvbkJhcl9tYXNrQnV0dG9uIG14X01lc3NhZ2VBY3Rpb25CYXJfb3B0aW9uc0J1dHRvblwiXG4gICAgICAgICAgICB0aXRsZT17X3QoXCJPcHRpb25zXCIpfVxuICAgICAgICAgICAgb25DbGljaz17b3Blbk1lbnV9XG4gICAgICAgICAgICBpc0V4cGFuZGVkPXttZW51RGlzcGxheWVkfVxuICAgICAgICAgICAgaW5wdXRSZWY9e3JlZn1cbiAgICAgICAgICAgIG9uRm9jdXM9e29uRm9jdXN9XG4gICAgICAgICAgICB0YWJJbmRleD17aXNBY3RpdmUgPyAwIDogLTF9XG4gICAgICAgIC8+XG5cbiAgICAgICAgeyBjb250ZXh0TWVudSB9XG4gICAgPC9SZWFjdC5GcmFnbWVudD47XG59O1xuXG5jb25zdCBSZWFjdEJ1dHRvbiA9ICh7bXhFdmVudCwgcmVhY3Rpb25zLCBvbkZvY3VzQ2hhbmdlfSkgPT4ge1xuICAgIGNvbnN0IFttZW51RGlzcGxheWVkLCBidXR0b24sIG9wZW5NZW51LCBjbG9zZU1lbnVdID0gdXNlQ29udGV4dE1lbnUoKTtcbiAgICBjb25zdCBbb25Gb2N1cywgaXNBY3RpdmUsIHJlZl0gPSB1c2VSb3ZpbmdUYWJJbmRleChidXR0b24pO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIG9uRm9jdXNDaGFuZ2UobWVudURpc3BsYXllZCk7XG4gICAgfSwgW29uRm9jdXNDaGFuZ2UsIG1lbnVEaXNwbGF5ZWRdKTtcblxuICAgIGxldCBjb250ZXh0TWVudTtcbiAgICBpZiAobWVudURpc3BsYXllZCkge1xuICAgICAgICBjb25zdCBidXR0b25SZWN0ID0gYnV0dG9uLmN1cnJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IFJlYWN0aW9uUGlja2VyID0gc2RrLmdldENvbXBvbmVudCgnZW1vamlwaWNrZXIuUmVhY3Rpb25QaWNrZXInKTtcbiAgICAgICAgY29udGV4dE1lbnUgPSA8Q29udGV4dE1lbnUgey4uLmFib3ZlTGVmdE9mKGJ1dHRvblJlY3QpfSBvbkZpbmlzaGVkPXtjbG9zZU1lbnV9IG1hbmFnZWQ9e2ZhbHNlfT5cbiAgICAgICAgICAgIDxSZWFjdGlvblBpY2tlciBteEV2ZW50PXtteEV2ZW50fSByZWFjdGlvbnM9e3JlYWN0aW9uc30gb25GaW5pc2hlZD17Y2xvc2VNZW51fSAvPlxuICAgICAgICA8L0NvbnRleHRNZW51PjtcbiAgICB9XG5cbiAgICByZXR1cm4gPFJlYWN0LkZyYWdtZW50PlxuICAgICAgICA8Q29udGV4dE1lbnVUb29sdGlwQnV0dG9uXG4gICAgICAgICAgICBjbGFzc05hbWU9XCJteF9NZXNzYWdlQWN0aW9uQmFyX21hc2tCdXR0b24gbXhfTWVzc2FnZUFjdGlvbkJhcl9yZWFjdEJ1dHRvblwiXG4gICAgICAgICAgICB0aXRsZT17X3QoXCJSZWFjdFwiKX1cbiAgICAgICAgICAgIG9uQ2xpY2s9e29wZW5NZW51fVxuICAgICAgICAgICAgaXNFeHBhbmRlZD17bWVudURpc3BsYXllZH1cbiAgICAgICAgICAgIGlucHV0UmVmPXtyZWZ9XG4gICAgICAgICAgICBvbkZvY3VzPXtvbkZvY3VzfVxuICAgICAgICAgICAgdGFiSW5kZXg9e2lzQWN0aXZlID8gMCA6IC0xfVxuICAgICAgICAvPlxuXG4gICAgICAgIHsgY29udGV4dE1lbnUgfVxuICAgIDwvUmVhY3QuRnJhZ21lbnQ+O1xufTtcblxuQHJlcGxhY2VhYmxlQ29tcG9uZW50KFwidmlld3MubWVzc2FnZXMuTWVzc2FnZUFjdGlvbkJhclwiKVxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWVzc2FnZUFjdGlvbkJhciBleHRlbmRzIFJlYWN0LlB1cmVDb21wb25lbnQge1xuICAgIHN0YXRpYyBwcm9wVHlwZXMgPSB7XG4gICAgICAgIG14RXZlbnQ6IFByb3BUeXBlcy5vYmplY3QuaXNSZXF1aXJlZCxcbiAgICAgICAgLy8gVGhlIFJlbGF0aW9ucyBtb2RlbCBmcm9tIHRoZSBKUyBTREsgZm9yIHJlYWN0aW9ucyB0byBgbXhFdmVudGBcbiAgICAgICAgcmVhY3Rpb25zOiBQcm9wVHlwZXMub2JqZWN0LFxuICAgICAgICBwZXJtYWxpbmtDcmVhdG9yOiBQcm9wVHlwZXMub2JqZWN0LFxuICAgICAgICBnZXRUaWxlOiBQcm9wVHlwZXMuZnVuYyxcbiAgICAgICAgZ2V0UmVwbHlUaHJlYWQ6IFByb3BUeXBlcy5mdW5jLFxuICAgICAgICBvbkZvY3VzQ2hhbmdlOiBQcm9wVHlwZXMuZnVuYyxcbiAgICB9O1xuXG4gICAgc3RhdGljIGNvbnRleHRUeXBlID0gUm9vbUNvbnRleHQ7XG5cbiAgICBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMubXhFdmVudC5zdGF0dXMgJiYgdGhpcy5wcm9wcy5teEV2ZW50LnN0YXR1cyAhPT0gRXZlbnRTdGF0dXMuU0VOVCkge1xuICAgICAgICAgICAgdGhpcy5wcm9wcy5teEV2ZW50Lm9uKFwiRXZlbnQuc3RhdHVzXCIsIHRoaXMub25TZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5nZXQoKTtcbiAgICAgICAgY2xpZW50LmRlY3J5cHRFdmVudElmTmVlZGVkKHRoaXMucHJvcHMubXhFdmVudCk7XG5cbiAgICAgICAgaWYgKHRoaXMucHJvcHMubXhFdmVudC5pc0JlaW5nRGVjcnlwdGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMucHJvcHMubXhFdmVudC5vbmNlKFwiRXZlbnQuZGVjcnlwdGVkXCIsIHRoaXMub25EZWNyeXB0ZWQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucHJvcHMubXhFdmVudC5vbihcIkV2ZW50LmJlZm9yZVJlZGFjdGlvblwiLCB0aGlzLm9uQmVmb3JlUmVkYWN0aW9uKTtcbiAgICB9XG5cbiAgICBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICAgICAgdGhpcy5wcm9wcy5teEV2ZW50Lm9mZihcIkV2ZW50LnN0YXR1c1wiLCB0aGlzLm9uU2VudCk7XG4gICAgICAgIHRoaXMucHJvcHMubXhFdmVudC5vZmYoXCJFdmVudC5kZWNyeXB0ZWRcIiwgdGhpcy5vbkRlY3J5cHRlZCk7XG4gICAgICAgIHRoaXMucHJvcHMubXhFdmVudC5vZmYoXCJFdmVudC5iZWZvcmVSZWRhY3Rpb25cIiwgdGhpcy5vbkJlZm9yZVJlZGFjdGlvbik7XG4gICAgfVxuXG4gICAgb25EZWNyeXB0ZWQgPSAoKSA9PiB7XG4gICAgICAgIC8vIFdoZW4gYW4gZXZlbnQgZGVjcnlwdHMsIGl0IGlzIGxpa2VseSB0byBjaGFuZ2UgdGhlIHNldCBvZiBhdmFpbGFibGVcbiAgICAgICAgLy8gYWN0aW9ucywgc28gd2UgZm9yY2UgYW4gdXBkYXRlIHRvIGNoZWNrIGFnYWluLlxuICAgICAgICB0aGlzLmZvcmNlVXBkYXRlKCk7XG4gICAgfTtcblxuICAgIG9uQmVmb3JlUmVkYWN0aW9uID0gKCkgPT4ge1xuICAgICAgICAvLyBXaGVuIGFuIGV2ZW50IGlzIHJlZGFjdGVkLCB3ZSBjYW4ndCBlZGl0IGl0IHNvIHVwZGF0ZSB0aGUgYXZhaWxhYmxlIGFjdGlvbnMuXG4gICAgICAgIHRoaXMuZm9yY2VVcGRhdGUoKTtcbiAgICB9O1xuXG4gICAgb25TZW50ID0gKCkgPT4ge1xuICAgICAgICAvLyBXaGVuIGFuIGV2ZW50IGlzIHNlbnQgYW5kIGVjaG9lZCB0aGUgcG9zc2libGUgYWN0aW9ucyBjaGFuZ2UuXG4gICAgICAgIHRoaXMuZm9yY2VVcGRhdGUoKTtcbiAgICB9O1xuXG4gICAgb25Gb2N1c0NoYW5nZSA9IChmb2N1c2VkKSA9PiB7XG4gICAgICAgIGlmICghdGhpcy5wcm9wcy5vbkZvY3VzQ2hhbmdlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wcm9wcy5vbkZvY3VzQ2hhbmdlKGZvY3VzZWQpO1xuICAgIH07XG5cbiAgICBvblJlcGx5Q2xpY2sgPSAoZXYpID0+IHtcbiAgICAgICAgZGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgIGFjdGlvbjogJ3JlcGx5X3RvX2V2ZW50JyxcbiAgICAgICAgICAgIGV2ZW50OiB0aGlzLnByb3BzLm14RXZlbnQsXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBvbkVkaXRDbGljayA9IChldikgPT4ge1xuICAgICAgICBkaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgYWN0aW9uOiAnZWRpdF9ldmVudCcsXG4gICAgICAgICAgICBldmVudDogdGhpcy5wcm9wcy5teEV2ZW50LFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUnVucyBhIGdpdmVuIGZuIG9uIHRoZSBzZXQgb2YgcG9zc2libGUgZXZlbnRzIHRvIHRlc3QuIFRoZSBmaXJzdCBldmVudFxuICAgICAqIHRoYXQgcGFzc2VzIHRoZSBjaGVja0ZuIHdpbGwgaGF2ZSBmbiBleGVjdXRlZCBvbiBpdC4gQm90aCBmdW5jdGlvbnMgdGFrZVxuICAgICAqIGEgTWF0cml4RXZlbnQgb2JqZWN0LiBJZiBubyBwYXJ0aWN1bGFyIGNvbmRpdGlvbnMgYXJlIG5lZWRlZCwgY2hlY2tGbiBjYW5cbiAgICAgKiBiZSBudWxsL3VuZGVmaW5lZC4gSWYgbm8gZnVuY3Rpb25zIHBhc3MgdGhlIGNoZWNrRm4sIG5vIGFjdGlvbiB3aWxsIGJlXG4gICAgICogdGFrZW4uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGV4ZWN1dGlvbiBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjaGVja0ZuIFRoZSB0ZXN0IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIHJ1bkFjdGlvbk9uRmFpbGVkRXYoZm4sIGNoZWNrRm4pIHtcbiAgICAgICAgaWYgKCFjaGVja0ZuKSBjaGVja0ZuID0gKCkgPT4gdHJ1ZTtcblxuICAgICAgICBjb25zdCBteEV2ZW50ID0gdGhpcy5wcm9wcy5teEV2ZW50O1xuICAgICAgICBjb25zdCBlZGl0RXZlbnQgPSBteEV2ZW50LnJlcGxhY2luZ0V2ZW50KCk7XG4gICAgICAgIGNvbnN0IHJlZGFjdEV2ZW50ID0gbXhFdmVudC5sb2NhbFJlZGFjdGlvbkV2ZW50KCk7XG4gICAgICAgIGNvbnN0IHRyeU9yZGVyID0gW3JlZGFjdEV2ZW50LCBlZGl0RXZlbnQsIG14RXZlbnRdO1xuICAgICAgICBmb3IgKGNvbnN0IGV2IG9mIHRyeU9yZGVyKSB7XG4gICAgICAgICAgICBpZiAoZXYgJiYgY2hlY2tGbihldikpIHtcbiAgICAgICAgICAgICAgICBmbihldik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblJlc2VuZENsaWNrID0gKGV2KSA9PiB7XG4gICAgICAgIHRoaXMucnVuQWN0aW9uT25GYWlsZWRFdigodGFyRXYpID0+IFJlc2VuZC5yZXNlbmQodGFyRXYpKTtcbiAgICB9O1xuXG4gICAgb25DYW5jZWxDbGljayA9IChldikgPT4ge1xuICAgICAgICB0aGlzLnJ1bkFjdGlvbk9uRmFpbGVkRXYoXG4gICAgICAgICAgICAodGFyRXYpID0+IFJlc2VuZC5yZW1vdmVGcm9tUXVldWUodGFyRXYpLFxuICAgICAgICAgICAgKHRlc3RFdikgPT4gY2FuQ2FuY2VsKHRlc3RFdi5zdGF0dXMpLFxuICAgICAgICApO1xuICAgIH07XG5cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGNvbnN0IHRvb2xiYXJPcHRzID0gW107XG4gICAgICAgIGlmIChjYW5FZGl0Q29udGVudCh0aGlzLnByb3BzLm14RXZlbnQpKSB7XG4gICAgICAgICAgICB0b29sYmFyT3B0cy5wdXNoKDxSb3ZpbmdBY2Nlc3NpYmxlVG9vbHRpcEJ1dHRvblxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X01lc3NhZ2VBY3Rpb25CYXJfbWFza0J1dHRvbiBteF9NZXNzYWdlQWN0aW9uQmFyX2VkaXRCdXR0b25cIlxuICAgICAgICAgICAgICAgIHRpdGxlPXtfdChcIkVkaXRcIil9XG4gICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy5vbkVkaXRDbGlja31cbiAgICAgICAgICAgICAgICBrZXk9XCJlZGl0XCJcbiAgICAgICAgICAgIC8+KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNhbmNlbFNlbmRpbmdCdXR0b24gPSA8Um92aW5nQWNjZXNzaWJsZVRvb2x0aXBCdXR0b25cbiAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X01lc3NhZ2VBY3Rpb25CYXJfbWFza0J1dHRvbiBteF9NZXNzYWdlQWN0aW9uQmFyX2NhbmNlbEJ1dHRvblwiXG4gICAgICAgICAgICB0aXRsZT17X3QoXCJEZWxldGVcIil9XG4gICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uQ2FuY2VsQ2xpY2t9XG4gICAgICAgICAgICBrZXk9XCJjYW5jZWxcIlxuICAgICAgICAvPjtcblxuICAgICAgICAvLyBXZSBzaG93IGEgZGlmZmVyZW50IHRvb2xiYXIgZm9yIGZhaWxlZCBldmVudHMsIHNvIGRldGVjdCB0aGF0IGZpcnN0LlxuICAgICAgICBjb25zdCBteEV2ZW50ID0gdGhpcy5wcm9wcy5teEV2ZW50O1xuICAgICAgICBjb25zdCBlZGl0U3RhdHVzID0gbXhFdmVudC5yZXBsYWNpbmdFdmVudCgpICYmIG14RXZlbnQucmVwbGFjaW5nRXZlbnQoKS5zdGF0dXM7XG4gICAgICAgIGNvbnN0IHJlZGFjdFN0YXR1cyA9IG14RXZlbnQubG9jYWxSZWRhY3Rpb25FdmVudCgpICYmIG14RXZlbnQubG9jYWxSZWRhY3Rpb25FdmVudCgpLnN0YXR1cztcbiAgICAgICAgY29uc3QgYWxsb3dDYW5jZWwgPSBjYW5DYW5jZWwobXhFdmVudC5zdGF0dXMpIHx8IGNhbkNhbmNlbChlZGl0U3RhdHVzKSB8fCBjYW5DYW5jZWwocmVkYWN0U3RhdHVzKTtcbiAgICAgICAgY29uc3QgaXNGYWlsZWQgPSBbbXhFdmVudC5zdGF0dXMsIGVkaXRTdGF0dXMsIHJlZGFjdFN0YXR1c10uaW5jbHVkZXMoXCJub3Rfc2VudFwiKTtcbiAgICAgICAgaWYgKGFsbG93Q2FuY2VsICYmIGlzRmFpbGVkKSB7XG4gICAgICAgICAgICAvLyBUaGUgcmVzZW5kIGJ1dHRvbiBuZWVkcyB0byBhcHBlYXIgYWhlYWQgb2YgdGhlIGVkaXQgYnV0dG9uLCBzbyBpbnNlcnQgdG8gdGhlXG4gICAgICAgICAgICAvLyBzdGFydCBvZiB0aGUgb3B0c1xuICAgICAgICAgICAgdG9vbGJhck9wdHMuc3BsaWNlKDAsIDAsIDxSb3ZpbmdBY2Nlc3NpYmxlVG9vbHRpcEJ1dHRvblxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X01lc3NhZ2VBY3Rpb25CYXJfbWFza0J1dHRvbiBteF9NZXNzYWdlQWN0aW9uQmFyX3Jlc2VuZEJ1dHRvblwiXG4gICAgICAgICAgICAgICAgdGl0bGU9e190KFwiUmV0cnlcIil9XG4gICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy5vblJlc2VuZENsaWNrfVxuICAgICAgICAgICAgICAgIGtleT1cInJlc2VuZFwiXG4gICAgICAgICAgICAvPik7XG5cbiAgICAgICAgICAgIC8vIFRoZSBkZWxldGUgYnV0dG9uIHNob3VsZCBhcHBlYXIgbGFzdCwgc28gd2UgY2FuIGp1c3QgZHJvcCBpdCBhdCB0aGUgZW5kXG4gICAgICAgICAgICB0b29sYmFyT3B0cy5wdXNoKGNhbmNlbFNlbmRpbmdCdXR0b24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGlzQ29udGVudEFjdGlvbmFibGUodGhpcy5wcm9wcy5teEV2ZW50KSkge1xuICAgICAgICAgICAgICAgIC8vIExpa2UgdGhlIHJlc2VuZCBidXR0b24sIHRoZSByZWFjdCBhbmQgcmVwbHkgYnV0dG9ucyBuZWVkIHRvIGFwcGVhciBiZWZvcmUgdGhlIGVkaXQuXG4gICAgICAgICAgICAgICAgLy8gVGhlIG9ubHkgY2F0Y2ggaXMgd2UgZG8gdGhlIHJlcGx5IGJ1dHRvbiBmaXJzdCBzbyB0aGF0IHdlIGNhbiBtYWtlIHN1cmUgdGhlIHJlYWN0XG4gICAgICAgICAgICAgICAgLy8gYnV0dG9uIGlzIHRoZSB2ZXJ5IGZpcnN0IGJ1dHRvbiB3aXRob3V0IGhhdmluZyB0byBkbyBsZW5ndGggY2hlY2tzIGZvciBgc3BsaWNlKClgLlxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbnRleHQuY2FuUmVwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgdG9vbGJhck9wdHMuc3BsaWNlKDAsIDAsIDxSb3ZpbmdBY2Nlc3NpYmxlVG9vbHRpcEJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfTWVzc2FnZUFjdGlvbkJhcl9tYXNrQnV0dG9uIG14X01lc3NhZ2VBY3Rpb25CYXJfcmVwbHlCdXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU9e190KFwiUmVwbHlcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uUmVwbHlDbGlja31cbiAgICAgICAgICAgICAgICAgICAgICAgIGtleT1cInJlcGx5XCJcbiAgICAgICAgICAgICAgICAgICAgLz4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb250ZXh0LmNhblJlYWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRvb2xiYXJPcHRzLnNwbGljZSgwLCAwLCA8UmVhY3RCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIG14RXZlbnQ9e3RoaXMucHJvcHMubXhFdmVudH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWN0aW9ucz17dGhpcy5wcm9wcy5yZWFjdGlvbnN9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkZvY3VzQ2hhbmdlPXt0aGlzLm9uRm9jdXNDaGFuZ2V9XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXk9XCJyZWFjdFwiXG4gICAgICAgICAgICAgICAgICAgIC8+KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChhbGxvd0NhbmNlbCkge1xuICAgICAgICAgICAgICAgIHRvb2xiYXJPcHRzLnB1c2goY2FuY2VsU2VuZGluZ0J1dHRvbik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRoZSBtZW51IGJ1dHRvbiBzaG91bGQgYmUgbGFzdCwgc28gZHVtcCBpdCB0aGVyZS5cbiAgICAgICAgICAgIHRvb2xiYXJPcHRzLnB1c2goPE9wdGlvbnNCdXR0b25cbiAgICAgICAgICAgICAgICBteEV2ZW50PXt0aGlzLnByb3BzLm14RXZlbnR9XG4gICAgICAgICAgICAgICAgZ2V0UmVwbHlUaHJlYWQ9e3RoaXMucHJvcHMuZ2V0UmVwbHlUaHJlYWR9XG4gICAgICAgICAgICAgICAgZ2V0VGlsZT17dGhpcy5wcm9wcy5nZXRUaWxlfVxuICAgICAgICAgICAgICAgIHBlcm1hbGlua0NyZWF0b3I9e3RoaXMucHJvcHMucGVybWFsaW5rQ3JlYXRvcn1cbiAgICAgICAgICAgICAgICBvbkZvY3VzQ2hhbmdlPXt0aGlzLm9uRm9jdXNDaGFuZ2V9XG4gICAgICAgICAgICAgICAga2V5PVwibWVudVwiXG4gICAgICAgICAgICAvPik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhcmlhLWxpdmU9b2ZmIHRvIG5vdCBoYXZlIHRoaXMgcmVhZCBvdXQgYXV0b21hdGljYWxseSBhcyBuYXZpZ2F0aW5nIGFyb3VuZCB0aW1lbGluZSwgZ2V0cyByZXBldGl0aXZlLlxuICAgICAgICByZXR1cm4gPFRvb2xiYXIgY2xhc3NOYW1lPVwibXhfTWVzc2FnZUFjdGlvbkJhclwiIGFyaWEtbGFiZWw9e190KFwiTWVzc2FnZSBBY3Rpb25zXCIpfSBhcmlhLWxpdmU9XCJvZmZcIj5cbiAgICAgICAgICAgIHt0b29sYmFyT3B0c31cbiAgICAgICAgPC9Ub29sYmFyPjtcbiAgICB9XG59XG4iXX0=