matrix-react-sdk
Version:
SDK for matrix.org using React
583 lines (461 loc) • 78.1 kB
JavaScript
"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 = _interopRequireWildcard(require("react"));
var _reactDom = _interopRequireDefault(require("react-dom"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _highlight = _interopRequireDefault(require("highlight.js"));
var HtmlUtils = _interopRequireWildcard(require("../../../HtmlUtils"));
var _DateUtils = require("../../../DateUtils");
var sdk = _interopRequireWildcard(require("../../../index"));
var _Modal = _interopRequireDefault(require("../../../Modal"));
var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher"));
var _languageHandler = require("../../../languageHandler");
var ContextMenu = _interopRequireWildcard(require("../../structures/ContextMenu"));
var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore"));
var _ReplyThread = _interopRequireDefault(require("../elements/ReplyThread"));
var _pillify = require("../../../utils/pillify");
var _IntegrationManagers = require("../../../integrations/IntegrationManagers");
var _Permalinks = require("../../../utils/permalinks/Permalinks");
var _strings = require("../../../utils/strings");
var _AccessibleTooltipButton = _interopRequireDefault(require("../elements/AccessibleTooltipButton"));
var _replaceableComponent = require("../../../utils/replaceableComponent");
var _dec, _class, _class2, _temp;
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
let TextualBody = (_dec = (0, _replaceableComponent.replaceableComponent)("views.messages.TextualBody"), _dec(_class = (_temp = _class2 = class TextualBody extends _react.default.Component {
constructor(props) {
super(props);
(0, _defineProperty2.default)(this, "onCancelClick", event => {
this.setState({
widgetHidden: true
}); // FIXME: persist this somewhere smarter than local storage
if (global.localStorage) {
global.localStorage.setItem("hide_preview_" + this.props.mxEvent.getId(), "1");
}
this.forceUpdate();
});
(0, _defineProperty2.default)(this, "onEmoteSenderClick", event => {
const mxEvent = this.props.mxEvent;
_dispatcher.default.dispatch({
action: 'insert_mention',
user_id: mxEvent.getSender()
});
});
(0, _defineProperty2.default)(this, "getEventTileOps", () => ({
isWidgetHidden: () => {
return this.state.widgetHidden;
},
unhideWidget: () => {
this.setState({
widgetHidden: false
});
if (global.localStorage) {
global.localStorage.removeItem("hide_preview_" + this.props.mxEvent.getId());
}
}
}));
(0, _defineProperty2.default)(this, "onStarterLinkClick", (starterLink, ev) => {
ev.preventDefault(); // We need to add on our scalar token to the starter link, but we may not have one!
// In addition, we can't fetch one on click and then go to it immediately as that
// is then treated as a popup!
// We can get around this by fetching one now and showing a "confirmation dialog" (hurr hurr)
// which requires the user to click through and THEN we can open the link in a new tab because
// the window.open command occurs in the same stack frame as the onClick callback.
const managers = _IntegrationManagers.IntegrationManagers.sharedInstance();
if (!managers.hasManager()) {
managers.openNoManagerDialog();
return;
} // Go fetch a scalar token
const integrationManager = managers.getPrimaryManager();
const scalarClient = integrationManager.getScalarClient();
scalarClient.connect().then(() => {
const completeUrl = scalarClient.getStarterLink(starterLink);
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const integrationsUrl = integrationManager.uiUrl;
_Modal.default.createTrackedDialog('Add an integration', '', QuestionDialog, {
title: (0, _languageHandler._t)("Add an Integration"),
description: /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("You are about to be taken to a third-party site so you can " + "authenticate your account for use with %(integrationsUrl)s. " + "Do you wish to continue?", {
integrationsUrl: integrationsUrl
})),
button: (0, _languageHandler._t)("Continue"),
onFinished(confirmed) {
if (!confirmed) {
return;
}
const width = window.screen.width > 1024 ? 1024 : window.screen.width;
const height = window.screen.height > 800 ? 800 : window.screen.height;
const left = (window.screen.width - width) / 2;
const top = (window.screen.height - height) / 2;
const features = `height=${height}, width=${width}, top=${top}, left=${left},`;
const wnd = window.open(completeUrl, '_blank', features);
wnd.opener = null;
}
});
});
});
(0, _defineProperty2.default)(this, "_openHistoryDialog", async () => {
const MessageEditHistoryDialog = sdk.getComponent("views.dialogs.MessageEditHistoryDialog");
_Modal.default.createDialog(MessageEditHistoryDialog, {
mxEvent: this.props.mxEvent
});
});
this._content = /*#__PURE__*/(0, _react.createRef)();
this.state = {
// the URLs (if any) to be previewed with a LinkPreviewWidget
// inside this TextualBody.
links: [],
// track whether the preview widget is hidden
widgetHidden: false
};
}
componentDidMount() {
this._unmounted = false;
this._pills = [];
if (!this.props.editState) {
this._applyFormatting();
}
}
_applyFormatting() {
const showLineNumbers = _SettingsStore.default.getValue("showCodeLineNumbers");
this.activateSpoilers([this._content.current]); // pillifyLinks BEFORE linkifyElement because plain room/user URLs in the composer
// are still sent as plaintext URLs. If these are ever pillified in the composer,
// we should be pillify them here by doing the linkifying BEFORE the pillifying.
(0, _pillify.pillifyLinks)([this._content.current], this.props.mxEvent, this._pills);
HtmlUtils.linkifyElement(this._content.current);
this.calculateUrlPreview();
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") {
// Handle expansion and add buttons
const pres = _reactDom.default.findDOMNode(this).getElementsByTagName("pre");
if (pres.length > 0) {
for (let i = 0; i < pres.length; i++) {
// If there already is a div wrapping the codeblock we want to skip this.
// This happens after the codeblock was edited.
if (pres[i].parentNode.className == "mx_EventTile_pre_container") continue; // Add code element if it's missing since we depend on it
if (pres[i].getElementsByTagName("code").length == 0) {
this._addCodeElement(pres[i]);
} // Wrap a div around <pre> so that the copy button can be correctly positioned
// when the <pre> overflows and is scrolled horizontally.
const div = this._wrapInDiv(pres[i]);
this._handleCodeBlockExpansion(pres[i]);
this._addCodeExpansionButton(div, pres[i]);
this._addCodeCopyButton(div);
if (showLineNumbers) {
this._addLineNumbers(pres[i]);
}
}
} // Highlight code
const codes = _reactDom.default.findDOMNode(this).getElementsByTagName("code");
if (codes.length > 0) {
// Do this asynchronously: parsing code takes time and we don't
// need to block the DOM update on it.
setTimeout(() => {
if (this._unmounted) return;
for (let i = 0; i < codes.length; i++) {
// If the code already has the hljs class we want to skip this.
// This happens after the codeblock was edited.
if (codes[i].className.includes("hljs")) continue;
this._highlightCode(codes[i]);
}
}, 10);
}
}
}
_addCodeElement(pre) {
const code = document.createElement("code");
code.append(...pre.childNodes);
pre.appendChild(code);
}
_addCodeExpansionButton(div, pre) {
// Calculate how many percent does the pre element take up.
// If it's less than 30% we don't add the expansion button.
const percentageOfViewport = pre.offsetHeight / window.innerHeight * 100;
if (percentageOfViewport < 30) return;
const button = document.createElement("span");
button.className = "mx_EventTile_button ";
if (pre.className == "mx_EventTile_collapsedCodeBlock") {
button.className += "mx_EventTile_expandButton";
} else {
button.className += "mx_EventTile_collapseButton";
}
button.onclick = async () => {
button.className = "mx_EventTile_button ";
if (pre.className == "mx_EventTile_collapsedCodeBlock") {
pre.className = "";
button.className += "mx_EventTile_collapseButton";
} else {
pre.className = "mx_EventTile_collapsedCodeBlock";
button.className += "mx_EventTile_expandButton";
} // By expanding/collapsing we changed
// the height, therefore we call this
this.props.onHeightChanged();
};
div.appendChild(button);
}
_addCodeCopyButton(div) {
const button = document.createElement("span");
button.className = "mx_EventTile_button mx_EventTile_copyButton "; // Check if expansion button exists. If so
// we put the copy button to the bottom
const expansionButtonExists = div.getElementsByClassName("mx_EventTile_button");
if (expansionButtonExists.length > 0) button.className += "mx_EventTile_buttonBottom";
button.onclick = async () => {
const copyCode = button.parentNode.getElementsByTagName("code")[0];
const successful = await (0, _strings.copyPlaintext)(copyCode.textContent);
const buttonRect = button.getBoundingClientRect();
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const {
close
} = ContextMenu.createMenu(GenericTextContextMenu, _objectSpread(_objectSpread({}, (0, ContextMenu.toRightOf)(buttonRect, 2)), {}, {
message: successful ? (0, _languageHandler._t)('Copied!') : (0, _languageHandler._t)('Failed to copy')
}));
button.onmouseleave = close;
};
div.appendChild(button);
}
_wrapInDiv(pre) {
const div = document.createElement("div");
div.className = "mx_EventTile_pre_container"; // Insert containing div in place of <pre> block
pre.parentNode.replaceChild(div, pre); // Append <pre> block and copy button to container
div.appendChild(pre);
return div;
}
_handleCodeBlockExpansion(pre) {
if (!_SettingsStore.default.getValue("expandCodeByDefault")) {
pre.className = "mx_EventTile_collapsedCodeBlock";
}
}
_addLineNumbers(pre) {
// Calculate number of lines in pre
const number = pre.innerHTML.replace(/\n(<\/code>)?$/, "").split(/\n/).length;
pre.innerHTML = '<span class="mx_EventTile_lineNumbers"></span>' + pre.innerHTML + '<span></span>';
const lineNumbers = pre.getElementsByClassName("mx_EventTile_lineNumbers")[0]; // Iterate through lines starting with 1 (number of the first line is 1)
for (let i = 1; i <= number; i++) {
lineNumbers.innerHTML += '<span class="mx_EventTile_lineNumber">' + i + '</span>';
}
}
_highlightCode(code) {
if (_SettingsStore.default.getValue("enableSyntaxHighlightLanguageDetection")) {
_highlight.default.highlightBlock(code);
} else {
// Only syntax highlight if there's a class starting with language-
const classes = code.className.split(/\s+/).filter(function (cl) {
return cl.startsWith('language-') && !cl.startsWith('language-_');
});
if (classes.length != 0) {
_highlight.default.highlightBlock(code);
}
}
}
componentDidUpdate(prevProps) {
if (!this.props.editState) {
const stoppedEditing = prevProps.editState && !this.props.editState;
const messageWasEdited = prevProps.replacingEventId !== this.props.replacingEventId;
if (messageWasEdited || stoppedEditing) {
this._applyFormatting();
}
}
}
componentWillUnmount() {
this._unmounted = true;
(0, _pillify.unmountPills)(this._pills);
}
shouldComponentUpdate(nextProps, nextState) {
//console.info("shouldComponentUpdate: ShowUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
// exploit that events are immutable :)
return nextProps.mxEvent.getId() !== this.props.mxEvent.getId() || nextProps.highlights !== this.props.highlights || nextProps.replacingEventId !== this.props.replacingEventId || nextProps.highlightLink !== this.props.highlightLink || nextProps.showUrlPreview !== this.props.showUrlPreview || nextProps.editState !== this.props.editState || nextState.links !== this.state.links || nextState.widgetHidden !== this.state.widgetHidden;
}
calculateUrlPreview() {
//console.info("calculateUrlPreview: ShowUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
if (this.props.showUrlPreview) {
// pass only the first child which is the event tile otherwise this recurses on edited events
let links = this.findLinks([this._content.current]);
if (links.length) {
// de-dup the links (but preserve ordering)
const seen = new Set();
links = links.filter(link => {
if (seen.has(link)) return false;
seen.add(link);
return true;
});
this.setState({
links: links
}); // lazy-load the hidden state of the preview widget from localstorage
if (global.localStorage) {
const hidden = global.localStorage.getItem("hide_preview_" + this.props.mxEvent.getId());
this.setState({
widgetHidden: hidden
});
}
} else if (this.state.links.length) {
this.setState({
links: []
});
}
}
}
activateSpoilers(nodes) {
let node = nodes[0];
while (node) {
if (node.tagName === "SPAN" && typeof node.getAttribute("data-mx-spoiler") === "string") {
const spoilerContainer = document.createElement('span');
const reason = node.getAttribute("data-mx-spoiler");
const Spoiler = sdk.getComponent('elements.Spoiler');
node.removeAttribute("data-mx-spoiler"); // we don't want to recurse
const spoiler = /*#__PURE__*/_react.default.createElement(Spoiler, {
reason: reason,
contentHtml: node.outerHTML
});
_reactDom.default.render(spoiler, spoilerContainer);
node.parentNode.replaceChild(spoilerContainer, node);
node = spoilerContainer;
}
if (node.childNodes && node.childNodes.length) {
this.activateSpoilers(node.childNodes);
}
node = node.nextSibling;
}
}
findLinks(nodes) {
let links = [];
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (node.tagName === "A" && node.getAttribute("href")) {
if (this.isLinkPreviewable(node)) {
links.push(node.getAttribute("href"));
}
} else if (node.tagName === "PRE" || node.tagName === "CODE" || node.tagName === "BLOCKQUOTE") {
continue;
} else if (node.children && node.children.length) {
links = links.concat(this.findLinks(node.children));
}
}
return links;
}
isLinkPreviewable(node) {
// don't try to preview relative links
if (!node.getAttribute("href").startsWith("http://") && !node.getAttribute("href").startsWith("https://")) {
return false;
} // as a random heuristic to avoid highlighting things like "foo.pl"
// we require the linked text to either include a / (either from http://
// or from a full foo.bar/baz style schemeless URL) - or be a markdown-style
// link, in which case we check the target text differs from the link value.
// TODO: make this configurable?
if (node.textContent.indexOf("/") > -1) {
return true;
} else {
const url = node.getAttribute("href");
const host = url.match(/^https?:\/\/(.*?)(\/|$)/)[1]; // never preview permalinks (if anything we should give a smart
// preview of the room/user they point to: nobody needs to be reminded
// what the matrix.to site looks like).
if ((0, _Permalinks.isPermalinkHost)(host)) return false;
if (node.textContent.toLowerCase().trim().startsWith(host.toLowerCase())) {
// it's a "foo.pl" style link
return false;
} else {
// it's a [foo bar](http://foo.com) style link
return true;
}
}
}
_renderEditedMarker() {
const date = this.props.mxEvent.replacingEventDate();
const dateString = date && (0, _DateUtils.formatDate)(date);
const tooltip = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_Tooltip_title"
}, (0, _languageHandler._t)("Edited at %(date)s", {
date: dateString
})), /*#__PURE__*/_react.default.createElement("div", {
className: "mx_Tooltip_sub"
}, (0, _languageHandler._t)("Click to view edits")));
return /*#__PURE__*/_react.default.createElement(_AccessibleTooltipButton.default, {
className: "mx_EventTile_edited",
onClick: this._openHistoryDialog,
title: (0, _languageHandler._t)("Edited at %(date)s. Click to view edits.", {
date: dateString
}),
tooltip: tooltip
}, /*#__PURE__*/_react.default.createElement("span", null, `(${(0, _languageHandler._t)("edited")})`));
}
render() {
if (this.props.editState) {
const EditMessageComposer = sdk.getComponent('rooms.EditMessageComposer');
return /*#__PURE__*/_react.default.createElement(EditMessageComposer, {
editState: this.props.editState,
className: "mx_EventTile_content"
});
}
const mxEvent = this.props.mxEvent;
const content = mxEvent.getContent(); // only strip reply if this is the original replying event, edits thereafter do not have the fallback
const stripReply = !mxEvent.replacingEvent() && _ReplyThread.default.getParentEventId(mxEvent);
let body = HtmlUtils.bodyToHtml(content, this.props.highlights, {
disableBigEmoji: content.msgtype === "m.emote" || !_SettingsStore.default.getValue('TextualBody.enableBigEmoji'),
// Part of Replies fallback support
stripReplyFallback: stripReply,
ref: this._content
});
if (this.props.replacingEventId) {
body = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, body, this._renderEditedMarker());
}
if (this.props.highlightLink) {
body = /*#__PURE__*/_react.default.createElement("a", {
href: this.props.highlightLink
}, body);
} else if (content.data && typeof content.data["org.matrix.neb.starter_link"] === "string") {
body = /*#__PURE__*/_react.default.createElement("a", {
href: "#",
onClick: this.onStarterLinkClick.bind(this, content.data["org.matrix.neb.starter_link"])
}, body);
}
let widgets;
if (this.state.links.length && !this.state.widgetHidden && this.props.showUrlPreview) {
const LinkPreviewWidget = sdk.getComponent('rooms.LinkPreviewWidget');
widgets = this.state.links.map(link => {
return /*#__PURE__*/_react.default.createElement(LinkPreviewWidget, {
key: link,
link: link,
mxEvent: this.props.mxEvent,
onCancelClick: this.onCancelClick,
onHeightChanged: this.props.onHeightChanged
});
});
}
switch (content.msgtype) {
case "m.emote":
return /*#__PURE__*/_react.default.createElement("span", {
className: "mx_MEmoteBody mx_EventTile_content"
}, "*\xA0", /*#__PURE__*/_react.default.createElement("span", {
className: "mx_MEmoteBody_sender",
onClick: this.onEmoteSenderClick
}, mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender()), "\xA0", body, widgets);
case "m.notice":
return /*#__PURE__*/_react.default.createElement("span", {
className: "mx_MNoticeBody mx_EventTile_content"
}, body, widgets);
default:
// including "m.text"
return /*#__PURE__*/_react.default.createElement("span", {
className: "mx_MTextBody mx_EventTile_content"
}, body, widgets);
}
}
}, (0, _defineProperty2.default)(_class2, "propTypes", {
/* the MatrixEvent to show */
mxEvent: _propTypes.default.object.isRequired,
/* a list of words to highlight */
highlights: _propTypes.default.array,
/* link URL for the highlights */
highlightLink: _propTypes.default.string,
/* should show URL previews for this event */
showUrlPreview: _propTypes.default.bool,
/* callback for when our widget has loaded */
onHeightChanged: _propTypes.default.func,
/* the shape of the tile, used */
tileShape: _propTypes.default.string
}), _temp)) || _class);
exports.default = TextualBody;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL21lc3NhZ2VzL1RleHR1YWxCb2R5LmpzIl0sIm5hbWVzIjpbIlRleHR1YWxCb2R5IiwiUmVhY3QiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsInByb3BzIiwiZXZlbnQiLCJzZXRTdGF0ZSIsIndpZGdldEhpZGRlbiIsImdsb2JhbCIsImxvY2FsU3RvcmFnZSIsInNldEl0ZW0iLCJteEV2ZW50IiwiZ2V0SWQiLCJmb3JjZVVwZGF0ZSIsImRpcyIsImRpc3BhdGNoIiwiYWN0aW9uIiwidXNlcl9pZCIsImdldFNlbmRlciIsImlzV2lkZ2V0SGlkZGVuIiwic3RhdGUiLCJ1bmhpZGVXaWRnZXQiLCJyZW1vdmVJdGVtIiwic3RhcnRlckxpbmsiLCJldiIsInByZXZlbnREZWZhdWx0IiwibWFuYWdlcnMiLCJJbnRlZ3JhdGlvbk1hbmFnZXJzIiwic2hhcmVkSW5zdGFuY2UiLCJoYXNNYW5hZ2VyIiwib3Blbk5vTWFuYWdlckRpYWxvZyIsImludGVncmF0aW9uTWFuYWdlciIsImdldFByaW1hcnlNYW5hZ2VyIiwic2NhbGFyQ2xpZW50IiwiZ2V0U2NhbGFyQ2xpZW50IiwiY29ubmVjdCIsInRoZW4iLCJjb21wbGV0ZVVybCIsImdldFN0YXJ0ZXJMaW5rIiwiUXVlc3Rpb25EaWFsb2ciLCJzZGsiLCJnZXRDb21wb25lbnQiLCJpbnRlZ3JhdGlvbnNVcmwiLCJ1aVVybCIsIk1vZGFsIiwiY3JlYXRlVHJhY2tlZERpYWxvZyIsInRpdGxlIiwiZGVzY3JpcHRpb24iLCJidXR0b24iLCJvbkZpbmlzaGVkIiwiY29uZmlybWVkIiwid2lkdGgiLCJ3aW5kb3ciLCJzY3JlZW4iLCJoZWlnaHQiLCJsZWZ0IiwidG9wIiwiZmVhdHVyZXMiLCJ3bmQiLCJvcGVuIiwib3BlbmVyIiwiTWVzc2FnZUVkaXRIaXN0b3J5RGlhbG9nIiwiY3JlYXRlRGlhbG9nIiwiX2NvbnRlbnQiLCJsaW5rcyIsImNvbXBvbmVudERpZE1vdW50IiwiX3VubW91bnRlZCIsIl9waWxscyIsImVkaXRTdGF0ZSIsIl9hcHBseUZvcm1hdHRpbmciLCJzaG93TGluZU51bWJlcnMiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJhY3RpdmF0ZVNwb2lsZXJzIiwiY3VycmVudCIsIkh0bWxVdGlscyIsImxpbmtpZnlFbGVtZW50IiwiY2FsY3VsYXRlVXJsUHJldmlldyIsImdldENvbnRlbnQiLCJmb3JtYXQiLCJwcmVzIiwiUmVhY3RET00iLCJmaW5kRE9NTm9kZSIsImdldEVsZW1lbnRzQnlUYWdOYW1lIiwibGVuZ3RoIiwiaSIsInBhcmVudE5vZGUiLCJjbGFzc05hbWUiLCJfYWRkQ29kZUVsZW1lbnQiLCJkaXYiLCJfd3JhcEluRGl2IiwiX2hhbmRsZUNvZGVCbG9ja0V4cGFuc2lvbiIsIl9hZGRDb2RlRXhwYW5zaW9uQnV0dG9uIiwiX2FkZENvZGVDb3B5QnV0dG9uIiwiX2FkZExpbmVOdW1iZXJzIiwiY29kZXMiLCJzZXRUaW1lb3V0IiwiaW5jbHVkZXMiLCJfaGlnaGxpZ2h0Q29kZSIsInByZSIsImNvZGUiLCJkb2N1bWVudCIsImNyZWF0ZUVsZW1lbnQiLCJhcHBlbmQiLCJjaGlsZE5vZGVzIiwiYXBwZW5kQ2hpbGQiLCJwZXJjZW50YWdlT2ZWaWV3cG9ydCIsIm9mZnNldEhlaWdodCIsImlubmVySGVpZ2h0Iiwib25jbGljayIsIm9uSGVpZ2h0Q2hhbmdlZCIsImV4cGFuc2lvbkJ1dHRvbkV4aXN0cyIsImdldEVsZW1lbnRzQnlDbGFzc05hbWUiLCJjb3B5Q29kZSIsInN1Y2Nlc3NmdWwiLCJ0ZXh0Q29udGVudCIsImJ1dHRvblJlY3QiLCJnZXRCb3VuZGluZ0NsaWVudFJlY3QiLCJHZW5lcmljVGV4dENvbnRleHRNZW51IiwiY2xvc2UiLCJDb250ZXh0TWVudSIsImNyZWF0ZU1lbnUiLCJtZXNzYWdlIiwib25tb3VzZWxlYXZlIiwicmVwbGFjZUNoaWxkIiwibnVtYmVyIiwiaW5uZXJIVE1MIiwicmVwbGFjZSIsInNwbGl0IiwibGluZU51bWJlcnMiLCJoaWdobGlnaHQiLCJoaWdobGlnaHRCbG9jayIsImNsYXNzZXMiLCJmaWx0ZXIiLCJjbCIsInN0YXJ0c1dpdGgiLCJjb21wb25lbnREaWRVcGRhdGUiLCJwcmV2UHJvcHMiLCJzdG9wcGVkRWRpdGluZyIsIm1lc3NhZ2VXYXNFZGl0ZWQiLCJyZXBsYWNpbmdFdmVudElkIiwiY29tcG9uZW50V2lsbFVubW91bnQiLCJzaG91bGRDb21wb25lbnRVcGRhdGUiLCJuZXh0UHJvcHMiLCJuZXh0U3RhdGUiLCJoaWdobGlnaHRzIiwiaGlnaGxpZ2h0TGluayIsInNob3dVcmxQcmV2aWV3IiwiZmluZExpbmtzIiwic2VlbiIsIlNldCIsImxpbmsiLCJoYXMiLCJhZGQiLCJoaWRkZW4iLCJnZXRJdGVtIiwibm9kZXMiLCJub2RlIiwidGFnTmFtZSIsImdldEF0dHJpYnV0ZSIsInNwb2lsZXJDb250YWluZXIiLCJyZWFzb24iLCJTcG9pbGVyIiwicmVtb3ZlQXR0cmlidXRlIiwic3BvaWxlciIsIm91dGVySFRNTCIsInJlbmRlciIsIm5leHRTaWJsaW5nIiwiaXNMaW5rUHJldmlld2FibGUiLCJwdXNoIiwiY2hpbGRyZW4iLCJjb25jYXQiLCJpbmRleE9mIiwidXJsIiwiaG9zdCIsIm1hdGNoIiwidG9Mb3dlckNhc2UiLCJ0cmltIiwiX3JlbmRlckVkaXRlZE1hcmtlciIsImRhdGUiLCJyZXBsYWNpbmdFdmVudERhdGUiLCJkYXRlU3RyaW5nIiwidG9vbHRpcCIsIl9vcGVuSGlzdG9yeURpYWxvZyIsIkVkaXRNZXNzYWdlQ29tcG9zZXIiLCJjb250ZW50Iiwic3RyaXBSZXBseSIsInJlcGxhY2luZ0V2ZW50IiwiUmVwbHlUaHJlYWQiLCJnZXRQYXJlbnRFdmVudElkIiwiYm9keSIsImJvZHlUb0h0bWwiLCJkaXNhYmxlQmlnRW1vamkiLCJtc2d0eXBlIiwic3RyaXBSZXBseUZhbGxiYWNrIiwicmVmIiwiZGF0YSIsIm9uU3RhcnRlckxpbmtDbGljayIsImJpbmQiLCJ3aWRnZXRzIiwiTGlua1ByZXZpZXdXaWRnZXQiLCJtYXAiLCJvbkNhbmNlbENsaWNrIiwib25FbW90ZVNlbmRlckNsaWNrIiwic2VuZGVyIiwibmFtZSIsIlByb3BUeXBlcyIsIm9iamVjdCIsImlzUmVxdWlyZWQiLCJhcnJheSIsInN0cmluZyIsImJvb2wiLCJmdW5jIiwidGlsZVNoYXBlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBa0JBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOzs7Ozs7OztJQUdxQkEsVyxXQURwQixnREFBcUIsNEJBQXJCLEMsbUNBQUQsTUFDcUJBLFdBRHJCLFNBQ3lDQyxlQUFNQyxTQUQvQyxDQUN5RDtBQXFCckRDLEVBQUFBLFdBQVcsQ0FBQ0MsS0FBRCxFQUFRO0FBQ2YsVUFBTUEsS0FBTjtBQURlLHlEQStUSEMsS0FBSyxJQUFJO0FBQ3JCLFdBQUtDLFFBQUwsQ0FBYztBQUFFQyxRQUFBQSxZQUFZLEVBQUU7QUFBaEIsT0FBZCxFQURxQixDQUVyQjs7QUFDQSxVQUFJQyxNQUFNLENBQUNDLFlBQVgsRUFBeUI7QUFDckJELFFBQUFBLE1BQU0sQ0FBQ0MsWUFBUCxDQUFvQkMsT0FBcEIsQ0FBNEIsa0JBQWtCLEtBQUtOLEtBQUwsQ0FBV08sT0FBWCxDQUFtQkMsS0FBbkIsRUFBOUMsRUFBMEUsR0FBMUU7QUFDSDs7QUFDRCxXQUFLQyxXQUFMO0FBQ0gsS0F0VWtCO0FBQUEsOERBd1VFUixLQUFLLElBQUk7QUFDMUIsWUFBTU0sT0FBTyxHQUFHLEtBQUtQLEtBQUwsQ0FBV08sT0FBM0I7O0FBQ0FHLDBCQUFJQyxRQUFKLENBQWE7QUFDVEMsUUFBQUEsTUFBTSxFQUFFLGdCQURDO0FBRVRDLFFBQUFBLE9BQU8sRUFBRU4sT0FBTyxDQUFDTyxTQUFSO0FBRkEsT0FBYjtBQUlILEtBOVVrQjtBQUFBLDJEQWdWRCxPQUFPO0FBQ3JCQyxNQUFBQSxj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QUwsQ0FBVzBHO0FBTHpCLFVBQVA7QUFPSCxPQVJTLENBQVY7QUFTSDs7QUFFRCxZQUFRMkUsT0FBTyxDQUFDUSxPQUFoQjtBQUNJLFdBQUssU0FBTDtBQUNJLDRCQUNJO0FBQU0sVUFBQSxTQUFTLEVBQUM7QUFBaEIsaUNBRUk7QUFDSSxVQUFBLFNBQVMsRUFBQyxzQkFEZDtBQUVJLFVBQUEsT0FBTyxFQUFFLEtBQUtVO0FBRmxCLFdBSU1oTSxPQUFPLENBQUNpTSxNQUFSLEdBQWlCak0sT0FBTyxDQUFDaU0sTUFBUixDQUFlQyxJQUFoQyxHQUF1Q2xNLE9BQU8sQ0FBQ08sU0FBUixFQUo3QyxDQUZKLFVBU000SyxJQVROLEVBVU1TLE9BVk4sQ0FESjs7QUFjSixXQUFLLFVBQUw7QUFDSSw0QkFDSTtBQUFNLFVBQUEsU0FBUyxFQUFDO0FBQWhCLFdBQ01ULElBRE4sRUFFTVMsT0FGTixDQURKOztBQU1KO0FBQVM7QUFDTCw0QkFDSTtBQUFNLFVBQUEsU0FBUyxFQUFDO0FBQWhCLFdBQ01ULElBRE4sRUFFTVMsT0FGTixDQURKO0FBeEJSO0FBK0JIOztBQTNnQm9ELEMsc0RBQ2xDO0FBQ2Y7QUFDQTVMLEVBQUFBLE9BQU8sRUFBRW1NLG1CQUFVQyxNQUFWLENBQWlCQyxVQUZYOztBQUlmO0FBQ0EvRCxFQUFBQSxVQUFVLEVBQUU2RCxtQkFBVUcsS0FMUDs7QUFPZjtBQUNBL0QsRUFBQUEsYUFBYSxFQUFFNEQsbUJBQVVJLE1BUlY7O0FBVWY7QUFDQS9ELEVBQUFBLGNBQWMsRUFBRTJELG1CQUFVSyxJQVhYOztBQWFmO0FBQ0FyRyxFQUFBQSxlQUFlLEVBQUVnRyxtQkFBVU0sSUFkWjs7QUFnQmY7QUFDQUMsRUFBQUEsU0FBUyxFQUFFUCxtQkFBVUk7QUFqQk4sQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAxNSwgMjAxNiBPcGVuTWFya2V0IEx0ZFxuQ29weXJpZ2h0IDIwMTcgTmV3IFZlY3RvciBMdGRcbkNvcHlyaWdodCAyMDE5IFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IFJlYWN0LCB7Y3JlYXRlUmVmfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgUmVhY3RET00gZnJvbSAncmVhY3QtZG9tJztcbmltcG9ydCBQcm9wVHlwZXMgZnJvbSAncHJvcC10eXBlcyc7XG5pbXBvcnQgaGlnaGxpZ2h0IGZyb20gJ2hpZ2hsaWdodC5qcyc7XG5pbXBvcnQgKiBhcyBIdG1sVXRpbHMgZnJvbSAnLi4vLi4vLi4vSHRtbFV0aWxzJztcbmltcG9ydCB7Zm9ybWF0RGF0ZX0gZnJvbSAnLi4vLi4vLi4vRGF0ZVV0aWxzJztcbmltcG9ydCAqIGFzIHNkayBmcm9tICcuLi8uLi8uLi9pbmRleCc7XG5pbXBvcnQgTW9kYWwgZnJvbSAnLi4vLi4vLi4vTW9kYWwnO1xuaW1wb3J0IGRpcyBmcm9tICcuLi8uLi8uLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXInO1xuaW1wb3J0IHsgX3QgfSBmcm9tICcuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXInO1xuaW1wb3J0ICogYXMgQ29udGV4dE1lbnUgZnJvbSAnLi4vLi4vc3RydWN0dXJlcy9Db250ZXh0TWVudSc7XG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vLi4vLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IFJlcGx5VGhyZWFkIGZyb20gXCIuLi9lbGVtZW50cy9SZXBseVRocmVhZFwiO1xuaW1wb3J0IHtwaWxsaWZ5TGlua3MsIHVubW91bnRQaWxsc30gZnJvbSAnLi4vLi4vLi4vdXRpbHMvcGlsbGlmeSc7XG5pbXBvcnQge0ludGVncmF0aW9uTWFuYWdlcnN9IGZyb20gXCIuLi8uLi8uLi9pbnRlZ3JhdGlvbnMvSW50ZWdyYXRpb25NYW5hZ2Vyc1wiO1xuaW1wb3J0IHtpc1Blcm1hbGlua0hvc3R9IGZyb20gXCIuLi8uLi8uLi91dGlscy9wZXJtYWxpbmtzL1Blcm1hbGlua3NcIjtcbmltcG9ydCB7dG9SaWdodE9mfSBmcm9tIFwiLi4vLi4vc3RydWN0dXJlcy9Db250ZXh0TWVudVwiO1xuaW1wb3J0IHtjb3B5UGxhaW50ZXh0fSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvc3RyaW5nc1wiO1xuaW1wb3J0IEFjY2Vzc2libGVUb29sdGlwQnV0dG9uIGZyb20gXCIuLi9lbGVtZW50cy9BY2Nlc3NpYmxlVG9vbHRpcEJ1dHRvblwiO1xuaW1wb3J0IHtyZXBsYWNlYWJsZUNvbXBvbmVudH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL3JlcGxhY2VhYmxlQ29tcG9uZW50XCI7XG5cbkByZXBsYWNlYWJsZUNvbXBvbmVudChcInZpZXdzLm1lc3NhZ2VzLlRleHR1YWxCb2R5XCIpXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUZXh0dWFsQm9keSBleHRlbmRzIFJlYWN0LkNvbXBvbmVudCB7XG4gICAgc3RhdGljIHByb3BUeXBlcyA9IHtcbiAgICAgICAgLyogdGhlIE1hdHJpeEV2ZW50IHRvIHNob3cgKi9cbiAgICAgICAgbXhFdmVudDogUHJvcFR5cGVzLm9iamVjdC5pc1JlcXVpcmVkLFxuXG4gICAgICAgIC8qIGEgbGlzdCBvZiB3b3JkcyB0byBoaWdobGlnaHQgKi9cbiAgICAgICAgaGlnaGxpZ2h0czogUHJvcFR5cGVzLmFycmF5LFxuXG4gICAgICAgIC8qIGxpbmsgVVJMIGZvciB0aGUgaGlnaGxpZ2h0cyAqL1xuICAgICAgICBoaWdobGlnaHRMaW5rOiBQcm9wVHlwZXMuc3RyaW5nLFxuXG4gICAgICAgIC8qIHNob3VsZCBzaG93IFVSTCBwcmV2aWV3cyBmb3IgdGhpcyBldmVudCAqL1xuICAgICAgICBzaG93VXJsUHJldmlldzogUHJvcFR5cGVzLmJvb2wsXG5cbiAgICAgICAgLyogY2FsbGJhY2sgZm9yIHdoZW4gb3VyIHdpZGdldCBoYXMgbG9hZGVkICovXG4gICAgICAgIG9uSGVpZ2h0Q2hhbmdlZDogUHJvcFR5cGVzLmZ1bmMsXG5cbiAgICAgICAgLyogdGhlIHNoYXBlIG9mIHRoZSB0aWxlLCB1c2VkICovXG4gICAgICAgIHRpbGVTaGFwZTogUHJvcFR5cGVzLnN0cmluZyxcbiAgICB9O1xuXG4gICAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuXG4gICAgICAgIHRoaXMuX2NvbnRlbnQgPSBjcmVhdGVSZWYoKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgLy8gdGhlIFVSTHMgKGlmIGFueSkgdG8gYmUgcHJldmlld2VkIHdpdGggY