UNPKG

matrix-react-sdk

Version:
552 lines (428 loc) 63.6 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 _react = _interopRequireDefault(require("react")); var sdk = _interopRequireWildcard(require("../../../index")); var _languageHandler = require("../../../languageHandler"); var _propTypes = _interopRequireDefault(require("prop-types")); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var _model = _interopRequireDefault(require("../../../editor/model")); var _dom = require("../../../editor/dom"); var _serialize = require("../../../editor/serialize"); var _EventUtils = require("../../../utils/EventUtils"); var _deserialize = require("../../../editor/deserialize"); var _parts = require("../../../editor/parts"); var _EditorStateTransfer = _interopRequireDefault(require("../../../utils/EditorStateTransfer")); var _classnames = _interopRequireDefault(require("classnames")); var _event = require("matrix-js-sdk/src/models/event"); var _BasicMessageComposer = _interopRequireDefault(require("./BasicMessageComposer")); var _MatrixClientContext = _interopRequireDefault(require("../../../contexts/MatrixClientContext")); var _SlashCommands = require("../../../SlashCommands"); var _actions = require("../../../dispatcher/actions"); var _CountlyAnalytics = _interopRequireDefault(require("../../../CountlyAnalytics")); var _KeyBindingsManager = require("../../../KeyBindingsManager"); var _replaceableComponent = require("../../../utils/replaceableComponent"); var _SendHistoryManager = _interopRequireDefault(require("../../../SendHistoryManager")); var _Modal = _interopRequireDefault(require("../../../Modal")); var _dec, _class, _class2, _temp; function _isReply(mxEvent) { const relatesTo = mxEvent.getContent()["m.relates_to"]; const isReply = !!(relatesTo && relatesTo["m.in_reply_to"]); return isReply; } function getHtmlReplyFallback(mxEvent) { const html = mxEvent.getContent().formatted_body; if (!html) { return ""; } const rootNode = new DOMParser().parseFromString(html, "text/html").body; const mxReply = rootNode.querySelector("mx-reply"); return mxReply && mxReply.outerHTML || ""; } function getTextReplyFallback(mxEvent) { const body = mxEvent.getContent().body; const lines = body.split("\n").map(l => l.trim()); if (lines.length > 2 && lines[0].startsWith("> ") && lines[1].length === 0) { return `${lines[0]}\n\n`; } return ""; } function createEditContent(model, editedEvent) { const isEmote = (0, _serialize.containsEmote)(model); if (isEmote) { model = (0, _serialize.stripEmoteCommand)(model); } const isReply = _isReply(editedEvent); let plainPrefix = ""; let htmlPrefix = ""; if (isReply) { plainPrefix = getTextReplyFallback(editedEvent); htmlPrefix = getHtmlReplyFallback(editedEvent); } const body = (0, _serialize.textSerialize)(model); const newContent = { "msgtype": isEmote ? "m.emote" : "m.text", "body": body }; const contentBody = { msgtype: newContent.msgtype, body: `${plainPrefix} * ${body}` }; const formattedBody = (0, _serialize.htmlSerializeIfNeeded)(model, { forceHTML: isReply }); if (formattedBody) { newContent.format = "org.matrix.custom.html"; newContent.formatted_body = formattedBody; contentBody.format = newContent.format; contentBody.formatted_body = `${htmlPrefix} * ${formattedBody}`; } return Object.assign({ "m.new_content": newContent, "m.relates_to": { "rel_type": "m.replace", "event_id": editedEvent.getId() } }, contentBody); } let EditMessageComposer = (_dec = (0, _replaceableComponent.replaceableComponent)("views.rooms.EditMessageComposer"), _dec(_class = (_temp = _class2 = class EditMessageComposer extends _react.default.Component { constructor(props, context) { super(props, context); (0, _defineProperty2.default)(this, "_setEditorRef", ref => { this._editorRef = ref; }); (0, _defineProperty2.default)(this, "_onKeyDown", event => { // ignore any keypress while doing IME compositions if (this._editorRef.isComposing(event)) { return; } const action = (0, _KeyBindingsManager.getKeyBindingsManager)().getMessageComposerAction(event); switch (action) { case _KeyBindingsManager.MessageComposerAction.Send: this._sendEdit(); event.preventDefault(); break; case _KeyBindingsManager.MessageComposerAction.CancelEditing: this._cancelEdit(); break; case _KeyBindingsManager.MessageComposerAction.EditPrevMessage: { if (this._editorRef.isModified() || !this._editorRef.isCaretAtStart()) { return; } const previousEvent = (0, _EventUtils.findEditableEvent)(this._getRoom(), false, this.props.editState.getEvent().getId()); if (previousEvent) { _dispatcher.default.dispatch({ action: 'edit_event', event: previousEvent }); event.preventDefault(); } break; } case _KeyBindingsManager.MessageComposerAction.EditNextMessage: { if (this._editorRef.isModified() || !this._editorRef.isCaretAtEnd()) { return; } const nextEvent = (0, _EventUtils.findEditableEvent)(this._getRoom(), true, this.props.editState.getEvent().getId()); if (nextEvent) { _dispatcher.default.dispatch({ action: 'edit_event', event: nextEvent }); } else { _dispatcher.default.dispatch({ action: 'edit_event', event: null }); _dispatcher.default.fire(_actions.Action.FocusComposer); } event.preventDefault(); break; } } }); (0, _defineProperty2.default)(this, "_cancelEdit", () => { this._clearStoredEditorState(); _dispatcher.default.dispatch({ action: "edit_event", event: null }); _dispatcher.default.fire(_actions.Action.FocusComposer); }); (0, _defineProperty2.default)(this, "_sendEdit", async () => { const startTime = _CountlyAnalytics.default.getTimestamp(); const editedEvent = this.props.editState.getEvent(); const editContent = createEditContent(this.model, editedEvent); const newContent = editContent["m.new_content"]; let shouldSend = true; // If content is modified then send an updated event into the room if (this._isContentModified(newContent)) { const roomId = editedEvent.getRoomId(); if (!(0, _serialize.containsEmote)(this.model) && this._isSlashCommand()) { const [cmd, args, commandText] = this._getSlashCommand(); if (cmd) { if (cmd.category === _SlashCommands.CommandCategories.messages) { editContent["m.new_content"] = await this._runSlashCommand(cmd, args, roomId); } else { this._runSlashCommand(cmd, args, roomId); shouldSend = false; } } else { // ask the user if their unknown command should be sent as a message const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const { finished } = _Modal.default.createTrackedDialog("Unknown command", "", QuestionDialog, { title: (0, _languageHandler._t)("Unknown Command"), description: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("Unrecognised command: %(commandText)s", { commandText })), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("You can use <code>/help</code> to list available commands. " + "Did you mean to send this as a message?", {}, { code: t => /*#__PURE__*/_react.default.createElement("code", null, t) })), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("Hint: Begin your message with <code>//</code> to start it with a slash.", {}, { code: t => /*#__PURE__*/_react.default.createElement("code", null, t) }))), button: (0, _languageHandler._t)('Send as message') }); const [sendAnyway] = await finished; // if !sendAnyway bail to let the user edit the composer and try again if (!sendAnyway) return; } } if (shouldSend) { this._cancelPreviousPendingEdit(); const prom = this.context.sendMessage(roomId, editContent); this._clearStoredEditorState(); _dispatcher.default.dispatch({ action: "message_sent" }); _CountlyAnalytics.default.instance.trackSendMessage(startTime, prom, roomId, true, false, editContent); } } // close the event editing and focus composer _dispatcher.default.dispatch({ action: "edit_event", event: null }); _dispatcher.default.fire(_actions.Action.FocusComposer); }); (0, _defineProperty2.default)(this, "_onChange", () => { if (!this.state.saveDisabled || !this._editorRef || !this._editorRef.isModified()) { return; } this.setState({ saveDisabled: false }); }); this.model = null; this._editorRef = null; this.state = { saveDisabled: true }; this._createEditorModel(); window.addEventListener("beforeunload", this._saveStoredEditorState); } _getRoom() { return this.context.getRoom(this.props.editState.getEvent().getRoomId()); } get _editorRoomKey() { return `mx_edit_room_${this._getRoom().roomId}`; } get _editorStateKey() { return `mx_edit_state_${this.props.editState.getEvent().getId()}`; } get _shouldSaveStoredEditorState() { return localStorage.getItem(this._editorRoomKey) !== null; } _restoreStoredEditorState(partCreator) { const json = localStorage.getItem(this._editorStateKey); if (json) { try { const { parts: serializedParts } = JSON.parse(json); const parts = serializedParts.map(p => partCreator.deserializePart(p)); return parts; } catch (e) { console.error("Error parsing editing state: ", e); } } } _clearStoredEditorState() { localStorage.removeItem(this._editorRoomKey); localStorage.removeItem(this._editorStateKey); } _clearPreviousEdit() { if (localStorage.getItem(this._editorRoomKey)) { localStorage.removeItem(`mx_edit_state_${localStorage.getItem(this._editorRoomKey)}`); } } _saveStoredEditorState() { const item = _SendHistoryManager.default.createItem(this.model); this._clearPreviousEdit(); localStorage.setItem(this._editorRoomKey, this.props.editState.getEvent().getId()); localStorage.setItem(this._editorStateKey, JSON.stringify(item)); } _isSlashCommand() { const parts = this.model.parts; const firstPart = parts[0]; if (firstPart) { if (firstPart.type === "command" && firstPart.text.startsWith("/") && !firstPart.text.startsWith("//")) { return true; } if (firstPart.text.startsWith("/") && !firstPart.text.startsWith("//") && (firstPart.type === "plain" || firstPart.type === "pill-candidate")) { return true; } } return false; } _isContentModified(newContent) { // if nothing has changed then bail const oldContent = this.props.editState.getEvent().getContent(); if (!this._editorRef.isModified() || oldContent["msgtype"] === newContent["msgtype"] && oldContent["body"] === newContent["body"] && oldContent["format"] === newContent["format"] && oldContent["formatted_body"] === newContent["formatted_body"]) { return false; } return true; } _getSlashCommand() { const commandText = this.model.parts.reduce((text, part) => { // use mxid to textify user pills in a command if (part.type === "user-pill") { return text + part.resourceId; } return text + part.text; }, ""); const { cmd, args } = (0, _SlashCommands.getCommand)(commandText); return [cmd, args, commandText]; } async _runSlashCommand(cmd, args, roomId) { const result = cmd.run(roomId, args); let messageContent; let error = result.error; if (result.promise) { try { if (cmd.category === _SlashCommands.CommandCategories.messages) { messageContent = await result.promise; } else { await result.promise; } } catch (err) { error = err; } } if (error) { console.error("Command failure: %s", error); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); // assume the error is a server error when the command is async const isServerError = !!result.promise; const title = isServerError ? (0, _languageHandler._td)("Server error") : (0, _languageHandler._td)("Command error"); let errText; if (typeof error === 'string') { errText = error; } else if (error.message) { errText = error.message; } else { errText = (0, _languageHandler._t)("Server unavailable, overloaded, or something else went wrong."); } _Modal.default.createTrackedDialog(title, '', ErrorDialog, { title: (0, _languageHandler._t)(title), description: errText }); } else { console.log("Command success."); if (messageContent) return messageContent; } } _cancelPreviousPendingEdit() { const originalEvent = this.props.editState.getEvent(); const previousEdit = originalEvent.replacingEvent(); if (previousEdit && (previousEdit.status === _event.EventStatus.QUEUED || previousEdit.status === _event.EventStatus.NOT_SENT)) { this.context.cancelPendingEvent(previousEdit); } } componentWillUnmount() { // store caret and serialized parts in the // editorstate so it can be restored when the remote echo event tile gets rendered // in case we're currently editing a pending event const sel = document.getSelection(); let caret; if (sel.focusNode) { caret = (0, _dom.getCaretOffsetAndText)(this._editorRef, sel).caret; } const parts = this.model.serializeParts(); // if caret is undefined because for some reason there isn't a valid selection, // then when mounting the editor again with the same editor state, // it will set the cursor at the end. this.props.editState.setEditorState(caret, parts); window.removeEventListener("beforeunload", this._saveStoredEditorState); if (this._shouldSaveStoredEditorState) { this._saveStoredEditorState(); } } _createEditorModel() { const { editState } = this.props; const room = this._getRoom(); const partCreator = new _parts.CommandPartCreator(room, this.context); let parts; if (editState.hasEditorState()) { // if restoring state from a previous editor, // restore serialized parts from the state parts = editState.getSerializedParts().map(p => partCreator.deserializePart(p)); } else { //otherwise, either restore serialized parts from localStorage or parse the body of the event parts = this._restoreStoredEditorState(partCreator) || (0, _deserialize.parseEvent)(editState.getEvent(), partCreator); } this.model = new _model.default(parts, partCreator); this._saveStoredEditorState(); } _getInitialCaretPosition() { const { editState } = this.props; let caretPosition; if (editState.hasEditorState() && editState.getCaret()) { // if restoring state from a previous editor, // restore caret position from the state const caret = editState.getCaret(); caretPosition = this.model.positionForOffset(caret.offset, caret.atNodeEnd); } else { // otherwise, set it at the end caretPosition = this.model.getPositionAtEnd(); } return caretPosition; } render() { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); return /*#__PURE__*/_react.default.createElement("div", { className: (0, _classnames.default)("mx_EditMessageComposer", this.props.className), onKeyDown: this._onKeyDown }, /*#__PURE__*/_react.default.createElement(_BasicMessageComposer.default, { ref: this._setEditorRef, model: this.model, room: this._getRoom(), initialCaret: this.props.editState.getCaret(), label: (0, _languageHandler._t)("Edit message"), onChange: this._onChange }), /*#__PURE__*/_react.default.createElement("div", { className: "mx_EditMessageComposer_buttons" }, /*#__PURE__*/_react.default.createElement(AccessibleButton, { kind: "secondary", onClick: this._cancelEdit }, (0, _languageHandler._t)("Cancel")), /*#__PURE__*/_react.default.createElement(AccessibleButton, { kind: "primary", onClick: this._sendEdit, disabled: this.state.saveDisabled }, (0, _languageHandler._t)("Save")))); } }, (0, _defineProperty2.default)(_class2, "propTypes", { // the message event being edited editState: _propTypes.default.instanceOf(_EditorStateTransfer.default).isRequired }), (0, _defineProperty2.default)(_class2, "contextType", _MatrixClientContext.default), _temp)) || _class); exports.default = EditMessageComposer; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL3Jvb21zL0VkaXRNZXNzYWdlQ29tcG9zZXIuanMiXSwibmFtZXMiOlsiX2lzUmVwbHkiLCJteEV2ZW50IiwicmVsYXRlc1RvIiwiZ2V0Q29udGVudCIsImlzUmVwbHkiLCJnZXRIdG1sUmVwbHlGYWxsYmFjayIsImh0bWwiLCJmb3JtYXR0ZWRfYm9keSIsInJvb3ROb2RlIiwiRE9NUGFyc2VyIiwicGFyc2VGcm9tU3RyaW5nIiwiYm9keSIsIm14UmVwbHkiLCJxdWVyeVNlbGVjdG9yIiwib3V0ZXJIVE1MIiwiZ2V0VGV4dFJlcGx5RmFsbGJhY2siLCJsaW5lcyIsInNwbGl0IiwibWFwIiwibCIsInRyaW0iLCJsZW5ndGgiLCJzdGFydHNXaXRoIiwiY3JlYXRlRWRpdENvbnRlbnQiLCJtb2RlbCIsImVkaXRlZEV2ZW50IiwiaXNFbW90ZSIsInBsYWluUHJlZml4IiwiaHRtbFByZWZpeCIsIm5ld0NvbnRlbnQiLCJjb250ZW50Qm9keSIsIm1zZ3R5cGUiLCJmb3JtYXR0ZWRCb2R5IiwiZm9yY2VIVE1MIiwiZm9ybWF0IiwiT2JqZWN0IiwiYXNzaWduIiwiZ2V0SWQiLCJFZGl0TWVzc2FnZUNvbXBvc2VyIiwiUmVhY3QiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsInByb3BzIiwiY29udGV4dCIsInJlZiIsIl9lZGl0b3JSZWYiLCJldmVudCIsImlzQ29tcG9zaW5nIiwiYWN0aW9uIiwiZ2V0TWVzc2FnZUNvbXBvc2VyQWN0aW9uIiwiTWVzc2FnZUNvbXBvc2VyQWN0aW9uIiwiU2VuZCIsIl9zZW5kRWRpdCIsInByZXZlbnREZWZhdWx0IiwiQ2FuY2VsRWRpdGluZyIsIl9jYW5jZWxFZGl0IiwiRWRpdFByZXZNZXNzYWdlIiwiaXNNb2RpZmllZCIsImlzQ2FyZXRBdFN0YXJ0IiwicHJldmlvdXNFdmVudCIsIl9nZXRSb29tIiwiZWRpdFN0YXRlIiwiZ2V0RXZlbnQiLCJkaXMiLCJkaXNwYXRjaCIsIkVkaXROZXh0TWVzc2FnZSIsImlzQ2FyZXRBdEVuZCIsIm5leHRFdmVudCIsImZpcmUiLCJBY3Rpb24iLCJGb2N1c0NvbXBvc2VyIiwiX2NsZWFyU3RvcmVkRWRpdG9yU3RhdGUiLCJzdGFydFRpbWUiLCJDb3VudGx5QW5hbHl0aWNzIiwiZ2V0VGltZXN0YW1wIiwiZWRpdENvbnRlbnQiLCJzaG91bGRTZW5kIiwiX2lzQ29udGVudE1vZGlmaWVkIiwicm9vbUlkIiwiZ2V0Um9vbUlkIiwiX2lzU2xhc2hDb21tYW5kIiwiY21kIiwiYXJncyIsImNvbW1hbmRUZXh0IiwiX2dldFNsYXNoQ29tbWFuZCIsImNhdGVnb3J5IiwiQ29tbWFuZENhdGVnb3JpZXMiLCJtZXNzYWdlcyIsIl9ydW5TbGFzaENvbW1hbmQiLCJRdWVzdGlvbkRpYWxvZyIsInNkayIsImdldENvbXBvbmVudCIsImZpbmlzaGVkIiwiTW9kYWwiLCJjcmVhdGVUcmFja2VkRGlhbG9nIiwidGl0bGUiLCJkZXNjcmlwdGlvbiIsImNvZGUiLCJ0IiwiYnV0dG9uIiwic2VuZEFueXdheSIsIl9jYW5jZWxQcmV2aW91c1BlbmRpbmdFZGl0IiwicHJvbSIsInNlbmRNZXNzYWdlIiwiaW5zdGFuY2UiLCJ0cmFja1NlbmRNZXNzYWdlIiwic3RhdGUiLCJzYXZlRGlzYWJsZWQiLCJzZXRTdGF0ZSIsIl9jcmVhdGVFZGl0b3JNb2RlbCIsIndpbmRvdyIsImFkZEV2ZW50TGlzdGVuZXIiLCJfc2F2ZVN0b3JlZEVkaXRvclN0YXRlIiwiZ2V0Um9vbSIsIl9lZGl0b3JSb29tS2V5IiwiX2VkaXRvclN0YXRlS2V5IiwiX3Nob3VsZFNhdmVTdG9yZWRFZGl0b3JTdGF0ZSIsImxvY2FsU3RvcmFnZSIsImdldEl0ZW0iLCJfcmVzdG9yZVN0b3JlZEVkaXRvclN0YXRlIiwicGFydENyZWF0b3IiLCJqc29uIiwicGFydHMiLCJzZXJpYWxpemVkUGFydHMiLCJKU09OIiwicGFyc2UiLCJwIiwiZGVzZXJpYWxpemVQYXJ0IiwiZSIsImNvbnNvbGUiLCJlcnJvciIsInJlbW92ZUl0ZW0iLCJfY2xlYXJQcmV2aW91c0VkaXQiLCJpdGVtIiwiU2VuZEhpc3RvcnlNYW5hZ2VyIiwiY3JlYXRlSXRlbSIsInNldEl0ZW0iLCJzdHJpbmdpZnkiLCJmaXJzdFBhcnQiLCJ0eXBlIiwidGV4dCIsIm9sZENvbnRlbnQiLCJyZWR1Y2UiLCJwYXJ0IiwicmVzb3VyY2VJZCIsInJlc3VsdCIsInJ1biIsIm1lc3NhZ2VDb250ZW50IiwicHJvbWlzZSIsImVyciIsIkVycm9yRGlhbG9nIiwiaXNTZXJ2ZXJFcnJvciIsImVyclRleHQiLCJtZXNzYWdlIiwibG9nIiwib3JpZ2luYWxFdmVudCIsInByZXZpb3VzRWRpdCIsInJlcGxhY2luZ0V2ZW50Iiwic3RhdHVzIiwiRXZlbnRTdGF0dXMiLCJRVUVVRUQiLCJOT1RfU0VOVCIsImNhbmNlbFBlbmRpbmdFdmVudCIsImNvbXBvbmVudFdpbGxVbm1vdW50Iiwic2VsIiwiZG9jdW1lbnQiLCJnZXRTZWxlY3Rpb24iLCJjYXJldCIsImZvY3VzTm9kZSIsInNlcmlhbGl6ZVBhcnRzIiwic2V0RWRpdG9yU3RhdGUiLCJyZW1vdmVFdmVudExpc3RlbmVyIiwicm9vbSIsIkNvbW1hbmRQYXJ0Q3JlYXRvciIsImhhc0VkaXRvclN0YXRlIiwiZ2V0U2VyaWFsaXplZFBhcnRzIiwiRWRpdG9yTW9kZWwiLCJfZ2V0SW5pdGlhbENhcmV0UG9zaXRpb24iLCJjYXJldFBvc2l0aW9uIiwiZ2V0Q2FyZXQiLCJwb3NpdGlvbkZvck9mZnNldCIsIm9mZnNldCIsImF0Tm9kZUVuZCIsImdldFBvc2l0aW9uQXRFbmQiLCJyZW5kZXIiLCJBY2Nlc3NpYmxlQnV0dG9uIiwiY2xhc3NOYW1lIiwiX29uS2V5RG93biIsIl9zZXRFZGl0b3JSZWYiLCJfb25DaGFuZ2UiLCJQcm9wVHlwZXMiLCJpbnN0YW5jZU9mIiwiRWRpdG9yU3RhdGVUcmFuc2ZlciIsImlzUmVxdWlyZWQiLCJNYXRyaXhDbGllbnRDb250ZXh0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBZ0JB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QUFEO0FBQWtCLE1BQUEsSUFBSSxFQUFDLFNBQXZCO0FBQWlDLE1BQUEsT0FBTyxFQUFFLEtBQUtILFNBQS9DO0FBQTBELE1BQUEsUUFBUSxFQUFFLEtBQUtzRCxLQUFMLENBQVdDO0FBQS9FLE9BQ0sseUJBQUcsTUFBSCxDQURMLENBRkosQ0FUSSxDQUFSO0FBZ0JIOztBQWxXNEQsQyxzREFDMUM7QUFDZjtBQUNBOUMsRUFBQUEsU0FBUyxFQUFFaUksbUJBQVVDLFVBQVYsQ0FBcUJDLDRCQUFyQixFQUEwQ0M7QUFGdEMsQyx5REFLRUMsNEIiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMTkgTmV3IFZlY3RvciBMdGRcbkNvcHlyaWdodCAyMDE5IFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgKiBhcyBzZGsgZnJvbSAnLi4vLi4vLi4vaW5kZXgnO1xuaW1wb3J0IHtfdCwgX3RkfSBmcm9tICcuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXInO1xuaW1wb3J0IFByb3BUeXBlcyBmcm9tICdwcm9wLXR5cGVzJztcbmltcG9ydCBkaXMgZnJvbSAnLi4vLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyJztcbmltcG9ydCBFZGl0b3JNb2RlbCBmcm9tICcuLi8uLi8uLi9lZGl0b3IvbW9kZWwnO1xuaW1wb3J0IHtnZXRDYXJldE9mZnNldEFuZFRleHR9IGZyb20gJy4uLy4uLy4uL2VkaXRvci9kb20nO1xuaW1wb3J0IHtodG1sU2VyaWFsaXplSWZOZWVkZWQsIHRleHRTZXJpYWxpemUsIGNvbnRhaW5zRW1vdGUsIHN0cmlwRW1vdGVDb21tYW5kfSBmcm9tICcuLi8uLi8uLi9lZGl0b3Ivc2VyaWFsaXplJztcbmltcG9ydCB7ZmluZEVkaXRhYmxlRXZlbnR9IGZyb20gJy4uLy4uLy4uL3V0aWxzL0V2ZW50VXRpbHMnO1xuaW1wb3J0IHtwYXJzZUV2ZW50fSBmcm9tICcuLi8uLi8uLi9lZGl0b3IvZGVzZXJpYWxpemUnO1xuaW1wb3J0IHtDb21tYW5kUGFydENyZWF0b3J9IGZyb20gJy4uLy4uLy4uL2VkaXRvci9wYXJ0cyc7XG5pbXBvcnQgRWRpdG9yU3RhdGVUcmFuc2ZlciBmcm9tICcuLi8uLi8uLi91dGlscy9FZGl0b3JTdGF0ZVRyYW5zZmVyJztcbmltcG9ydCBjbGFzc05hbWVzIGZyb20gJ2NsYXNzbmFtZXMnO1xuaW1wb3J0IHtFdmVudFN0YXR1c30gZnJvbSAnbWF0cml4LWpzLXNkay9zcmMvbW9kZWxzL2V2ZW50JztcbmltcG9ydCBCYXNpY01lc3NhZ2VDb21wb3NlciBmcm9tIFwiLi9CYXNpY01lc3NhZ2VDb21wb3NlclwiO1xuaW1wb3J0IE1hdHJpeENsaWVudENvbnRleHQgZnJvbSBcIi4uLy4uLy4uL2NvbnRleHRzL01hdHJpeENsaWVudENvbnRleHRcIjtcbmltcG9ydCB7Q29tbWFuZENhdGVnb3JpZXMsIGdldENvbW1hbmR9IGZyb20gJy4uLy4uLy4uL1NsYXNoQ29tbWFuZHMnO1xuaW1wb3J0IHtBY3Rpb259IGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL2FjdGlvbnNcIjtcbmltcG9ydCBDb3VudGx5QW5hbHl0aWNzIGZyb20gXCIuLi8uLi8uLi9Db3VudGx5QW5hbHl0aWNzXCI7XG5pbXBvcnQge2dldEtleUJpbmRpbmdzTWFuYWdlciwgTWVzc2FnZUNvbXBvc2VyQWN0aW9ufSBmcm9tICcuLi8uLi8uLi9LZXlCaW5kaW5nc01hbmFnZXInO1xuaW1wb3J0IHtyZXBsYWNlYWJsZUNvbXBvbmVudH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL3JlcGxhY2VhYmxlQ29tcG9uZW50XCI7XG5pbXBvcnQgU2VuZEhpc3RvcnlNYW5hZ2VyIGZyb20gJy4uLy4uLy4uL1NlbmRIaXN0b3J5TWFuYWdlcic7XG5pbXBvcnQgTW9kYWwgZnJvbSAnLi4vLi4vLi4vTW9kYWwnO1xuXG5mdW5jdGlvbiBfaXNSZXBseShteEV2ZW50KSB7XG4gICAgY29uc3QgcmVsYXRlc1RvID0gbXhFdmVudC5nZXRDb250ZW50KClbXCJtLnJlbGF0ZXNfdG9cIl07XG4gICAgY29uc3QgaXNSZXBseSA9ICEhKHJlbGF0ZXNUbyAmJiByZWxhdGVzVG9bXCJtLmluX3JlcGx5X3RvXCJdKTtcbiAgICByZXR1cm4gaXNSZXBseTtcbn1cblxuZnVuY3Rpb24gZ2V0SHRtbFJlcGx5RmFsbGJhY2sobXhFdmVudCkge1xuICAgIGNvbnN0IGh0bWwgPSBteEV2ZW50LmdldENvbnRlbnQoKS5mb3JtYXR0ZWRfYm9keTtcbiAgICBpZiAoIWh0bWwpIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuICAgIGNvbnN0IHJvb3ROb2RlID0gbmV3IERPTVBhcnNlcigpLnBhcnNlRnJvbVN0cmluZyhodG1sLCBcInRleHQvaHRtbFwiKS5ib2R5O1xuICAgIGNvbnN0IG14UmVwbHkgPSByb290Tm9kZS5xdWVyeVNlbGVjdG9yKFwibXgtcmVwbHlcIik7XG4gICAgcmV0dXJuIChteFJlcGx5ICYmIG14UmVwbHkub3V0ZXJIVE1MKSB8fCBcIlwiO1xufVxuXG5mdW5jdGlvbiBnZXRUZXh0UmVwbHlGYWxsYmFjayhteEV2ZW50KSB7XG4gICAgY29uc3QgYm9keSA9IG14RXZlbnQuZ2V0Q29udGVudCgpLmJvZHk7XG4gICAgY29uc3QgbGluZXMgPSBib2R5LnNwbGl0KFwiXFxuXCIpLm1hcChsID0+IGwudHJpbSgpKTtcbiAgICBpZiAobGluZXMubGVuZ3RoID4gMiAmJiBsaW5lc1swXS5zdGFydHNXaXRoKFwiPiBcIikgJiYgbGluZXNbMV0ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBgJHtsaW5lc1swXX1cXG5cXG5gO1xuICAgIH1cbiAgICByZXR1cm4gXCJcIjtcbn1cblxuZnVuY3Rpb24gY3JlYXRlRWRpdENvbnRlbnQobW9kZWwsIGVkaXRlZEV2ZW50KSB7XG4gICAgY29uc3QgaXNFbW90ZSA9IGNvbnRhaW5zRW1vdGUobW9kZWwpO1xuICAgIGlmIChpc0Vtb3RlKSB7XG4gICAgICAgIG1vZGVsID0gc3RyaXBFbW90ZUNvbW1hbmQobW9kZWwpO1xuICAgIH1cbiAgICBjb25zdCBpc1JlcGx5ID0gX2lzUmVwbHkoZWRpdGVkRXZlbnQpO1xuICAgIGxldCBwbGFpblByZWZpeCA9IFwiXCI7XG4gICAgbGV0IGh0bWxQcmVmaXggPSBcIlwiO1xuXG4gICAgaWYgKGlzUmVwbHkpIHtcbiAgICAgICAgcGxhaW5QcmVmaXggPSBnZXRUZXh0UmVwbHlGYWxsYmFjayhlZGl0ZWRFdmVudCk7XG4gICAgICAgIGh0bWxQcmVmaXggPSBnZXRIdG1sUmVwbHlGYWxsYmFjayhlZGl0ZWRFdmVudCk7XG4gICAgfVxuXG4gICAgY29uc3QgYm9keSA9IHRleHRTZXJpYWxpemUobW9kZWwpO1xuXG4gICAgY29uc3QgbmV3Q29udGVudCA9IHtcbiAgICAgICAgXCJtc2d0eXBlXCI6IGlzRW1vdGUgPyBcIm0uZW1vdGVcIiA6IFwibS50ZXh0XCIsXG4gICAgICAgIFwiYm9keVwiOiBib2R5LFxuICAgIH07XG4gICAgY29uc3QgY29udGVudEJvZHkgPSB7XG4gICAgICAgIG1zZ3R5cGU6IG5ld0NvbnRlbnQubXNndHlwZSxcbiAgICAgICAgYm9keTogYCR7cGxhaW5QcmVmaXh9ICogJHtib2R5fWAsXG4gICAgfTtcblxuICAgIGNvbnN0IGZvcm1hdHRlZEJvZHkgPSBodG1sU2VyaWFsaXplSWZOZWVkZWQobW9kZWwsIHtmb3JjZUhUTUw6IGlzUmVwbHl9KTtcbiAgICBpZiAoZm9ybWF0dGVkQm9keSkge1xuICAgICAgICBuZXdDb250ZW50LmZvcm1hdCA9IFwib3JnLm1hdHJpeC5jdXN0b20uaHRtbFwiO1xuICAgICAgICBuZXdDb250ZW50LmZvcm1hdHRlZF9ib2R5ID0gZm9ybWF0dGVkQm9keTtcbiAgICAgICAgY29udGVudEJvZHkuZm9ybWF0ID0gbmV3Q29udGVudC5mb3JtYXQ7XG4gICAgICAgIGNvbnRlbnRCb2R5LmZvcm1hdHRlZF9ib2R5ID0gYCR7aHRtbFByZWZpeH0gKiAke2Zvcm1hdHRlZEJvZHl9YDtcbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7XG4gICAgICAgIFwibS5uZXdfY29udGVudFwiOiBuZXdDb250ZW50LFxuICAgICAgICBcIm0ucmVsYXRlc190b1wiOiB7XG4gICAgICAgICAgICBcInJlbF90eXBlXCI6IFwibS5yZXBsYWNlXCIsXG4gICAgICAgICAgICBcImV2ZW50X2lkXCI6IGVkaXRlZEV2ZW50LmdldElkKCksXG4gICAgICAgIH0sXG4gICAgfSwgY29udGVudEJvZHkpO1xufVxuXG5AcmVwbGFjZWFibGVDb21wb25lbnQoXCJ2aWV3cy5yb29tcy5FZGl0TWVzc2FnZUNvbXBvc2VyXCIpXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFZGl0TWVzc2FnZUNvbXBvc2VyIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50IHtcbiAgICBzdGF0aWMgcHJvcFR5cGVzID0ge1xuICAgICAgICAvLyB0aGUgbWVzc2FnZSBldmVudCBiZWluZyBlZGl0ZWRcbiAgICAgICAgZWRpdFN0YXRlOiBQcm9wVHlwZXMuaW5zdGFuY2VPZihFZGl0b3JTdGF0ZVRyYW5zZmVyKS5pc1JlcXVpcmVkLFxuICAgIH07XG5cbiAgICBzdGF0aWMgY29udGV4dFR5cGUgPSBNYXRyaXhDbGllbnRDb250ZXh0O1xuXG4gICAgY29uc3RydWN0b3IocHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgc3VwZXIocHJvcHMsIGNvbnRleHQpO1xuICAgICAgICB0aGlzLm1vZGVsID0gbnVsbDtcbiAgICAgICAgdGhpcy5fZWRpdG9yUmVmID0gbnVsbDtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgc2F2ZURpc2FibGVkOiB0cnVlLFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLl9jcmVhdGVFZGl0b3JNb2RlbCgpO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImJlZm9yZXVubG9hZFwiLCB0aGlzLl9zYXZlU3RvcmVkRWRpdG9yU3RhdGUpO1xuICAgIH1cblxuICAgIF9zZXRFZGl0b3JSZWYgPSByZWYgPT4ge1xuICAgICAgICB0aGlzLl9lZGl0b3JSZWYgPSByZWY7XG4gICAgfTtcblxuICAgIF9nZXRSb29tKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0LmdldFJvb20odGhpcy5wcm9wcy5lZGl0U3RhdGUuZ2V0RXZlbnQoKS5nZXRSb29tSWQoKSk7XG4gICAgfVxuXG4gICAgX29uS2V5RG93biA9IChldmVudCkgPT4ge1xuICAgICAgICAvLyBpZ25vcmUgYW55IGtleXByZXNzIHdoaWxlIGRvaW5nIElNRSBjb21wb3NpdGlvbnNcbiAgICAgICAgaWYgKHRoaXMuX2VkaXRvclJlZi5pc0NvbXBvc2luZyhldmVudCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhY3Rpb24gPSBnZXRLZXlCaW5kaW5nc01hbmFnZXIoKS5nZXRNZXNzYWdlQ29tcG9zZXJBY3Rpb24oZXZlbnQpO1xuICAgICAgICBzd2l0Y2ggKGFjdGlvbikge1xuICAgICAgICAgICAgY2FzZSBNZXNzYWdlQ29tcG9zZXJBY3Rpb24uU2VuZDpcbiAgICAgICAgICAgICAgICB0aGlzLl9zZW5kRWRpdCgpO1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VDb21wb3NlckFjdGlvbi5DYW5jZWxFZGl0aW5nOlxuICAgICAgICAgICAgICAgIHRoaXMuX2NhbmNlbEVkaXQoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgTWVzc2FnZUNvbXBvc2VyQWN0aW9uLkVkaXRQcmV2TWVzc2FnZToge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9lZGl0b3JSZWYuaXNNb2RpZmllZCgpIHx8ICF0aGlzLl9lZGl0b3JSZWYuaXNDYXJldEF0U3RhcnQoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzRXZlbnQgPSBmaW5kRWRpdGFibGVFdmVudCh0aGlzLl9nZXRSb29tKCksIGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnByb3BzLmVkaXRTdGF0ZS5nZXRFdmVudCgpLmdldElkKCkpO1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c0V2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGRpcy5kaXNwYXRjaCh7YWN0aW9uOiAnZWRpdF9ldmVudCcsIGV2ZW50OiBwcmV2aW91c0V2ZW50fSk7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBNZXNzYWdlQ29tcG9zZXJBY3Rpb24uRWRpdE5leHRNZXNzYWdlOiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2VkaXRvclJlZi5pc01vZGlmaWVkKCkgfHwgIXRoaXMuX2VkaXRvclJlZi5pc0NhcmV0QXRFbmQoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IG5leHRFdmVudCA9IGZpbmRFZGl0YWJsZUV2ZW50KHRoaXMuX2dldFJvb20oKSwgdHJ1ZSwgdGhpcy5wcm9wcy5lZGl0U3RhdGUuZ2V0RXZlbnQoKS5nZXRJZCgpKTtcbiAgICAgICAgICAgICAgICBpZiAobmV4dEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGRpcy5kaXNwYXRjaCh7YWN0aW9uOiAnZWRpdF9ldmVudCcsIGV2ZW50OiBuZXh0RXZlbnR9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkaXMuZGlzcGF0Y2goe2FjdGlvbjogJ2VkaXRfZXZlbnQnLCBldmVudDogbnVsbH0pO1xuICAgICAgICAgICAgICAgICAgICBkaXMuZmlyZShBY3Rpb24uRm9jdXNDb21wb3Nlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXQgX2VkaXRvclJvb21LZXkoKSB7XG4gICAgICAgIHJldHVybiBgbXhfZWRpdF9yb29tXyR7dGhpcy5fZ2V0Um9vbSgpLnJvb21JZH1gO1xuICAgIH1cblxuICAgIGdldCBfZWRpdG9yU3RhdGVLZXkoKSB7XG4gICAgICAgIHJldHVybiBgbXhfZWRpdF9zdGF0ZV8ke3RoaXMucHJvcHMuZWRpdFN0YXRlLmdldEV2ZW50KCkuZ2V0SWQoKX1gO1xuICAgIH1cblxuICAgIF9jYW5jZWxFZGl0ID0gKCkgPT4ge1xuICAgICAgICB0aGlzLl9jbGVhclN0b3JlZEVkaXRvclN0YXRlKCk7XG4gICAgICAgIGRpcy5kaXNwYXRjaCh7YWN0aW9uOiBcImVkaXRfZXZlbnRcIiwgZXZlbnQ6IG51bGx9KTtcbiAgICAgICAgZGlzLmZpcmUoQWN0aW9uLkZvY3VzQ29tcG9zZXIpO1xuICAgIH1cblxuICAgIGdldCBfc2hvdWxkU2F2ZVN0b3JlZEVkaXRvclN0YXRlKCkge1xuICAgICAgICByZXR1cm4gbG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5fZWRpdG9yUm9vbUtleSkgIT09IG51bGw7XG4gICAgfVxuXG4gICAgX3Jlc3RvcmVTdG9yZWRFZGl0b3JTdGF0ZShwYXJ0Q3JlYXRvcikge1xuICAgICAgICBjb25zdCBqc29uID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5fZWRpdG9yU3RhdGVLZXkpO1xuICAgICAgICBpZiAoanNvbikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCB7cGFydHM6IHNlcmlhbGl6ZWRQYXJ0c30gPSBKU09OLnBhcnNlKGpzb24pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcnRzID0gc2VyaWFsaXplZFBhcnRzLm1hcChwID0+IHBhcnRDcmVhdG9yLmRlc2VyaWFsaXplUGFydChwKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnRzO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBwYXJzaW5nIGVkaXRpbmcgc3RhdGU6IFwiLCBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIF9jbGVhclN0b3JlZEVkaXRvclN0YXRlKCkge1xuICAgICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbSh0aGlzLl9lZGl0b3JSb29tS2V5KTtcbiAgICAgICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0odGhpcy5fZWRpdG9yU3RhdGVLZXkpO1xuICAgIH1cblxuICAgIF9jbGVhclByZXZpb3VzRWRpdCgpIHtcbiAgICAgICAgaWYgKGxvY2FsU3RvcmFnZS5nZXRJdGVtKHRoaXMuX2VkaXRvclJvb21LZXkpKSB7XG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShgbXhfZWRpdF9zdGF0ZV8ke2xvY2FsU3RvcmFnZS5nZXRJdGVtKHRoaXMuX2VkaXRvclJvb21LZXkpfWApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgX3NhdmVTdG9yZWRFZGl0b3JTdGF0ZSgpIHtcbiAgICAgICAgY29uc3QgaXRlbSA9IFNlbmRIaXN0b3J5TWFuYWdlci5jcmVhdGVJdGVtKHRoaXMubW9kZWwpO1xuICAgICAgICB0aGlzLl9jbGVhclByZXZpb3VzRWRpdCgpO1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSh0aGlzLl9lZGl0b3JSb29tS2V5LCB0aGlzLnByb3BzLmVkaXRTdGF0ZS5nZXRFdmVudCgpLmdldElkKCkpO1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSh0aGlzLl9lZGl0b3JTdGF0ZUtleSwgSlNPTi5zdHJpbmdpZnkoaXRlbSkp