matrix-react-sdk
Version:
SDK for matrix.org using React
220 lines (217 loc) • 35.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _languageHandler = require("../../../languageHandler");
var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher"));
var _Permalinks = require("../../../utils/permalinks/Permalinks");
var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore"));
var _FormattingUtils = require("../../../utils/FormattingUtils");
var _actions = require("../../../dispatcher/actions");
var _Spinner = _interopRequireDefault(require("./Spinner"));
var _ReplyTile = _interopRequireDefault(require("../rooms/ReplyTile"));
var _Pill = require("./Pill");
var _AccessibleButton = _interopRequireDefault(require("./AccessibleButton"));
var _Reply = require("../../../utils/Reply");
var _RoomContext = _interopRequireDefault(require("../../../contexts/RoomContext"));
var _MatrixClientPeg = require("../../../MatrixClientPeg");
/*
Copyright 2024 New Vector Ltd.
Copyright 2017-2023 The Matrix.org Foundation C.I.C.
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
/**
* This number is based on the previous behavior - if we have message of height
* over 60px then we want to show button that will allow to expand it.
*/
const SHOW_EXPAND_QUOTE_PIXELS = 60;
// This component does no cycle detection, simply because the only way to make such a cycle would be to
// craft event_id's, using a homeserver that generates predictable event IDs; even then the impact would
// be low as each event being loaded (after the first) is triggered by an explicit user action.
class ReplyChain extends _react.default.Component {
constructor(props, context) {
super(props, context);
(0, _defineProperty2.default)(this, "unmounted", false);
(0, _defineProperty2.default)(this, "room", void 0);
(0, _defineProperty2.default)(this, "blockquoteRef", /*#__PURE__*/_react.default.createRef());
(0, _defineProperty2.default)(this, "canCollapse", () => {
return this.state.events.length > 1;
});
(0, _defineProperty2.default)(this, "collapse", () => {
this.initialize();
});
(0, _defineProperty2.default)(this, "onQuoteClick", async () => {
if (!this.state.loadedEv) return;
const events = [this.state.loadedEv, ...this.state.events];
let loadedEv = null;
if (events.length > 0) {
loadedEv = await this.getNextEvent(events[0]);
}
this.setState({
loadedEv,
events
});
_dispatcher.default.fire(_actions.Action.FocusSendMessageComposer);
});
this.state = {
events: [],
loadedEv: null,
loading: true,
err: false
};
this.room = this.matrixClient.getRoom(this.props.parentEv.getRoomId());
}
get matrixClient() {
return _MatrixClientPeg.MatrixClientPeg.safeGet();
}
componentDidMount() {
this.initialize();
this.trySetExpandableQuotes();
}
componentDidUpdate() {
this.props.onHeightChanged?.();
this.trySetExpandableQuotes();
}
componentWillUnmount() {
this.unmounted = true;
}
trySetExpandableQuotes() {
if (this.props.isQuoteExpanded === undefined && this.blockquoteRef.current) {
const el = this.blockquoteRef.current.querySelector(".mx_EventTile_body");
if (el) {
const code = el.querySelector("code");
const isCodeEllipsisShown = code ? code.offsetHeight >= SHOW_EXPAND_QUOTE_PIXELS : false;
const isElipsisShown = el.offsetHeight >= SHOW_EXPAND_QUOTE_PIXELS || isCodeEllipsisShown;
if (isElipsisShown) {
this.props.setQuoteExpanded(false);
}
}
}
}
async initialize() {
const {
parentEv
} = this.props;
// at time of making this component we checked that props.parentEv has a parentEventId
const ev = await this.getEvent((0, _Reply.getParentEventId)(parentEv));
if (this.unmounted) return;
if (ev) {
const loadedEv = await this.getNextEvent(ev);
this.setState({
events: [ev],
loadedEv,
loading: false
});
} else {
this.setState({
err: true
});
}
}
async getNextEvent(ev) {
try {
const inReplyToEventId = (0, _Reply.getParentEventId)(ev);
if (!inReplyToEventId) return null;
return await this.getEvent(inReplyToEventId);
} catch (e) {
return null;
}
}
async getEvent(eventId) {
if (!eventId) return null;
const event = this.room.findEventById(eventId);
if (event) return event;
try {
// ask the client to fetch the event we want using the context API, only interface to do so is to ask
// for a timeline with that event, but once it is loaded we can use findEventById to look up the ev map
await this.matrixClient.getEventTimeline(this.room.getUnfilteredTimelineSet(), eventId);
} catch (e) {
// if it fails catch the error and return early, there's no point trying to find the event in this case.
// Return null as it is falsy and thus should be treated as an error (as the event cannot be resolved).
return null;
}
return this.room.findEventById(eventId) ?? null;
}
getReplyChainColorClass(ev) {
return (0, _FormattingUtils.getUserNameColorClass)(ev.getSender()).replace("Username", "ReplyChain");
}
render() {
let header;
if (this.state.err) {
header = /*#__PURE__*/_react.default.createElement("blockquote", {
className: "mx_ReplyChain mx_ReplyChain_error"
}, (0, _languageHandler._t)("timeline|reply|error_loading"));
} else if (this.state.loadedEv && (0, _Reply.shouldDisplayReply)(this.state.events[0])) {
const ev = this.state.loadedEv;
const room = this.matrixClient.getRoom(ev.getRoomId());
header = /*#__PURE__*/_react.default.createElement("blockquote", {
className: `mx_ReplyChain ${this.getReplyChainColorClass(ev)}`
}, (0, _languageHandler._t)("timeline|reply|in_reply_to", {}, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
className: "mx_ReplyChain_show",
onClick: this.onQuoteClick
}, sub),
pill: /*#__PURE__*/_react.default.createElement(_Pill.Pill, {
type: _Pill.PillType.UserMention,
room: room ?? undefined,
url: (0, _Permalinks.makeUserPermalink)(ev.getSender()),
shouldShowPillAvatar: _SettingsStore.default.getValue("Pill.shouldShowPillAvatar")
})
}));
} else if (this.props.forExport) {
const eventId = (0, _Reply.getParentEventId)(this.props.parentEv);
header = /*#__PURE__*/_react.default.createElement("p", {
className: "mx_ReplyChain_Export"
}, (0, _languageHandler._t)("timeline|reply|in_reply_to_for_export", {}, {
a: sub => /*#__PURE__*/_react.default.createElement("a", {
className: "mx_reply_anchor",
href: `#${eventId}`,
"data-scroll-to": eventId
}, " ", sub, " ")
}));
} else if (this.state.loading) {
header = /*#__PURE__*/_react.default.createElement(_Spinner.default, {
w: 16,
h: 16
});
}
const {
isQuoteExpanded
} = this.props;
const evTiles = this.state.events.map(ev => {
const classname = (0, _classnames.default)({
"mx_ReplyChain": true,
[this.getReplyChainColorClass(ev)]: true,
// We don't want to add the class if it's undefined, it should only be expanded/collapsed when it's true/false
"mx_ReplyChain--expanded": isQuoteExpanded === true,
// We don't want to add the class if it's undefined, it should only be expanded/collapsed when it's true/false
"mx_ReplyChain--collapsed": isQuoteExpanded === false
});
return /*#__PURE__*/_react.default.createElement("blockquote", {
ref: this.blockquoteRef,
className: classname,
key: ev.getId()
}, /*#__PURE__*/_react.default.createElement(_ReplyTile.default, {
mxEvent: ev,
onHeightChanged: this.props.onHeightChanged,
permalinkCreator: this.props.permalinkCreator,
toggleExpandedQuote: () => this.props.setQuoteExpanded(!this.props.isQuoteExpanded),
getRelationsForEvent: this.props.getRelationsForEvent
}));
});
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_ReplyChain_wrapper"
}, /*#__PURE__*/_react.default.createElement("div", null, header), /*#__PURE__*/_react.default.createElement("div", null, evTiles));
}
}
exports.default = ReplyChain;
(0, _defineProperty2.default)(ReplyChain, "contextType", _RoomContext.default);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9jbGFzc25hbWVzIiwiX2xhbmd1YWdlSGFuZGxlciIsIl9kaXNwYXRjaGVyIiwiX1Blcm1hbGlua3MiLCJfU2V0dGluZ3NTdG9yZSIsIl9Gb3JtYXR0aW5nVXRpbHMiLCJfYWN0aW9ucyIsIl9TcGlubmVyIiwiX1JlcGx5VGlsZSIsIl9QaWxsIiwiX0FjY2Vzc2libGVCdXR0b24iLCJfUmVwbHkiLCJfUm9vbUNvbnRleHQiLCJfTWF0cml4Q2xpZW50UGVnIiwiU0hPV19FWFBBTkRfUVVPVEVfUElYRUxTIiwiUmVwbHlDaGFpbiIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsImNvbnRleHQiLCJfZGVmaW5lUHJvcGVydHkyIiwiZGVmYXVsdCIsImNyZWF0ZVJlZiIsInN0YXRlIiwiZXZlbnRzIiwibGVuZ3RoIiwiaW5pdGlhbGl6ZSIsImxvYWRlZEV2IiwiZ2V0TmV4dEV2ZW50Iiwic2V0U3RhdGUiLCJkaXMiLCJmaXJlIiwiQWN0aW9uIiwiRm9jdXNTZW5kTWVzc2FnZUNvbXBvc2VyIiwibG9hZGluZyIsImVyciIsInJvb20iLCJtYXRyaXhDbGllbnQiLCJnZXRSb29tIiwicGFyZW50RXYiLCJnZXRSb29tSWQiLCJNYXRyaXhDbGllbnRQZWciLCJzYWZlR2V0IiwiY29tcG9uZW50RGlkTW91bnQiLCJ0cnlTZXRFeHBhbmRhYmxlUXVvdGVzIiwiY29tcG9uZW50RGlkVXBkYXRlIiwib25IZWlnaHRDaGFuZ2VkIiwiY29tcG9uZW50V2lsbFVubW91bnQiLCJ1bm1vdW50ZWQiLCJpc1F1b3RlRXhwYW5kZWQiLCJ1bmRlZmluZWQiLCJibG9ja3F1b3RlUmVmIiwiY3VycmVudCIsImVsIiwicXVlcnlTZWxlY3RvciIsImNvZGUiLCJpc0NvZGVFbGxpcHNpc1Nob3duIiwib2Zmc2V0SGVpZ2h0IiwiaXNFbGlwc2lzU2hvd24iLCJzZXRRdW90ZUV4cGFuZGVkIiwiZXYiLCJnZXRFdmVudCIsImdldFBhcmVudEV2ZW50SWQiLCJpblJlcGx5VG9FdmVudElkIiwiZSIsImV2ZW50SWQiLCJldmVudCIsImZpbmRFdmVudEJ5SWQiLCJnZXRFdmVudFRpbWVsaW5lIiwiZ2V0VW5maWx0ZXJlZFRpbWVsaW5lU2V0IiwiZ2V0UmVwbHlDaGFpbkNvbG9yQ2xhc3MiLCJnZXRVc2VyTmFtZUNvbG9yQ2xhc3MiLCJnZXRTZW5kZXIiLCJyZXBsYWNlIiwicmVuZGVyIiwiaGVhZGVyIiwiY3JlYXRlRWxlbWVudCIsImNsYXNzTmFtZSIsIl90Iiwic2hvdWxkRGlzcGxheVJlcGx5IiwiYSIsInN1YiIsImtpbmQiLCJvbkNsaWNrIiwib25RdW90ZUNsaWNrIiwicGlsbCIsIlBpbGwiLCJ0eXBlIiwiUGlsbFR5cGUiLCJVc2VyTWVudGlvbiIsInVybCIsIm1ha2VVc2VyUGVybWFsaW5rIiwic2hvdWxkU2hvd1BpbGxBdmF0YXIiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJmb3JFeHBvcnQiLCJocmVmIiwidyIsImgiLCJldlRpbGVzIiwibWFwIiwiY2xhc3NuYW1lIiwiY2xhc3NOYW1lcyIsInJlZiIsImtleSIsImdldElkIiwibXhFdmVudCIsInBlcm1hbGlua0NyZWF0b3IiLCJ0b2dnbGVFeHBhbmRlZFF1b3RlIiwiZ2V0UmVsYXRpb25zRm9yRXZlbnQiLCJleHBvcnRzIiwiUm9vbUNvbnRleHQiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9lbGVtZW50cy9SZXBseUNoYWluLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxNy0yMDIzIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5Db3B5cmlnaHQgMjAxOSBNaWNoYWVsIFRlbGF0eW5za2kgPDd0M2NoZ3V5QGdtYWlsLmNvbT5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IGNsYXNzTmFtZXMgZnJvbSBcImNsYXNzbmFtZXNcIjtcbmltcG9ydCB7IE1hdHJpeEV2ZW50LCBSb29tLCBNYXRyaXhDbGllbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5cbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IGRpcyBmcm9tIFwiLi4vLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBtYWtlVXNlclBlcm1hbGluaywgUm9vbVBlcm1hbGlua0NyZWF0b3IgfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvcGVybWFsaW5rcy9QZXJtYWxpbmtzXCI7XG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vLi4vLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IHsgTGF5b3V0IH0gZnJvbSBcIi4uLy4uLy4uL3NldHRpbmdzL2VudW1zL0xheW91dFwiO1xuaW1wb3J0IHsgZ2V0VXNlck5hbWVDb2xvckNsYXNzIH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL0Zvcm1hdHRpbmdVdGlsc1wiO1xuaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSBcIi4uLy4uLy4uL2Rpc3BhdGNoZXIvYWN0aW9uc1wiO1xuaW1wb3J0IFNwaW5uZXIgZnJvbSBcIi4vU3Bpbm5lclwiO1xuaW1wb3J0IFJlcGx5VGlsZSBmcm9tIFwiLi4vcm9vbXMvUmVwbHlUaWxlXCI7XG5pbXBvcnQgeyBQaWxsLCBQaWxsVHlwZSB9IGZyb20gXCIuL1BpbGxcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uIGZyb20gXCIuL0FjY2Vzc2libGVCdXR0b25cIjtcbmltcG9ydCB7IGdldFBhcmVudEV2ZW50SWQsIHNob3VsZERpc3BsYXlSZXBseSB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9SZXBseVwiO1xuaW1wb3J0IFJvb21Db250ZXh0IGZyb20gXCIuLi8uLi8uLi9jb250ZXh0cy9Sb29tQ29udGV4dFwiO1xuaW1wb3J0IHsgTWF0cml4Q2xpZW50UGVnIH0gZnJvbSBcIi4uLy4uLy4uL01hdHJpeENsaWVudFBlZ1wiO1xuaW1wb3J0IHsgR2V0UmVsYXRpb25zRm9yRXZlbnQgfSBmcm9tIFwiLi4vcm9vbXMvRXZlbnRUaWxlXCI7XG5cbi8qKlxuICogVGhpcyBudW1iZXIgaXMgYmFzZWQgb24gdGhlIHByZXZpb3VzIGJlaGF2aW9yIC0gaWYgd2UgaGF2ZSBtZXNzYWdlIG9mIGhlaWdodFxuICogb3ZlciA2MHB4IHRoZW4gd2Ugd2FudCB0byBzaG93IGJ1dHRvbiB0aGF0IHdpbGwgYWxsb3cgdG8gZXhwYW5kIGl0LlxuICovXG5jb25zdCBTSE9XX0VYUEFORF9RVU9URV9QSVhFTFMgPSA2MDtcblxuaW50ZXJmYWNlIElQcm9wcyB7XG4gICAgLy8gdGhlIGxhdGVzdCBldmVudCBpbiB0aGlzIGNoYWluIG9mIHJlcGxpZXNcbiAgICBwYXJlbnRFdjogTWF0cml4RXZlbnQ7XG4gICAgLy8gY2FsbGVkIHdoZW4gdGhlIFJlcGx5Q2hhaW4gY29udGVudHMgaGFzIGNoYW5nZWQsIGluY2x1ZGluZyBFdmVudFRpbGVzIHRoZXJlb2ZcbiAgICBvbkhlaWdodENoYW5nZWQ/OiAoKSA9PiB2b2lkO1xuICAgIHBlcm1hbGlua0NyZWF0b3I/OiBSb29tUGVybWFsaW5rQ3JlYXRvcjtcbiAgICAvLyBTcGVjaWZpZXMgd2hpY2ggbGF5b3V0IHRvIHVzZS5cbiAgICBsYXlvdXQ/OiBMYXlvdXQ7XG4gICAgLy8gV2hldGhlciB0byBhbHdheXMgc2hvdyBhIHRpbWVzdGFtcFxuICAgIGFsd2F5c1Nob3dUaW1lc3RhbXBzPzogYm9vbGVhbjtcbiAgICBmb3JFeHBvcnQ/OiBib29sZWFuO1xuICAgIGlzUXVvdGVFeHBhbmRlZD86IGJvb2xlYW47XG4gICAgc2V0UXVvdGVFeHBhbmRlZDogKGlzRXhwYW5kZWQ6IGJvb2xlYW4pID0+IHZvaWQ7XG4gICAgZ2V0UmVsYXRpb25zRm9yRXZlbnQ/OiBHZXRSZWxhdGlvbnNGb3JFdmVudDtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgLy8gVGhlIGxvYWRlZCBldmVudHMgdG8gYmUgcmVuZGVyZWQgYXMgbGluZWFyLXJlcGxpZXNcbiAgICBldmVudHM6IE1hdHJpeEV2ZW50W107XG4gICAgLy8gVGhlIGxhdGVzdCBsb2FkZWQgZXZlbnQgd2hpY2ggaGFzIG5vdCB5ZXQgYmVlbiBzaG93blxuICAgIGxvYWRlZEV2OiBNYXRyaXhFdmVudCB8IG51bGw7XG4gICAgLy8gV2hldGhlciB0aGUgY29tcG9uZW50IGlzIHN0aWxsIGxvYWRpbmcgbW9yZSBldmVudHNcbiAgICBsb2FkaW5nOiBib29sZWFuO1xuICAgIC8vIFdoZXRoZXIgYXMgZXJyb3Igd2FzIGVuY291bnRlcmVkIGZldGNoaW5nIGEgcmVwbGllZCB0byBldmVudC5cbiAgICBlcnI6IGJvb2xlYW47XG59XG5cbi8vIFRoaXMgY29tcG9uZW50IGRvZXMgbm8gY3ljbGUgZGV0ZWN0aW9uLCBzaW1wbHkgYmVjYXVzZSB0aGUgb25seSB3YXkgdG8gbWFrZSBzdWNoIGEgY3ljbGUgd291bGQgYmUgdG9cbi8vIGNyYWZ0IGV2ZW50X2lkJ3MsIHVzaW5nIGEgaG9tZXNlcnZlciB0aGF0IGdlbmVyYXRlcyBwcmVkaWN0YWJsZSBldmVudCBJRHM7IGV2ZW4gdGhlbiB0aGUgaW1wYWN0IHdvdWxkXG4vLyBiZSBsb3cgYXMgZWFjaCBldmVudCBiZWluZyBsb2FkZWQgKGFmdGVyIHRoZSBmaXJzdCkgaXMgdHJpZ2dlcmVkIGJ5IGFuIGV4cGxpY2l0IHVzZXIgYWN0aW9uLlxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVwbHlDaGFpbiBleHRlbmRzIFJlYWN0LkNvbXBvbmVudDxJUHJvcHMsIElTdGF0ZT4ge1xuICAgIHB1YmxpYyBzdGF0aWMgY29udGV4dFR5cGUgPSBSb29tQ29udGV4dDtcbiAgICBwdWJsaWMgZGVjbGFyZSBjb250ZXh0OiBSZWFjdC5Db250ZXh0VHlwZTx0eXBlb2YgUm9vbUNvbnRleHQ+O1xuXG4gICAgcHJpdmF0ZSB1bm1vdW50ZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHJvb206IFJvb207XG4gICAgcHJpdmF0ZSBibG9ja3F1b3RlUmVmID0gUmVhY3QuY3JlYXRlUmVmPEhUTUxRdW90ZUVsZW1lbnQ+KCk7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IElQcm9wcywgY29udGV4dDogUmVhY3QuQ29udGV4dFR5cGU8dHlwZW9mIFJvb21Db250ZXh0Pikge1xuICAgICAgICBzdXBlcihwcm9wcywgY29udGV4dCk7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIGV2ZW50czogW10sXG4gICAgICAgICAgICBsb2FkZWRFdjogbnVsbCxcbiAgICAgICAgICAgIGxvYWRpbmc6IHRydWUsXG4gICAgICAgICAgICBlcnI6IGZhbHNlLFxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMucm9vbSA9IHRoaXMubWF0cml4Q2xpZW50LmdldFJvb20odGhpcy5wcm9wcy5wYXJlbnRFdi5nZXRSb29tSWQoKSkhO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IG1hdHJpeENsaWVudCgpOiBNYXRyaXhDbGllbnQge1xuICAgICAgICByZXR1cm4gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkTW91bnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZSgpO1xuICAgICAgICB0aGlzLnRyeVNldEV4cGFuZGFibGVRdW90ZXMoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkVXBkYXRlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnByb3BzLm9uSGVpZ2h0Q2hhbmdlZD8uKCk7XG4gICAgICAgIHRoaXMudHJ5U2V0RXhwYW5kYWJsZVF1b3RlcygpO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wb25lbnRXaWxsVW5tb3VudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy51bm1vdW50ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgdHJ5U2V0RXhwYW5kYWJsZVF1b3RlcygpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMuaXNRdW90ZUV4cGFuZGVkID09PSB1bmRlZmluZWQgJiYgdGhpcy5ibG9ja3F1b3RlUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGVsOiBIVE1MRWxlbWVudCB8IG51bGwgPSB0aGlzLmJsb2NrcXVvdGVSZWYuY3VycmVudC5xdWVyeVNlbGVjdG9yKFwiLm14X0V2ZW50VGlsZV9ib2R5XCIpO1xuICAgICAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29kZTogSFRNTEVsZW1lbnQgfCBudWxsID0gZWwucXVlcnlTZWxlY3RvcihcImNvZGVcIik7XG4gICAgICAgICAgICAgICAgY29uc3QgaXNDb2RlRWxsaXBzaXNTaG93biA9IGNvZGUgPyBjb2RlLm9mZnNldEhlaWdodCA+PSBTSE9XX0VYUEFORF9RVU9URV9QSVhFTFMgOiBmYWxzZTtcbiAgICAgICAgICAgICAgICBjb25zdCBpc0VsaXBzaXNTaG93biA9IGVsLm9mZnNldEhlaWdodCA+PSBTSE9XX0VYUEFORF9RVU9URV9QSVhFTFMgfHwgaXNDb2RlRWxsaXBzaXNTaG93bjtcbiAgICAgICAgICAgICAgICBpZiAoaXNFbGlwc2lzU2hvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5zZXRRdW90ZUV4cGFuZGVkKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHsgcGFyZW50RXYgfSA9IHRoaXMucHJvcHM7XG4gICAgICAgIC8vIGF0IHRpbWUgb2YgbWFraW5nIHRoaXMgY29tcG9uZW50IHdlIGNoZWNrZWQgdGhhdCBwcm9wcy5wYXJlbnRFdiBoYXMgYSBwYXJlbnRFdmVudElkXG4gICAgICAgIGNvbnN0IGV2ID0gYXdhaXQgdGhpcy5nZXRFdmVudChnZXRQYXJlbnRFdmVudElkKHBhcmVudEV2KSk7XG5cbiAgICAgICAgaWYgKHRoaXMudW5tb3VudGVkKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2KSB7XG4gICAgICAgICAgICBjb25zdCBsb2FkZWRFdiA9IGF3YWl0IHRoaXMuZ2V0TmV4dEV2ZW50KGV2KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIGV2ZW50czogW2V2XSxcbiAgICAgICAgICAgICAgICBsb2FkZWRFdixcbiAgICAgICAgICAgICAgICBsb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGVycjogdHJ1ZSB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgZ2V0TmV4dEV2ZW50KGV2OiBNYXRyaXhFdmVudCk6IFByb21pc2U8TWF0cml4RXZlbnQgfCBudWxsPiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBpblJlcGx5VG9FdmVudElkID0gZ2V0UGFyZW50RXZlbnRJZChldik7XG4gICAgICAgICAgICBpZiAoIWluUmVwbHlUb0V2ZW50SWQpIHJldHVybiBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0RXZlbnQoaW5SZXBseVRvRXZlbnRJZCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBnZXRFdmVudChldmVudElkPzogc3RyaW5nKTogUHJvbWlzZTxNYXRyaXhFdmVudCB8IG51bGw+IHtcbiAgICAgICAgaWYgKCFldmVudElkKSByZXR1cm4gbnVsbDtcbiAgICAgICAgY29uc3QgZXZlbnQgPSB0aGlzLnJvb20uZmluZEV2ZW50QnlJZChldmVudElkKTtcbiAgICAgICAgaWYgKGV2ZW50KSByZXR1cm4gZXZlbnQ7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIGFzayB0aGUgY2xpZW50IHRvIGZldGNoIHRoZSBldmVudCB3ZSB3YW50IHVzaW5nIHRoZSBjb250ZXh0IEFQSSwgb25seSBpbnRlcmZhY2UgdG8gZG8gc28gaXMgdG8gYXNrXG4gICAgICAgICAgICAvLyBmb3IgYSB0aW1lbGluZSB3aXRoIHRoYXQgZXZlbnQsIGJ1dCBvbmNlIGl0IGlzIGxvYWRlZCB3ZSBjYW4gdXNlIGZpbmRFdmVudEJ5SWQgdG8gbG9vayB1cCB0aGUgZXYgbWFwXG4gICAgICAgICAgICBhd2FpdCB0aGlzLm1hdHJpeENsaWVudC5nZXRFdmVudFRpbWVsaW5lKHRoaXMucm9vbS5nZXRVbmZpbHRlcmVkVGltZWxpbmVTZXQoKSwgZXZlbnRJZCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIGlmIGl0IGZhaWxzIGNhdGNoIHRoZSBlcnJvciBhbmQgcmV0dXJuIGVhcmx5LCB0aGVyZSdzIG5vIHBvaW50IHRyeWluZyB0byBmaW5kIHRoZSBldmVudCBpbiB0aGlzIGNhc2UuXG4gICAgICAgICAgICAvLyBSZXR1cm4gbnVsbCBhcyBpdCBpcyBmYWxzeSBhbmQgdGh1cyBzaG91bGQgYmUgdHJlYXRlZCBhcyBhbiBlcnJvciAoYXMgdGhlIGV2ZW50IGNhbm5vdCBiZSByZXNvbHZlZCkuXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yb29tLmZpbmRFdmVudEJ5SWQoZXZlbnRJZCkgPz8gbnVsbDtcbiAgICB9XG5cbiAgICBwdWJsaWMgY2FuQ29sbGFwc2UgPSAoKTogYm9vbGVhbiA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlLmV2ZW50cy5sZW5ndGggPiAxO1xuICAgIH07XG5cbiAgICBwdWJsaWMgY29sbGFwc2UgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZSgpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUXVvdGVDbGljayA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLmxvYWRlZEV2KSByZXR1cm47XG4gICAgICAgIGNvbnN0IGV2ZW50cyA9IFt0aGlzLnN0YXRlLmxvYWRlZEV2LCAuLi50aGlzLnN0YXRlLmV2ZW50c107XG5cbiAgICAgICAgbGV0IGxvYWRlZEV2OiBNYXRyaXhFdmVudCB8IG51bGwgPSBudWxsO1xuICAgICAgICBpZiAoZXZlbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxvYWRlZEV2ID0gYXdhaXQgdGhpcy5nZXROZXh0RXZlbnQoZXZlbnRzWzBdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgbG9hZGVkRXYsXG4gICAgICAgICAgICBldmVudHMsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRpcy5maXJlKEFjdGlvbi5Gb2N1c1NlbmRNZXNzYWdlQ29tcG9zZXIpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIGdldFJlcGx5Q2hhaW5Db2xvckNsYXNzKGV2OiBNYXRyaXhFdmVudCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBnZXRVc2VyTmFtZUNvbG9yQ2xhc3MoZXYuZ2V0U2VuZGVyKCkhKS5yZXBsYWNlKFwiVXNlcm5hbWVcIiwgXCJSZXBseUNoYWluXCIpO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgbGV0IGhlYWRlcjogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmVycikge1xuICAgICAgICAgICAgaGVhZGVyID0gKFxuICAgICAgICAgICAgICAgIDxibG9ja3F1b3RlIGNsYXNzTmFtZT1cIm14X1JlcGx5Q2hhaW4gbXhfUmVwbHlDaGFpbl9lcnJvclwiPlxuICAgICAgICAgICAgICAgICAgICB7X3QoXCJ0aW1lbGluZXxyZXBseXxlcnJvcl9sb2FkaW5nXCIpfVxuICAgICAgICAgICAgICAgIDwvYmxvY2txdW90ZT5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5sb2FkZWRFdiAmJiBzaG91bGREaXNwbGF5UmVwbHkodGhpcy5zdGF0ZS5ldmVudHNbMF0pKSB7XG4gICAgICAgICAgICBjb25zdCBldiA9IHRoaXMuc3RhdGUubG9hZGVkRXY7XG4gICAgICAgICAgICBjb25zdCByb29tID0gdGhpcy5tYXRyaXhDbGllbnQuZ2V0Um9vbShldi5nZXRSb29tSWQoKSk7XG4gICAgICAgICAgICBoZWFkZXIgPSAoXG4gICAgICAgICAgICAgICAgPGJsb2NrcXVvdGUgY2xhc3NOYW1lPXtgbXhfUmVwbHlDaGFpbiAke3RoaXMuZ2V0UmVwbHlDaGFpbkNvbG9yQ2xhc3MoZXYpfWB9PlxuICAgICAgICAgICAgICAgICAgICB7X3QoXG4gICAgICAgICAgICAgICAgICAgICAgICBcInRpbWVsaW5lfHJlcGx5fGluX3JlcGx5X3RvXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhOiAoc3ViKSA9PiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBraW5kPVwibGlua19pbmxpbmVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfUmVwbHlDaGFpbl9zaG93XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25RdW90ZUNsaWNrfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaWxsOiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxQaWxsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPXtQaWxsVHlwZS5Vc2VyTWVudGlvbn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb209e3Jvb20gPz8gdW5kZWZpbmVkfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsPXttYWtlVXNlclBlcm1hbGluayhldi5nZXRTZW5kZXIoKSEpfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvdWxkU2hvd1BpbGxBdmF0YXI9e1NldHRpbmdzU3RvcmUuZ2V0VmFsdWUoXCJQaWxsLnNob3VsZFNob3dQaWxsQXZhdGFyXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgIDwvYmxvY2txdW90ZT5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5wcm9wcy5mb3JFeHBvcnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50SWQgPSBnZXRQYXJlbnRFdmVudElkKHRoaXMucHJvcHMucGFyZW50RXYpO1xuICAgICAgICAgICAgaGVhZGVyID0gKFxuICAgICAgICAgICAgICAgIDxwIGNsYXNzTmFtZT1cIm14X1JlcGx5Q2hhaW5fRXhwb3J0XCI+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcbiAgICAgICAgICAgICAgICAgICAgICAgIFwidGltZWxpbmV8cmVwbHl8aW5fcmVwbHlfdG9fZm9yX2V4cG9ydFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYTogKHN1YikgPT4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSBjbGFzc05hbWU9XCJteF9yZXBseV9hbmNob3JcIiBocmVmPXtgIyR7ZXZlbnRJZH1gfSBkYXRhLXNjcm9sbC10bz17ZXZlbnRJZH0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XCIgXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifXtcIiBcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5sb2FkaW5nKSB7XG4gICAgICAgICAgICBoZWFkZXIgPSA8U3Bpbm5lciB3PXsxNn0gaD17MTZ9IC8+O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBpc1F1b3RlRXhwYW5kZWQgfSA9IHRoaXMucHJvcHM7XG4gICAgICAgIGNvbnN0IGV2VGlsZXMgPSB0aGlzLnN0YXRlLmV2ZW50cy5tYXAoKGV2KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc25hbWUgPSBjbGFzc05hbWVzKHtcbiAgICAgICAgICAgICAgICBcIm14X1JlcGx5Q2hhaW5cIjogdHJ1ZSxcbiAgICAgICAgICAgICAgICBbdGhpcy5nZXRSZXBseUNoYWluQ29sb3JDbGFzcyhldildOiB0cnVlLFxuICAgICAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gYWRkIHRoZSBjbGFzcyBpZiBpdCdzIHVuZGVmaW5lZCwgaXQgc2hvdWxkIG9ubHkgYmUgZXhwYW5kZWQvY29sbGFwc2VkIHdoZW4gaXQncyB0cnVlL2ZhbHNlXG4gICAgICAgICAgICAgICAgXCJteF9SZXBseUNoYWluLS1leHBhbmRlZFwiOiBpc1F1b3RlRXhwYW5kZWQgPT09IHRydWUsXG4gICAgICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byBhZGQgdGhlIGNsYXNzIGlmIGl0J3MgdW5kZWZpbmVkLCBpdCBzaG91bGQgb25seSBiZSBleHBhbmRlZC9jb2xsYXBzZWQgd2hlbiBpdCdzIHRydWUvZmFsc2VcbiAgICAgICAgICAgICAgICBcIm14X1JlcGx5Q2hhaW4tLWNvbGxhcHNlZFwiOiBpc1F1b3RlRXhwYW5kZWQgPT09IGZhbHNlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIDxibG9ja3F1b3RlIHJlZj17dGhpcy5ibG9ja3F1b3RlUmVmfSBjbGFzc05hbWU9e2NsYXNzbmFtZX0ga2V5PXtldi5nZXRJZCgpfT5cbiAgICAgICAgICAgICAgICAgICAgPFJlcGx5VGlsZVxuICAgICAgICAgICAgICAgICAgICAgICAgbXhFdmVudD17ZXZ9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkhlaWdodENoYW5nZWQ9e3RoaXMucHJvcHMub25IZWlnaHRDaGFuZ2VkfVxuICAgICAgICAgICAgICAgICAgICAgICAgcGVybWFsaW5rQ3JlYXRvcj17dGhpcy5wcm9wcy5wZXJtYWxpbmtDcmVhdG9yfVxuICAgICAgICAgICAgICAgICAgICAgICAgdG9nZ2xlRXhwYW5kZWRRdW90ZT17KCkgPT4gdGhpcy5wcm9wcy5zZXRRdW90ZUV4cGFuZGVkKCF0aGlzLnByb3BzLmlzUXVvdGVFeHBhbmRlZCl9XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRSZWxhdGlvbnNGb3JFdmVudD17dGhpcy5wcm9wcy5nZXRSZWxhdGlvbnNGb3JFdmVudH1cbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICA8L2Jsb2NrcXVvdGU+XG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9SZXBseUNoYWluX3dyYXBwZXJcIj5cbiAgICAgICAgICAgICAgICA8ZGl2PntoZWFkZXJ9PC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdj57ZXZUaWxlc308L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICApO1xuICAgIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQSxJQUFBQSxNQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxXQUFBLEdBQUFGLHNCQUFBLENBQUFDLE9BQUE7QUFHQSxJQUFBRSxnQkFBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsV0FBQSxHQUFBSixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUksV0FBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssY0FBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQU0sZ0JBQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLFFBQUEsR0FBQVAsT0FBQTtBQUNBLElBQUFRLFFBQUEsR0FBQVQsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFTLFVBQUEsR0FBQVYsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFVLEtBQUEsR0FBQVYsT0FBQTtBQUNBLElBQUFXLGlCQUFBLEdBQUFaLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBWSxNQUFBLEdBQUFaLE9BQUE7QUFDQSxJQUFBYSxZQUFBLEdBQUFkLHNCQUFB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