UNPKG

matrix-react-sdk

Version:
173 lines (170 loc) 25.8 kB
"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 _matrix = require("matrix-js-sdk/src/matrix"); var _utils = require("matrix-js-sdk/src/utils"); var _logger = require("matrix-js-sdk/src/logger"); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _languageHandler = require("../../../languageHandler"); var _DateUtils = require("../../../DateUtils"); var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore")); var _BaseDialog = _interopRequireDefault(require("./BaseDialog")); var _ScrollPanel = _interopRequireDefault(require("../../structures/ScrollPanel")); var _Spinner = _interopRequireDefault(require("../elements/Spinner")); var _EditHistoryMessage = _interopRequireDefault(require("../messages/EditHistoryMessage")); var _DateSeparator = _interopRequireDefault(require("../messages/DateSeparator")); /* Copyright 2024 New Vector Ltd. Copyright 2019 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ class MessageEditHistoryDialog extends _react.default.PureComponent { constructor(props) { super(props); (0, _defineProperty2.default)(this, "loadMoreEdits", async backwards => { if (backwards || !this.state.nextBatch && !this.state.isLoading) { // bail out on backwards as we only paginate in one direction return false; } const opts = { from: this.state.nextBatch ?? undefined }; const roomId = this.props.mxEvent.getRoomId(); const eventId = this.props.mxEvent.getId(); const client = _MatrixClientPeg.MatrixClientPeg.safeGet(); const { resolve, reject, promise } = (0, _utils.defer)(); let result; try { result = await client.relations(roomId, eventId, _matrix.RelationType.Replace, _matrix.EventType.RoomMessage, opts); } catch (error) { // log if the server returned an error if (error instanceof _matrix.MatrixError && error.errcode) { _logger.logger.error("fetching /relations failed with error", error); } this.setState({ error: error }, () => reject(error)); return promise; } const newEvents = result.events; this.locallyRedactEventsIfNeeded(newEvents); this.setState({ originalEvent: this.state.originalEvent ?? result.originalEvent ?? null, events: this.state.events.concat(newEvents), nextBatch: result.nextBatch ?? null, isLoading: false }, () => { const hasMoreResults = !!this.state.nextBatch; resolve(hasMoreResults); }); return promise; }); this.state = { originalEvent: null, error: null, events: [], nextBatch: null, isLoading: true, isTwelveHour: _SettingsStore.default.getValue("showTwelveHourTimestamps") }; } locallyRedactEventsIfNeeded(newEvents) { const roomId = this.props.mxEvent.getRoomId(); const client = _MatrixClientPeg.MatrixClientPeg.safeGet(); const room = client.getRoom(roomId); if (!room) return; const pendingEvents = room.getPendingEvents(); for (const e of newEvents) { const pendingRedaction = pendingEvents.find(pe => { return pe.getType() === _matrix.EventType.RoomRedaction && pe.getAssociatedId() === e.getId(); }); if (pendingRedaction) { e.markLocallyRedacted(pendingRedaction); } } } componentDidMount() { this.loadMoreEdits(); } renderEdits() { const nodes = []; let lastEvent; let allEvents = this.state.events; // append original event when we've done last pagination if (this.state.originalEvent && !this.state.nextBatch) { allEvents = allEvents.concat(this.state.originalEvent); } const baseEventId = this.props.mxEvent.getId(); allEvents.forEach((e, i) => { if (!lastEvent || (0, _DateUtils.wantsDateSeparator)(lastEvent.getDate() || undefined, e.getDate() || undefined)) { nodes.push( /*#__PURE__*/_react.default.createElement("li", { key: e.getTs() + "~" }, /*#__PURE__*/_react.default.createElement(_DateSeparator.default, { roomId: e.getRoomId(), ts: e.getTs() }))); } const isBaseEvent = e.getId() === baseEventId; nodes.push( /*#__PURE__*/_react.default.createElement(_EditHistoryMessage.default, { key: e.getId(), previousEdit: !isBaseEvent ? allEvents[i + 1] : undefined, isBaseEvent: isBaseEvent, mxEvent: e, isTwelveHour: this.state.isTwelveHour })); lastEvent = e; }); return nodes; } render() { let content; if (this.state.error) { const { error } = this.state; if (error.errcode === "M_UNRECOGNIZED") { content = /*#__PURE__*/_react.default.createElement("p", { className: "mx_MessageEditHistoryDialog_error" }, (0, _languageHandler._t)("error|edit_history_unsupported")); } else if (error.errcode) { // some kind of error from the homeserver content = /*#__PURE__*/_react.default.createElement("p", { className: "mx_MessageEditHistoryDialog_error" }, (0, _languageHandler._t)("error|something_went_wrong")); } else { content = /*#__PURE__*/_react.default.createElement("p", { className: "mx_MessageEditHistoryDialog_error" }, (0, _languageHandler._t)("cannot_reach_homeserver"), /*#__PURE__*/_react.default.createElement("br", null), (0, _languageHandler._t)("cannot_reach_homeserver_detail")); } } else if (this.state.isLoading) { content = /*#__PURE__*/_react.default.createElement(_Spinner.default, null); } else { content = /*#__PURE__*/_react.default.createElement(_ScrollPanel.default, { className: "mx_MessageEditHistoryDialog_scrollPanel", onFillRequest: this.loadMoreEdits, stickyBottom: false, startAtBottom: false }, /*#__PURE__*/_react.default.createElement("ul", { className: "mx_MessageEditHistoryDialog_edits" }, this.renderEdits())); } return /*#__PURE__*/_react.default.createElement(_BaseDialog.default, { className: "mx_MessageEditHistoryDialog", hasCancel: true, onFinished: this.props.onFinished, title: (0, _languageHandler._t)("message_edit_dialog_title") }, content); } } exports.default = MessageEditHistoryDialog; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9tYXRyaXgiLCJfdXRpbHMiLCJfbG9nZ2VyIiwiX01hdHJpeENsaWVudFBlZyIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfRGF0ZVV0aWxzIiwiX1NldHRpbmdzU3RvcmUiLCJfQmFzZURpYWxvZyIsIl9TY3JvbGxQYW5lbCIsIl9TcGlubmVyIiwiX0VkaXRIaXN0b3J5TWVzc2FnZSIsIl9EYXRlU2VwYXJhdG9yIiwiTWVzc2FnZUVkaXRIaXN0b3J5RGlhbG9nIiwiUmVhY3QiLCJQdXJlQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiYmFja3dhcmRzIiwic3RhdGUiLCJuZXh0QmF0Y2giLCJpc0xvYWRpbmciLCJvcHRzIiwiZnJvbSIsInVuZGVmaW5lZCIsInJvb21JZCIsIm14RXZlbnQiLCJnZXRSb29tSWQiLCJldmVudElkIiwiZ2V0SWQiLCJjbGllbnQiLCJNYXRyaXhDbGllbnRQZWciLCJzYWZlR2V0IiwicmVzb2x2ZSIsInJlamVjdCIsInByb21pc2UiLCJkZWZlciIsInJlc3VsdCIsInJlbGF0aW9ucyIsIlJlbGF0aW9uVHlwZSIsIlJlcGxhY2UiLCJFdmVudFR5cGUiLCJSb29tTWVzc2FnZSIsImVycm9yIiwiTWF0cml4RXJyb3IiLCJlcnJjb2RlIiwibG9nZ2VyIiwic2V0U3RhdGUiLCJuZXdFdmVudHMiLCJldmVudHMiLCJsb2NhbGx5UmVkYWN0RXZlbnRzSWZOZWVkZWQiLCJvcmlnaW5hbEV2ZW50IiwiY29uY2F0IiwiaGFzTW9yZVJlc3VsdHMiLCJpc1R3ZWx2ZUhvdXIiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJyb29tIiwiZ2V0Um9vbSIsInBlbmRpbmdFdmVudHMiLCJnZXRQZW5kaW5nRXZlbnRzIiwiZSIsInBlbmRpbmdSZWRhY3Rpb24iLCJmaW5kIiwicGUiLCJnZXRUeXBlIiwiUm9vbVJlZGFjdGlvbiIsImdldEFzc29jaWF0ZWRJZCIsIm1hcmtMb2NhbGx5UmVkYWN0ZWQiLCJjb21wb25lbnREaWRNb3VudCIsImxvYWRNb3JlRWRpdHMiLCJyZW5kZXJFZGl0cyIsIm5vZGVzIiwibGFzdEV2ZW50IiwiYWxsRXZlbnRzIiwiYmFzZUV2ZW50SWQiLCJmb3JFYWNoIiwiaSIsIndhbnRzRGF0ZVNlcGFyYXRvciIsImdldERhdGUiLCJwdXNoIiwiY3JlYXRlRWxlbWVudCIsImtleSIsImdldFRzIiwidHMiLCJpc0Jhc2VFdmVudCIsInByZXZpb3VzRWRpdCIsInJlbmRlciIsImNvbnRlbnQiLCJjbGFzc05hbWUiLCJfdCIsIm9uRmlsbFJlcXVlc3QiLCJzdGlja3lCb3R0b20iLCJzdGFydEF0Qm90dG9tIiwiaGFzQ2FuY2VsIiwib25GaW5pc2hlZCIsInRpdGxlIiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL2RpYWxvZ3MvTWVzc2FnZUVkaXRIaXN0b3J5RGlhbG9nLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxOSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBNYXRyaXhFdmVudCwgRXZlbnRUeXBlLCBSZWxhdGlvblR5cGUsIE1hdHJpeENsaWVudCwgTWF0cml4RXJyb3IgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBkZWZlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy91dGlsc1wiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuXG5pbXBvcnQgeyBNYXRyaXhDbGllbnRQZWcgfSBmcm9tIFwiLi4vLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCB7IHdhbnRzRGF0ZVNlcGFyYXRvciB9IGZyb20gXCIuLi8uLi8uLi9EYXRlVXRpbHNcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuLi8uLi8uLi9zZXR0aW5ncy9TZXR0aW5nc1N0b3JlXCI7XG5pbXBvcnQgQmFzZURpYWxvZyBmcm9tIFwiLi9CYXNlRGlhbG9nXCI7XG5pbXBvcnQgU2Nyb2xsUGFuZWwgZnJvbSBcIi4uLy4uL3N0cnVjdHVyZXMvU2Nyb2xsUGFuZWxcIjtcbmltcG9ydCBTcGlubmVyIGZyb20gXCIuLi9lbGVtZW50cy9TcGlubmVyXCI7XG5pbXBvcnQgRWRpdEhpc3RvcnlNZXNzYWdlIGZyb20gXCIuLi9tZXNzYWdlcy9FZGl0SGlzdG9yeU1lc3NhZ2VcIjtcbmltcG9ydCBEYXRlU2VwYXJhdG9yIGZyb20gXCIuLi9tZXNzYWdlcy9EYXRlU2VwYXJhdG9yXCI7XG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIG14RXZlbnQ6IE1hdHJpeEV2ZW50O1xuICAgIG9uRmluaXNoZWQoKTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgb3JpZ2luYWxFdmVudDogTWF0cml4RXZlbnQgfCBudWxsO1xuICAgIGVycm9yOiBNYXRyaXhFcnJvciB8IG51bGw7XG4gICAgZXZlbnRzOiBNYXRyaXhFdmVudFtdO1xuICAgIG5leHRCYXRjaDogc3RyaW5nIHwgbnVsbDtcbiAgICBpc0xvYWRpbmc6IGJvb2xlYW47XG4gICAgaXNUd2VsdmVIb3VyOiBib29sZWFuO1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNZXNzYWdlRWRpdEhpc3RvcnlEaWFsb2cgZXh0ZW5kcyBSZWFjdC5QdXJlQ29tcG9uZW50PElQcm9wcywgSVN0YXRlPiB7XG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJUHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogbnVsbCxcbiAgICAgICAgICAgIGVycm9yOiBudWxsLFxuICAgICAgICAgICAgZXZlbnRzOiBbXSxcbiAgICAgICAgICAgIG5leHRCYXRjaDogbnVsbCxcbiAgICAgICAgICAgIGlzTG9hZGluZzogdHJ1ZSxcbiAgICAgICAgICAgIGlzVHdlbHZlSG91cjogU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcInNob3dUd2VsdmVIb3VyVGltZXN0YW1wc1wiKSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRNb3JlRWRpdHMgPSBhc3luYyAoYmFja3dhcmRzPzogYm9vbGVhbik6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAgICAgICBpZiAoYmFja3dhcmRzIHx8ICghdGhpcy5zdGF0ZS5uZXh0QmF0Y2ggJiYgIXRoaXMuc3RhdGUuaXNMb2FkaW5nKSkge1xuICAgICAgICAgICAgLy8gYmFpbCBvdXQgb24gYmFja3dhcmRzIGFzIHdlIG9ubHkgcGFnaW5hdGUgaW4gb25lIGRpcmVjdGlvblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG9wdHMgPSB7IGZyb206IHRoaXMuc3RhdGUubmV4dEJhdGNoID8/IHVuZGVmaW5lZCB9O1xuICAgICAgICBjb25zdCByb29tSWQgPSB0aGlzLnByb3BzLm14RXZlbnQuZ2V0Um9vbUlkKCkhO1xuICAgICAgICBjb25zdCBldmVudElkID0gdGhpcy5wcm9wcy5teEV2ZW50LmdldElkKCkhO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpO1xuXG4gICAgICAgIGNvbnN0IHsgcmVzb2x2ZSwgcmVqZWN0LCBwcm9taXNlIH0gPSBkZWZlcjxib29sZWFuPigpO1xuICAgICAgICBsZXQgcmVzdWx0OiBBd2FpdGVkPFJldHVyblR5cGU8TWF0cml4Q2xpZW50W1wicmVsYXRpb25zXCJdPj47XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IGNsaWVudC5yZWxhdGlvbnMocm9vbUlkLCBldmVudElkLCBSZWxhdGlvblR5cGUuUmVwbGFjZSwgRXZlbnRUeXBlLlJvb21NZXNzYWdlLCBvcHRzKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIC8vIGxvZyBpZiB0aGUgc2VydmVyIHJldHVybmVkIGFuIGVycm9yXG4gICAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBNYXRyaXhFcnJvciAmJiBlcnJvci5lcnJjb2RlKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiZmV0Y2hpbmcgL3JlbGF0aW9ucyBmYWlsZWQgd2l0aCBlcnJvclwiLCBlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgZXJyb3I6IGVycm9yIGFzIE1hdHJpeEVycm9yIH0sICgpID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuZXdFdmVudHMgPSByZXN1bHQuZXZlbnRzO1xuICAgICAgICB0aGlzLmxvY2FsbHlSZWRhY3RFdmVudHNJZk5lZWRlZChuZXdFdmVudHMpO1xuICAgICAgICB0aGlzLnNldFN0YXRlKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IHRoaXMuc3RhdGUub3JpZ2luYWxFdmVudCA/PyByZXN1bHQub3JpZ2luYWxFdmVudCA/PyBudWxsLFxuICAgICAgICAgICAgICAgIGV2ZW50czogdGhpcy5zdGF0ZS5ldmVudHMuY29uY2F0KG5ld0V2ZW50cyksXG4gICAgICAgICAgICAgICAgbmV4dEJhdGNoOiByZXN1bHQubmV4dEJhdGNoID8/IG51bGwsXG4gICAgICAgICAgICAgICAgaXNMb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgaGFzTW9yZVJlc3VsdHMgPSAhIXRoaXMuc3RhdGUubmV4dEJhdGNoO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoaGFzTW9yZVJlc3VsdHMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfTtcblxuICAgIHByaXZhdGUgbG9jYWxseVJlZGFjdEV2ZW50c0lmTmVlZGVkKG5ld0V2ZW50czogTWF0cml4RXZlbnRbXSk6IHZvaWQge1xuICAgICAgICBjb25zdCByb29tSWQgPSB0aGlzLnByb3BzLm14RXZlbnQuZ2V0Um9vbUlkKCk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG4gICAgICAgIGNvbnN0IHJvb20gPSBjbGllbnQuZ2V0Um9vbShyb29tSWQpO1xuICAgICAgICBpZiAoIXJvb20pIHJldHVybjtcbiAgICAgICAgY29uc3QgcGVuZGluZ0V2ZW50cyA9IHJvb20uZ2V0UGVuZGluZ0V2ZW50cygpO1xuICAgICAgICBmb3IgKGNvbnN0IGUgb2YgbmV3RXZlbnRzKSB7XG4gICAgICAgICAgICBjb25zdCBwZW5kaW5nUmVkYWN0aW9uID0gcGVuZGluZ0V2ZW50cy5maW5kKChwZSkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBwZS5nZXRUeXBlKCkgPT09IEV2ZW50VHlwZS5Sb29tUmVkYWN0aW9uICYmIHBlLmdldEFzc29jaWF0ZWRJZCgpID09PSBlLmdldElkKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChwZW5kaW5nUmVkYWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgZS5tYXJrTG9jYWxseVJlZGFjdGVkKHBlbmRpbmdSZWRhY3Rpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudERpZE1vdW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRNb3JlRWRpdHMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbmRlckVkaXRzKCk6IEpTWC5FbGVtZW50W10ge1xuICAgICAgICBjb25zdCBub2RlczogSlNYLkVsZW1lbnRbXSA9IFtdO1xuICAgICAgICBsZXQgbGFzdEV2ZW50OiBNYXRyaXhFdmVudDtcbiAgICAgICAgbGV0IGFsbEV2ZW50cyA9IHRoaXMuc3RhdGUuZXZlbnRzO1xuICAgICAgICAvLyBhcHBlbmQgb3JpZ2luYWwgZXZlbnQgd2hlbiB3ZSd2ZSBkb25lIGxhc3QgcGFnaW5hdGlvblxuICAgICAgICBpZiAodGhpcy5zdGF0ZS5vcmlnaW5hbEV2ZW50ICYmICF0aGlzLnN0YXRlLm5leHRCYXRjaCkge1xuICAgICAgICAgICAgYWxsRXZlbnRzID0gYWxsRXZlbnRzLmNvbmNhdCh0aGlzLnN0YXRlLm9yaWdpbmFsRXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJhc2VFdmVudElkID0gdGhpcy5wcm9wcy5teEV2ZW50LmdldElkKCk7XG4gICAgICAgIGFsbEV2ZW50cy5mb3JFYWNoKChlLCBpKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWxhc3RFdmVudCB8fCB3YW50c0RhdGVTZXBhcmF0b3IobGFzdEV2ZW50LmdldERhdGUoKSB8fCB1bmRlZmluZWQsIGUuZ2V0RGF0ZSgpIHx8IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgICAgICAgICBub2Rlcy5wdXNoKFxuICAgICAgICAgICAgICAgICAgICA8bGkga2V5PXtlLmdldFRzKCkgKyBcIn5cIn0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8RGF0ZVNlcGFyYXRvciByb29tSWQ9e2UuZ2V0Um9vbUlkKCkhfSB0cz17ZS5nZXRUcygpfSAvPlxuICAgICAgICAgICAgICAgICAgICA8L2xpPixcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaXNCYXNlRXZlbnQgPSBlLmdldElkKCkgPT09IGJhc2VFdmVudElkO1xuICAgICAgICAgICAgbm9kZXMucHVzaChcbiAgICAgICAgICAgICAgICA8RWRpdEhpc3RvcnlNZXNzYWdlXG4gICAgICAgICAgICAgICAgICAgIGtleT17ZS5nZXRJZCgpfVxuICAgICAgICAgICAgICAgICAgICBwcmV2aW91c0VkaXQ9eyFpc0Jhc2VFdmVudCA/IGFsbEV2ZW50c1tpICsgMV0gOiB1bmRlZmluZWR9XG4gICAgICAgICAgICAgICAgICAgIGlzQmFzZUV2ZW50PXtpc0Jhc2VFdmVudH1cbiAgICAgICAgICAgICAgICAgICAgbXhFdmVudD17ZX1cbiAgICAgICAgICAgICAgICAgICAgaXNUd2VsdmVIb3VyPXt0aGlzLnN0YXRlLmlzVHdlbHZlSG91cn1cbiAgICAgICAgICAgICAgICAvPixcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBsYXN0RXZlbnQgPSBlO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgbGV0IGNvbnRlbnQ7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmVycm9yKSB7XG4gICAgICAgICAgICBjb25zdCB7IGVycm9yIH0gPSB0aGlzLnN0YXRlO1xuICAgICAgICAgICAgaWYgKGVycm9yLmVycmNvZGUgPT09IFwiTV9VTlJFQ09HTklaRURcIikge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQgPSA8cCBjbGFzc05hbWU9XCJteF9NZXNzYWdlRWRpdEhpc3RvcnlEaWFsb2dfZXJyb3JcIj57X3QoXCJlcnJvcnxlZGl0X2hpc3RvcnlfdW5zdXBwb3J0ZWRcIil9PC9wPjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IuZXJyY29kZSkge1xuICAgICAgICAgICAgICAgIC8vIHNvbWUga2luZCBvZiBlcnJvciBmcm9tIHRoZSBob21lc2VydmVyXG4gICAgICAgICAgICAgICAgY29udGVudCA9IDxwIGNsYXNzTmFtZT1cIm14X01lc3NhZ2VFZGl0SGlzdG9yeURpYWxvZ19lcnJvclwiPntfdChcImVycm9yfHNvbWV0aGluZ193ZW50X3dyb25nXCIpfTwvcD47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQgPSAoXG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzTmFtZT1cIm14X01lc3NhZ2VFZGl0SGlzdG9yeURpYWxvZ19lcnJvclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge190KFwiY2Fubm90X3JlYWNoX2hvbWVzZXJ2ZXJcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnIgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcImNhbm5vdF9yZWFjaF9ob21lc2VydmVyX2RldGFpbFwiKX1cbiAgICAgICAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5pc0xvYWRpbmcpIHtcbiAgICAgICAgICAgIGNvbnRlbnQgPSA8U3Bpbm5lciAvPjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRlbnQgPSAoXG4gICAgICAgICAgICAgICAgPFNjcm9sbFBhbmVsXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X01lc3NhZ2VFZGl0SGlzdG9yeURpYWxvZ19zY3JvbGxQYW5lbFwiXG4gICAgICAgICAgICAgICAgICAgIG9uRmlsbFJlcXVlc3Q9e3RoaXMubG9hZE1vcmVFZGl0c31cbiAgICAgICAgICAgICAgICAgICAgc3RpY2t5Qm90dG9tPXtmYWxzZX1cbiAgICAgICAgICAgICAgICAgICAgc3RhcnRBdEJvdHRvbT17ZmFsc2V9XG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICA8dWwgY2xhc3NOYW1lPVwibXhfTWVzc2FnZUVkaXRIaXN0b3J5RGlhbG9nX2VkaXRzXCI+e3RoaXMucmVuZGVyRWRpdHMoKX08L3VsPlxuICAgICAgICAgICAgICAgIDwvU2Nyb2xsUGFuZWw+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8QmFzZURpYWxvZ1xuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X01lc3NhZ2VFZGl0SGlzdG9yeURpYWxvZ1wiXG4gICAgICAgICAgICAgICAgaGFzQ2FuY2VsPXt0cnVlfVxuICAgICAgICAgICAgICAgIG9uRmluaXNoZWQ9e3RoaXMucHJvcHMub25GaW5pc2hlZH1cbiAgICAgICAgICAgICAgICB0aXRsZT17X3QoXCJtZXNzYWdlX2VkaXRfZGlhbG9nX3RpdGxlXCIpfVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIHtjb250ZW50fVxuICAgICAgICAgICAgPC9CYXNlRGlhbG9nPlxuICAgICAgICApO1xuICAgIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFRQSxJQUFBQSxNQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxNQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxPQUFBLEdBQUFILE9BQUE7QUFFQSxJQUFBSSxnQkFBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssZ0JBQUEsR0FBQUwsT0FBQTtBQUNBLElBQUFNLFVBQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLGNBQUEsR0FBQVIsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFRLFdBQUEsR0FBQVQsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFTLFlBQUEsR0FBQVYsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFVLFFBQUEsR0FBQVgsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElB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