matrix-react-sdk
Version:
SDK for matrix.org using React
626 lines (620 loc) • 109 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.WYSIWYG_EDITOR_STATE_STORAGE_PREFIX = exports.MessageComposer = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _compoundWeb = require("@vector-im/compound-web");
var _logger = require("matrix-js-sdk/src/logger");
var _languageHandler = require("../../../languageHandler");
var _MatrixClientPeg = require("../../../MatrixClientPeg");
var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher"));
var _Stickerpicker = _interopRequireDefault(require("./Stickerpicker"));
var _Permalinks = require("../../../utils/permalinks/Permalinks");
var _E2EIcon = _interopRequireDefault(require("./E2EIcon"));
var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore"));
var _ContextMenu = require("../../structures/ContextMenu");
var _ReplyPreview = _interopRequireDefault(require("./ReplyPreview"));
var _AsyncStore = require("../../../stores/AsyncStore");
var _VoiceRecordComposerTile = _interopRequireDefault(require("./VoiceRecordComposerTile"));
var _VoiceRecordingStore = require("../../../stores/VoiceRecordingStore");
var _VoiceRecording = require("../../../audio/VoiceRecording");
var _SendMessageComposer = _interopRequireDefault(require("./SendMessageComposer"));
var _actions = require("../../../dispatcher/actions");
var _UIStore = _interopRequireWildcard(require("../../../stores/UIStore"));
var _RoomContext = _interopRequireDefault(require("../../../contexts/RoomContext"));
var _MessageComposerButtons = _interopRequireDefault(require("./MessageComposerButtons"));
var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton"));
var _isLocalRoom = require("../../../utils/localRoom/isLocalRoom");
var _Settings = require("../../../settings/Settings");
var _wysiwyg_composer = require("./wysiwyg_composer/");
var _MatrixClientContext = require("../../../contexts/MatrixClientContext");
var _setUpVoiceBroadcastPreRecording = require("../../../voice-broadcast/utils/setUpVoiceBroadcastPreRecording");
var _SDKContext = require("../../../contexts/SDKContext");
var _voiceBroadcast = require("../../../voice-broadcast");
var _CantStartVoiceMessageBroadcastDialog = require("../dialogs/CantStartVoiceMessageBroadcastDialog");
var _UIFeature = require("../../../settings/UIFeature");
var _DateUtils = require("../../../DateUtils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/*
Copyright 2024 New Vector Ltd.
Copyright 2015-2022 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.
*/
// The prefix used when persisting editor drafts to localstorage.
const WYSIWYG_EDITOR_STATE_STORAGE_PREFIX = exports.WYSIWYG_EDITOR_STATE_STORAGE_PREFIX = "mx_wysiwyg_state_";
let instanceCount = 0;
function SendButton(props) {
return /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
className: "mx_MessageComposer_sendMessage",
onClick: props.onClick,
title: props.title ?? (0, _languageHandler._t)("composer|send_button_title"),
"data-testid": "sendmessagebtn"
});
}
class MessageComposer extends _react.default.Component {
constructor(props, context) {
super(props, context);
(0, _defineProperty2.default)(this, "dispatcherRef", void 0);
(0, _defineProperty2.default)(this, "messageComposerInput", /*#__PURE__*/(0, _react.createRef)());
(0, _defineProperty2.default)(this, "voiceRecordingButton", /*#__PURE__*/(0, _react.createRef)());
(0, _defineProperty2.default)(this, "ref", /*#__PURE__*/(0, _react.createRef)());
(0, _defineProperty2.default)(this, "instanceId", void 0);
(0, _defineProperty2.default)(this, "_voiceRecording", void 0);
(0, _defineProperty2.default)(this, "saveWysiwygEditorState", () => {
if (this.shouldSaveWysiwygEditorState()) {
const {
isRichTextEnabled,
composerContent
} = this.state;
const replyEventId = this.props.replyToEvent ? this.props.replyToEvent.getId() : undefined;
const item = {
content: composerContent,
isRichText: isRichTextEnabled,
replyEventId: replyEventId
};
localStorage.setItem(this.editorStateKey, JSON.stringify(item));
} else {
this.clearStoredEditorState();
}
});
// should save state when wysiwyg is enabled and has contents or reply is open
(0, _defineProperty2.default)(this, "shouldSaveWysiwygEditorState", () => {
const {
isWysiwygLabEnabled,
isComposerEmpty
} = this.state;
return isWysiwygLabEnabled && (!isComposerEmpty || !!this.props.replyToEvent);
});
(0, _defineProperty2.default)(this, "onResize", (type, entry) => {
if (type === _UIStore.UI_EVENTS.Resize) {
const {
narrow
} = this.context;
this.setState({
isMenuOpen: !narrow ? false : this.state.isMenuOpen,
isStickerPickerOpen: false
});
}
});
(0, _defineProperty2.default)(this, "onAction", payload => {
switch (payload.action) {
case "reply_to_event":
if (payload.context === this.context.timelineRenderingType) {
// add a timeout for the reply preview to be rendered, so
// that the ScrollPanel listening to the resizeNotifier can
// correctly measure it's new height and scroll down to keep
// at the bottom if it already is
window.setTimeout(() => {
this.props.resizeNotifier.notifyTimelineHeightChanged();
}, 100);
}
break;
case _actions.Action.SettingUpdated:
{
const settingUpdatedPayload = payload;
switch (settingUpdatedPayload.settingName) {
case "MessageComposerInput.showStickersButton":
{
const showStickersButton = _SettingsStore.default.getValue("MessageComposerInput.showStickersButton");
if (this.state.showStickersButton !== showStickersButton) {
this.setState({
showStickersButton
});
}
break;
}
case "MessageComposerInput.showPollsButton":
{
const showPollsButton = _SettingsStore.default.getValue("MessageComposerInput.showPollsButton");
if (this.state.showPollsButton !== showPollsButton) {
this.setState({
showPollsButton
});
}
break;
}
case _Settings.Features.VoiceBroadcast:
{
if (this.state.showVoiceBroadcastButton !== settingUpdatedPayload.newValue) {
this.setState({
showVoiceBroadcastButton: !!settingUpdatedPayload.newValue
});
}
break;
}
case "feature_wysiwyg_composer":
{
if (this.state.isWysiwygLabEnabled !== settingUpdatedPayload.newValue) {
this.setState({
isWysiwygLabEnabled: Boolean(settingUpdatedPayload.newValue)
});
}
break;
}
}
}
}
});
(0, _defineProperty2.default)(this, "onTombstoneClick", ev => {
ev.preventDefault();
const replacementRoomId = this.context.tombstone?.getContent()["replacement_room"];
const replacementRoom = _MatrixClientPeg.MatrixClientPeg.safeGet().getRoom(replacementRoomId);
let createEventId;
if (replacementRoom) {
const createEvent = replacementRoom.currentState.getStateEvents(_matrix.EventType.RoomCreate, "");
if (createEvent?.getId()) createEventId = createEvent.getId();
}
const sender = this.context.tombstone?.getSender();
const viaServers = sender ? [sender.split(":").slice(1).join(":")] : undefined;
_dispatcher.default.dispatch({
action: _actions.Action.ViewRoom,
highlighted: true,
event_id: createEventId,
room_id: replacementRoomId,
auto_join: true,
// Try to join via the server that sent the event. This converts @something:example.org
// into a server domain by splitting on colons and ignoring the first entry ("@something").
via_servers: viaServers,
metricsTrigger: "Tombstone",
metricsViaKeyboard: ev.type !== "click"
});
});
(0, _defineProperty2.default)(this, "renderPlaceholderText", () => {
if (this.props.replyToEvent) {
const replyingToThread = this.props.relation?.rel_type === _matrix.THREAD_RELATION_TYPE.name;
if (replyingToThread && this.props.e2eStatus) {
return (0, _languageHandler._t)("composer|placeholder_thread_encrypted");
} else if (replyingToThread) {
return (0, _languageHandler._t)("composer|placeholder_thread");
} else if (this.props.e2eStatus) {
return (0, _languageHandler._t)("composer|placeholder_reply_encrypted");
} else {
return (0, _languageHandler._t)("composer|placeholder_reply");
}
} else {
if (this.props.e2eStatus) {
return (0, _languageHandler._t)("composer|placeholder_encrypted");
} else {
return (0, _languageHandler._t)("composer|placeholder");
}
}
});
(0, _defineProperty2.default)(this, "addEmoji", emoji => {
_dispatcher.default.dispatch({
action: _actions.Action.ComposerInsert,
text: emoji,
timelineRenderingType: this.context.timelineRenderingType
});
return true;
});
(0, _defineProperty2.default)(this, "sendMessage", async () => {
if (this.state.haveRecording && this.voiceRecordingButton.current) {
// There shouldn't be any text message to send when a voice recording is active, so
// just send out the voice recording.
await this.voiceRecordingButton.current?.send();
return;
}
this.messageComposerInput.current?.sendMessage();
if (this.state.isWysiwygLabEnabled) {
const {
permalinkCreator,
relation,
replyToEvent
} = this.props;
const composerContent = this.state.composerContent;
this.setState({
composerContent: "",
initialComposerContent: ""
});
_dispatcher.default.dispatch({
action: _actions.Action.ClearAndFocusSendMessageComposer,
timelineRenderingType: this.context.timelineRenderingType
});
await (0, _wysiwyg_composer.sendMessage)(composerContent, this.state.isRichTextEnabled, {
mxClient: this.props.mxClient,
roomContext: this.context,
permalinkCreator,
relation,
replyToEvent
});
}
});
(0, _defineProperty2.default)(this, "onChange", model => {
this.setState({
isComposerEmpty: model.isEmpty
});
});
(0, _defineProperty2.default)(this, "onWysiwygChange", content => {
this.setState({
composerContent: content,
isComposerEmpty: content?.length === 0
});
});
(0, _defineProperty2.default)(this, "onRichTextToggle", async () => {
const {
richToPlain,
plainToRich
} = await (0, _wysiwyg_composer.getConversionFunctions)();
const {
isRichTextEnabled,
composerContent
} = this.state;
const convertedContent = isRichTextEnabled ? await richToPlain(composerContent, false) : await plainToRich(composerContent, false);
this.setState({
isRichTextEnabled: !isRichTextEnabled,
composerContent: convertedContent,
initialComposerContent: convertedContent
});
});
(0, _defineProperty2.default)(this, "onVoiceStoreUpdate", () => {
this.updateRecordingState();
});
(0, _defineProperty2.default)(this, "onRecordingStarted", () => {
// update the recording instance, just in case
const voiceRecordingId = _VoiceRecordingStore.VoiceRecordingStore.getVoiceRecordingId(this.props.room, this.props.relation);
this.voiceRecording = _VoiceRecordingStore.VoiceRecordingStore.instance.getActiveRecording(voiceRecordingId);
this.setState({
haveRecording: !!this.voiceRecording
});
});
(0, _defineProperty2.default)(this, "onRecordingEndingSoon", ({
secondsLeft
}) => {
this.setState({
recordingTimeLeftSeconds: secondsLeft
});
window.setTimeout(() => this.setState({
recordingTimeLeftSeconds: undefined
}), 3000);
});
(0, _defineProperty2.default)(this, "setStickerPickerOpen", isStickerPickerOpen => {
this.setState({
isStickerPickerOpen,
isMenuOpen: false
});
});
(0, _defineProperty2.default)(this, "toggleStickerPickerOpen", () => {
this.setStickerPickerOpen(!this.state.isStickerPickerOpen);
});
(0, _defineProperty2.default)(this, "toggleButtonMenu", () => {
this.setState({
isMenuOpen: !this.state.isMenuOpen
});
});
(0, _defineProperty2.default)(this, "onRecordStartEndClick", () => {
const currentBroadcastRecording = _SDKContext.SdkContextClass.instance.voiceBroadcastRecordingsStore.getCurrent();
if (currentBroadcastRecording && currentBroadcastRecording.getState() !== _voiceBroadcast.VoiceBroadcastInfoState.Stopped) {
(0, _CantStartVoiceMessageBroadcastDialog.createCantStartVoiceMessageBroadcastDialog)();
} else {
this.voiceRecordingButton.current?.onRecordStartEndClick();
}
if (this.context.narrow) {
this.toggleButtonMenu();
}
});
this.context = context; // otherwise React will only set it prior to render due to type def above
_VoiceRecordingStore.VoiceRecordingStore.instance.on(_AsyncStore.UPDATE_EVENT, this.onVoiceStoreUpdate);
window.addEventListener("beforeunload", this.saveWysiwygEditorState);
const _isWysiwygLabEnabled = _SettingsStore.default.getValue("feature_wysiwyg_composer");
let _isRichTextEnabled = true;
let initialComposerContent = "";
if (_isWysiwygLabEnabled) {
const wysiwygState = this.restoreWysiwygEditorState();
if (wysiwygState) {
_isRichTextEnabled = wysiwygState.isRichText;
initialComposerContent = wysiwygState.content;
if (wysiwygState.replyEventId) {
_dispatcher.default.dispatch({
action: "reply_to_event",
event: this.props.room.findEventById(wysiwygState.replyEventId),
context: this.context.timelineRenderingType
});
}
}
}
this.state = {
isComposerEmpty: initialComposerContent?.length === 0,
composerContent: initialComposerContent,
haveRecording: false,
recordingTimeLeftSeconds: undefined,
// when set to a number, shows a toast
isMenuOpen: false,
isStickerPickerOpen: false,
showStickersButton: _SettingsStore.default.getValue("MessageComposerInput.showStickersButton"),
showPollsButton: _SettingsStore.default.getValue("MessageComposerInput.showPollsButton"),
showVoiceBroadcastButton: _SettingsStore.default.getValue(_Settings.Features.VoiceBroadcast),
isWysiwygLabEnabled: _isWysiwygLabEnabled,
isRichTextEnabled: _isRichTextEnabled,
initialComposerContent: initialComposerContent
};
this.instanceId = instanceCount++;
_SettingsStore.default.monitorSetting("MessageComposerInput.showStickersButton", null);
_SettingsStore.default.monitorSetting("MessageComposerInput.showPollsButton", null);
_SettingsStore.default.monitorSetting(_Settings.Features.VoiceBroadcast, null);
_SettingsStore.default.monitorSetting("feature_wysiwyg_composer", null);
}
get editorStateKey() {
let key = WYSIWYG_EDITOR_STATE_STORAGE_PREFIX + this.props.room.roomId;
if (this.props.relation?.rel_type === _matrix.THREAD_RELATION_TYPE.name) {
key += `_${this.props.relation.event_id}`;
}
return key;
}
restoreWysiwygEditorState() {
const json = localStorage.getItem(this.editorStateKey);
if (json) {
try {
const state = JSON.parse(json);
return state;
} catch (e) {
_logger.logger.error(e);
}
}
return undefined;
}
clearStoredEditorState() {
localStorage.removeItem(this.editorStateKey);
}
get voiceRecording() {
return this._voiceRecording;
}
set voiceRecording(rec) {
if (this._voiceRecording) {
this._voiceRecording.off(_VoiceRecording.RecordingState.Started, this.onRecordingStarted);
this._voiceRecording.off(_VoiceRecording.RecordingState.EndingSoon, this.onRecordingEndingSoon);
}
this._voiceRecording = rec;
if (rec) {
// Delay saying we have a recording until it is started, as we might not yet
// have A/V permissions
rec.on(_VoiceRecording.RecordingState.Started, this.onRecordingStarted);
// We show a little heads up that the recording is about to automatically end soon. The 3s
// display time is completely arbitrary.
rec.on(_VoiceRecording.RecordingState.EndingSoon, this.onRecordingEndingSoon);
}
}
componentDidMount() {
this.dispatcherRef = _dispatcher.default.register(this.onAction);
this.waitForOwnMember();
_UIStore.default.instance.trackElementDimensions(`MessageComposer${this.instanceId}`, this.ref.current);
_UIStore.default.instance.on(`MessageComposer${this.instanceId}`, this.onResize);
this.updateRecordingState(); // grab any cached recordings
}
waitForOwnMember() {
// If we have the member already, do that
const me = this.props.room.getMember(_MatrixClientPeg.MatrixClientPeg.safeGet().getUserId());
if (me) {
this.setState({
me
});
return;
}
// Otherwise, wait for member loading to finish and then update the member for the avatar.
// The members should already be loading, and loadMembersIfNeeded
// will return the promise for the existing operation
this.props.room.loadMembersIfNeeded().then(() => {
const me = this.props.room.getMember(_MatrixClientPeg.MatrixClientPeg.safeGet().getSafeUserId()) ?? undefined;
this.setState({
me
});
});
}
componentWillUnmount() {
_VoiceRecordingStore.VoiceRecordingStore.instance.off(_AsyncStore.UPDATE_EVENT, this.onVoiceStoreUpdate);
if (this.dispatcherRef) _dispatcher.default.unregister(this.dispatcherRef);
_UIStore.default.instance.stopTrackingElementDimensions(`MessageComposer${this.instanceId}`);
_UIStore.default.instance.removeListener(`MessageComposer${this.instanceId}`, this.onResize);
window.removeEventListener("beforeunload", this.saveWysiwygEditorState);
this.saveWysiwygEditorState();
// clean up our listeners by setting our cached recording to falsy (see internal setter)
this.voiceRecording = null;
}
updateRecordingState() {
const voiceRecordingId = _VoiceRecordingStore.VoiceRecordingStore.getVoiceRecordingId(this.props.room, this.props.relation);
this.voiceRecording = _VoiceRecordingStore.VoiceRecordingStore.instance.getActiveRecording(voiceRecordingId);
if (this.voiceRecording) {
// If the recording has already started, it's probably a cached one.
if (this.voiceRecording.hasRecording && !this.voiceRecording.isRecording) {
this.setState({
haveRecording: true
});
}
// Note: Listeners for recording states are set by the `this.voiceRecording` setter.
} else {
this.setState({
haveRecording: false
});
}
}
get showStickersButton() {
return this.state.showStickersButton && !(0, _isLocalRoom.isLocalRoom)(this.props.room);
}
getMenuPosition() {
if (this.ref.current) {
const hasFormattingButtons = this.state.isWysiwygLabEnabled && this.state.isRichTextEnabled;
const contentRect = this.ref.current.getBoundingClientRect();
// Here we need to remove the all the extra space above the editor
// Instead of doing a querySelector or pass a ref to find the compute the height formatting buttons
// We are using an arbitrary value, the formatting buttons height doesn't change during the lifecycle of the component
// It's easier to just use a constant here instead of an over-engineering way to find the height
const heightToRemove = hasFormattingButtons ? 36 : 0;
const fixedRect = new DOMRect(contentRect.x, contentRect.y + heightToRemove, contentRect.width, contentRect.height - heightToRemove);
return (0, _ContextMenu.aboveLeftOf)(fixedRect);
}
}
render() {
const hasE2EIcon = Boolean(!this.state.isWysiwygLabEnabled && this.props.e2eStatus);
const e2eIcon = hasE2EIcon && /*#__PURE__*/_react.default.createElement("div", {
className: "mx_MessageComposer_e2eIconWrapper"
}, /*#__PURE__*/_react.default.createElement(_E2EIcon.default, {
key: "e2eIcon",
status: this.props.e2eStatus,
className: "mx_MessageComposer_e2eIcon"
}));
const controls = [];
const menuPosition = this.getMenuPosition();
const canSendMessages = this.context.canSendMessages && !this.context.tombstone;
let composer;
if (canSendMessages) {
if (this.state.isWysiwygLabEnabled && menuPosition) {
composer = /*#__PURE__*/_react.default.createElement(_wysiwyg_composer.SendWysiwygComposer, {
key: "controls_input",
disabled: this.state.haveRecording,
onChange: this.onWysiwygChange,
onSend: this.sendMessage,
isRichTextEnabled: this.state.isRichTextEnabled,
initialContent: this.state.initialComposerContent,
e2eStatus: this.props.e2eStatus,
menuPosition: menuPosition,
placeholder: this.renderPlaceholderText(),
eventRelation: this.props.relation
});
} else {
composer = /*#__PURE__*/_react.default.createElement(_SendMessageComposer.default, {
ref: this.messageComposerInput,
key: "controls_input",
room: this.props.room,
placeholder: this.renderPlaceholderText(),
permalinkCreator: this.props.permalinkCreator,
relation: this.props.relation,
replyToEvent: this.props.replyToEvent,
onChange: this.onChange,
disabled: this.state.haveRecording,
toggleStickerPickerOpen: this.toggleStickerPickerOpen
});
}
controls.push( /*#__PURE__*/_react.default.createElement(_VoiceRecordComposerTile.default, {
key: "controls_voice_record",
ref: this.voiceRecordingButton,
room: this.props.room,
permalinkCreator: this.props.permalinkCreator,
relation: this.props.relation,
replyToEvent: this.props.replyToEvent
}));
} else if (this.context.tombstone) {
const replacementRoomId = this.context.tombstone.getContent()["replacement_room"];
const continuesLink = replacementRoomId ? /*#__PURE__*/_react.default.createElement("a", {
href: (0, _Permalinks.makeRoomPermalink)(_MatrixClientPeg.MatrixClientPeg.safeGet(), replacementRoomId),
className: "mx_MessageComposer_roomReplaced_link",
onClick: this.onTombstoneClick
}, (0, _languageHandler._t)("composer|room_upgraded_link")) : "";
controls.push( /*#__PURE__*/_react.default.createElement("div", {
className: "mx_MessageComposer_replaced_wrapper",
key: "room_replaced"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_MessageComposer_replaced_valign"
}, /*#__PURE__*/_react.default.createElement("img", {
"aria-hidden": true,
alt: "",
className: "mx_MessageComposer_roomReplaced_icon",
src: require("../../../../res/img/room_replaced.svg").default
}), /*#__PURE__*/_react.default.createElement("span", {
className: "mx_MessageComposer_roomReplaced_header"
}, (0, _languageHandler._t)("composer|room_upgraded_notice")), /*#__PURE__*/_react.default.createElement("br", null), continuesLink)));
} else {
controls.push( /*#__PURE__*/_react.default.createElement("div", {
key: "controls_error",
className: "mx_MessageComposer_noperm_error"
}, (0, _languageHandler._t)("composer|no_perms_notice")));
}
let recordingTooltip;
const isTooltipOpen = Boolean(this.state.recordingTimeLeftSeconds);
const secondsLeft = this.state.recordingTimeLeftSeconds ? Math.round(this.state.recordingTimeLeftSeconds) : 0;
const threadId = this.props.relation?.rel_type === _matrix.THREAD_RELATION_TYPE.name ? this.props.relation.event_id : null;
controls.push( /*#__PURE__*/_react.default.createElement(_Stickerpicker.default, {
room: this.props.room,
threadId: threadId,
isStickerPickerOpen: this.state.isStickerPickerOpen,
setStickerPickerOpen: this.setStickerPickerOpen,
menuPosition: menuPosition,
key: "stickers"
}));
const showSendButton = canSendMessages && (!this.state.isComposerEmpty || this.state.haveRecording);
const classes = (0, _classnames.default)({
"mx_MessageComposer": true,
"mx_MessageComposer--compact": this.props.compact,
"mx_MessageComposer_e2eStatus": hasE2EIcon,
"mx_MessageComposer_wysiwyg": this.state.isWysiwygLabEnabled
});
return /*#__PURE__*/_react.default.createElement(_compoundWeb.Tooltip, {
open: isTooltipOpen,
description: (0, _DateUtils.formatTimeLeft)(secondsLeft),
placement: "bottom"
}, /*#__PURE__*/_react.default.createElement("div", {
className: classes,
ref: this.ref,
role: "region",
"aria-label": (0, _languageHandler._t)("a11y|message_composer")
}, recordingTooltip, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_MessageComposer_wrapper"
}, /*#__PURE__*/_react.default.createElement(_ReplyPreview.default, {
replyToEvent: this.props.replyToEvent,
permalinkCreator: this.props.permalinkCreator
}), /*#__PURE__*/_react.default.createElement("div", {
className: "mx_MessageComposer_row"
}, e2eIcon, composer, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_MessageComposer_actions"
}, controls, canSendMessages && /*#__PURE__*/_react.default.createElement(_MessageComposerButtons.default, {
addEmoji: this.addEmoji,
haveRecording: this.state.haveRecording,
isMenuOpen: this.state.isMenuOpen,
isStickerPickerOpen: this.state.isStickerPickerOpen,
menuPosition: menuPosition,
relation: this.props.relation,
onRecordStartEndClick: this.onRecordStartEndClick,
setStickerPickerOpen: this.setStickerPickerOpen,
showLocationButton: !window.electron && _SettingsStore.default.getValue(_UIFeature.UIFeature.LocationSharing),
showPollsButton: this.state.showPollsButton,
showStickersButton: this.showStickersButton,
isRichTextEnabled: this.state.isRichTextEnabled,
onComposerModeClick: this.onRichTextToggle,
toggleButtonMenu: this.toggleButtonMenu,
showVoiceBroadcastButton: this.state.showVoiceBroadcastButton,
onStartVoiceBroadcastClick: () => {
(0, _setUpVoiceBroadcastPreRecording.setUpVoiceBroadcastPreRecording)(this.props.room, _MatrixClientPeg.MatrixClientPeg.safeGet(), _SDKContext.SdkContextClass.instance.voiceBroadcastPlaybacksStore, _SDKContext.SdkContextClass.instance.voiceBroadcastRecordingsStore, _SDKContext.SdkContextClass.instance.voiceBroadcastPreRecordingStore);
this.toggleButtonMenu();
}
}), showSendButton && /*#__PURE__*/_react.default.createElement(SendButton, {
key: "controls_send",
onClick: this.sendMessage,
title: this.state.haveRecording ? (0, _languageHandler._t)("composer|send_button_voice_message") : undefined
}))))));
}
}
exports.MessageComposer = MessageComposer;
(0, _defineProperty2.default)(MessageComposer, "contextType", _RoomContext.default);
(0, _defineProperty2.default)(MessageComposer, "defaultProps", {
compact: false,
showVoiceBroadcastButton: false,
isRichTextEnabled: true
});
const MessageComposerWithMatrixClient = (0, _MatrixClientContext.withMatrixClientHOC)(MessageComposer);
var _default = exports.default = MessageComposerWithMatrixClient;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfY2xhc3NuYW1lcyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfbWF0cml4IiwiX2NvbXBvdW5kV2ViIiwiX2xvZ2dlciIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfTWF0cml4Q2xpZW50UGVnIiwiX2Rpc3BhdGNoZXIiLCJfU3RpY2tlcnBpY2tlciIsIl9QZXJtYWxpbmtzIiwiX0UyRUljb24iLCJfU2V0dGluZ3NTdG9yZSIsIl9Db250ZXh0TWVudSIsIl9SZXBseVByZXZpZXciLCJfQXN5bmNTdG9yZSIsIl9Wb2ljZVJlY29yZENvbXBvc2VyVGlsZSIsIl9Wb2ljZVJlY29yZGluZ1N0b3JlIiwiX1ZvaWNlUmVjb3JkaW5nIiwiX1NlbmRNZXNzYWdlQ29tcG9zZXIiLCJfYWN0aW9ucyIsIl9VSVN0b3JlIiwiX1Jvb21Db250ZXh0IiwiX01lc3NhZ2VDb21wb3NlckJ1dHRvbnMiLCJfQWNjZXNzaWJsZUJ1dHRvbiIsIl9pc0xvY2FsUm9vbSIsIl9TZXR0aW5ncyIsIl93eXNpd3lnX2NvbXBvc2VyIiwiX01hdHJpeENsaWVudENvbnRleHQiLCJfc2V0VXBWb2ljZUJyb2FkY2FzdFByZVJlY29yZGluZyIsIl9TREtDb250ZXh0IiwiX3ZvaWNlQnJvYWRjYXN0IiwiX0NhbnRTdGFydFZvaWNlTWVzc2FnZUJyb2FkY2FzdERpYWxvZyIsIl9VSUZlYXR1cmUiLCJfRGF0ZVV0aWxzIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0IiwiV1lTSVdZR19FRElUT1JfU1RBVEVfU1RPUkFHRV9QUkVGSVgiLCJleHBvcnRzIiwiaW5zdGFuY2VDb3VudCIsIlNlbmRCdXR0b24iLCJwcm9wcyIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc05hbWUiLCJvbkNsaWNrIiwidGl0bGUiLCJfdCIsIk1lc3NhZ2VDb21wb3NlciIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJjb250ZXh0IiwiX2RlZmluZVByb3BlcnR5MiIsImNyZWF0ZVJlZiIsInNob3VsZFNhdmVXeXNpd3lnRWRpdG9yU3RhdGUiLCJpc1JpY2hUZXh0RW5hYmxlZCIsImNvbXBvc2VyQ29udGVudCIsInN0YXRlIiwicmVwbHlFdmVudElkIiwicmVwbHlUb0V2ZW50IiwiZ2V0SWQiLCJ1bmRlZmluZWQiLCJpdGVtIiwiY29udGVudCIsImlzUmljaFRleHQiLCJsb2NhbFN0b3JhZ2UiLCJzZXRJdGVtIiwiZWRpdG9yU3RhdGVLZXkiLCJKU09OIiwic3RyaW5naWZ5IiwiY2xlYXJTdG9yZWRFZGl0b3JTdGF0ZSIsImlzV3lzaXd5Z0xhYkVuYWJsZWQiLCJpc0NvbXBvc2VyRW1wdHkiLCJ0eXBlIiwiZW50cnkiLCJVSV9FVkVOVFMiLCJSZXNpemUiLCJuYXJyb3ciLCJzZXRTdGF0ZSIsImlzTWVudU9wZW4iLCJpc1N0aWNrZXJQaWNrZXJPcGVuIiwicGF5bG9hZCIsImFjdGlvbiIsInRpbWVsaW5lUmVuZGVyaW5nVHlwZSIsIndpbmRvdyIsInNldFRpbWVvdXQiLCJyZXNpemVOb3RpZmllciIsIm5vdGlmeVRpbWVsaW5lSGVpZ2h0Q2hhbmdlZCIsIkFjdGlvbiIsIlNldHRpbmdVcGRhdGVkIiwic2V0dGluZ1VwZGF0ZWRQYXlsb2FkIiwic2V0dGluZ05hbWUiLCJzaG93U3RpY2tlcnNCdXR0b24iLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJzaG93UG9sbHNCdXR0b24iLCJGZWF0dXJlcyIsIlZvaWNlQnJvYWRjYXN0Iiwic2hvd1ZvaWNlQnJvYWRjYXN0QnV0dG9uIiwibmV3VmFsdWUiLCJCb29sZWFuIiwiZXYiLCJwcmV2ZW50RGVmYXVsdCIsInJlcGxhY2VtZW50Um9vbUlkIiwidG9tYnN0b25lIiwiZ2V0Q29udGVudCIsInJlcGxhY2VtZW50Um9vbSIsIk1hdHJpeENsaWVudFBlZyIsInNhZmVHZXQiLCJnZXRSb29tIiwiY3JlYXRlRXZlbnRJZCIsImNyZWF0ZUV2ZW50IiwiY3VycmVudFN0YXRlIiwiZ2V0U3RhdGVFdmVudHMiLCJFdmVudFR5cGUiLCJSb29tQ3JlYXRlIiwic2VuZGVyIiwiZ2V0U2VuZGVyIiwidmlhU2VydmVycyIsInNwbGl0Iiwic2xpY2UiLCJqb2luIiwiZGlzIiwiZGlzcGF0Y2giLCJWaWV3Um9vbSIsImhpZ2hsaWdodGVkIiwiZXZlbnRfaWQiLCJyb29tX2lkIiwiYXV0b19qb2luIiwidmlhX3NlcnZlcnMiLCJtZXRyaWNzVHJpZ2dlciIsIm1ldHJpY3NWaWFLZXlib2FyZCIsInJlcGx5aW5nVG9UaHJlYWQiLCJyZWxhdGlvbiIsInJlbF90eXBlIiwiVEhSRUFEX1JFTEFUSU9OX1RZUEUiLCJuYW1lIiwiZTJlU3RhdHVzIiwiZW1vamkiLCJDb21wb3Nlckluc2VydCIsInRleHQiLCJoYXZlUmVjb3JkaW5nIiwidm9pY2VSZWNvcmRpbmdCdXR0b24iLCJjdXJyZW50Iiwic2VuZCIsIm1lc3NhZ2VDb21wb3NlcklucHV0Iiwic2VuZE1lc3NhZ2UiLCJwZXJtYWxpbmtDcmVhdG9yIiwiaW5pdGlhbENvbXBvc2VyQ29udGVudCIsIkNsZWFyQW5kRm9jdXNTZW5kTWVzc2FnZUNvbXBvc2VyIiwibXhDbGllbnQiLCJyb29tQ29udGV4dCIsIm1vZGVsIiwiaXNFbXB0eSIsImxlbmd0aCIsInJpY2hUb1BsYWluIiwicGxhaW5Ub1JpY2giLCJnZXRDb252ZXJzaW9uRnVuY3Rpb25zIiwiY29udmVydGVkQ29udGVudCIsInVwZGF0ZVJlY29yZGluZ1N0YXRlIiwidm9pY2VSZWNvcmRpbmdJZCIsIlZvaWNlUmVjb3JkaW5nU3RvcmUiLCJnZXRWb2ljZVJlY29yZGluZ0lkIiwicm9vbSIsInZvaWNlUmVjb3JkaW5nIiwiaW5zdGFuY2UiLCJnZXRBY3RpdmVSZWNvcmRpbmciLCJzZWNvbmRzTGVmdCIsInJlY29yZGluZ1RpbWVMZWZ0U2Vjb25kcyIsInNldFN0aWNrZXJQaWNrZXJPcGVuIiwiY3VycmVudEJyb2FkY2FzdFJlY29yZGluZyIsIlNka0NvbnRleHRDbGFzcyIsInZvaWNlQnJvYWRjYXN0UmVjb3JkaW5nc1N0b3JlIiwiZ2V0Q3VycmVudCIsImdldFN0YXRlIiwiVm9pY2VCcm9hZGNhc3RJbmZvU3RhdGUiLCJTdG9wcGVkIiwiY3JlYXRlQ2FudFN0YXJ0Vm9pY2VNZXNzYWdlQnJvYWRjYXN0RGlhbG9nIiwib25SZWNvcmRTdGFydEVuZENsaWNrIiwidG9nZ2xlQnV0dG9uTWVudSIsIm9uIiwiVVBEQVRFX0VWRU5UIiwib25Wb2ljZVN0b3JlVXBkYXRlIiwiYWRkRXZlbnRMaXN0ZW5lciIsInNhdmVXeXNpd3lnRWRpdG9yU3RhdGUiLCJ3eXNpd3lnU3RhdGUiLCJyZXN0b3JlV3lzaXd5Z0VkaXRvclN0YXRlIiwiZXZlbnQiLCJmaW5kRXZlbnRCeUlkIiwiaW5zdGFuY2VJZCIsIm1vbml0b3JTZXR0aW5nIiwia2V5Iiwicm9vbUlkIiwianNvbiIsImdldEl0ZW0iLCJwYXJzZSIsImxvZ2dlciIsImVycm9yIiwicmVtb3ZlSXRlbSIsIl92b2ljZVJlY29yZGluZyIsInJlYyIsIm9mZiIsIlJlY29yZGluZ1N0YXRlIiwiU3RhcnRlZCIsIm9uUmVjb3JkaW5nU3RhcnRlZCIsIkVuZGluZ1Nvb24iLCJvblJlY29yZGluZ0VuZGluZ1Nvb24iLCJjb21wb25lbnREaWRNb3VudCIsImRpc3BhdGNoZXJSZWYiLCJyZWdpc3RlciIsIm9uQWN0aW9uIiwid2FpdEZvck93bk1lbWJlciIsIlVJU3RvcmUiLCJ0cmFja0VsZW1lbnREaW1lbnNpb25zIiwicmVmIiwib25SZXNpemUiLCJtZSIsImdldE1lbWJlciIsImdldFVzZXJJZCIsImxvYWRNZW1iZXJzSWZOZWVkZWQiLCJ0aGVuIiwiZ2V0U2FmZVVzZXJJZCIsImNvbXBvbmVudFdpbGxVbm1vdW50IiwidW5yZWdpc3RlciIsInN0b3BUcmFja2luZ0VsZW1lbnREaW1lbnNpb25zIiwicmVtb3ZlTGlzdGVuZXIiLCJyZW1vdmVFdmVudExpc3RlbmVyIiwiaGFzUmVjb3JkaW5nIiwiaXNSZWNvcmRpbmciLCJpc0xvY2FsUm9vbSIsImdldE1lbnVQb3NpdGlvbiIsImhhc0Zvcm1hdHRpbmdCdXR0b25zIiwiY29udGVudFJlY3QiLCJnZXRCb3VuZGluZ0NsaWVudFJlY3QiLCJoZWlnaHRUb1JlbW92ZSIsImZpeGVkUmVjdCIsIkRPTVJlY3QiLCJ4IiwieSIsIndpZHRoIiwiaGVpZ2h0IiwiYWJvdmVMZWZ0T2YiLCJyZW5kZXIiLCJoYXNFMkVJY29uIiwiZTJlSWNvbiIsInN0YXR1cyIsImNvbnRyb2xzIiwibWVudVBvc2l0aW9uIiwiY2FuU2VuZE1lc3NhZ2VzIiwiY29tcG9zZXIiLCJTZW5kV3lzaXd5Z0NvbXBvc2VyIiwiZGlzYWJsZWQiLCJvbkNoYW5nZSIsIm9uV3lzaXd5Z0NoYW5nZSIsIm9uU2VuZCIsImluaXRpYWxDb250ZW50IiwicGxhY2Vob2xkZXIiLCJyZW5kZXJQbGFjZWhvbGRlclRleHQiLCJldmVudFJlbGF0aW9uIiwidG9nZ2xlU3RpY2tlclBpY2tlck9wZW4iLCJwdXNoIiwiY29udGludWVzTGluayIsImhyZWYiLCJtYWtlUm9vbVBlcm1hbGluayIsIm9uVG9tYnN0b25lQ2xpY2siLCJhbHQiLCJzcmMiLCJyZWNvcmRpbmdUb29sdGlwIiwiaXNUb29sdGlwT3BlbiIsIk1hdGgiLCJyb3VuZCIsInRocmVhZElkIiwic2hvd1NlbmRCdXR0b24iLCJjbGFzc2VzIiwiY2xhc3NOYW1lcyIsImNvbXBhY3QiLCJUb29sdGlwIiwib3BlbiIsImRlc2NyaXB0aW9uIiwiZm9ybWF0VGltZUxlZnQiLCJwbGFjZW1lbnQiLCJyb2xlIiwiYWRkRW1vamkiLCJzaG93TG9jYXRpb25CdXR0b24iLCJlbGVjdHJvbiIsIlVJRmVhdHVyZSIsIkxvY2F0aW9uU2hhcmluZyIsIm9uQ29tcG9zZXJNb2RlQ2xpY2siLCJvblJpY2hUZXh0VG9nZ2xlIiwib25TdGFydFZvaWNlQnJvYWRjYXN0Q2xpY2siLCJzZXRVcFZvaWNlQnJvYWRjYXN0UHJlUmVjb3JkaW5nIiwidm9pY2VCcm9hZGNhc3RQbGF5YmFja3NTdG9yZSIsInZvaWNlQnJvYWRjYXN0UHJlUmVjb3JkaW5nU3RvcmUiLCJSb29tQ29udGV4dCIsIk1lc3NhZ2VDb21wb3NlcldpdGhNYXRyaXhDbGllbnQiLCJ3aXRoTWF0cml4Q2xpZW50SE9DIiwiX2RlZmF1bHQiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9yb29tcy9NZXNzYWdlQ29tcG9zZXIudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE1LTIwMjIgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0LCB7IGNyZWF0ZVJlZiwgUmVhY3ROb2RlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgY2xhc3NOYW1lcyBmcm9tIFwiY2xhc3NuYW1lc1wiO1xuaW1wb3J0IHtcbiAgICBJRXZlbnRSZWxhdGlvbixcbiAgICBNYXRyaXhFdmVudCxcbiAgICBSb29tLFxuICAgIFJvb21NZW1iZXIsXG4gICAgRXZlbnRUeXBlLFxuICAgIFRIUkVBRF9SRUxBVElPTl9UWVBFLFxufSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBPcHRpb25hbCB9IGZyb20gXCJtYXRyaXgtZXZlbnRzLXNka1wiO1xuaW1wb3J0IHsgVG9vbHRpcCB9IGZyb20gXCJAdmVjdG9yLWltL2NvbXBvdW5kLXdlYlwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuXG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi8uLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCBkaXMgZnJvbSBcIi4uLy4uLy4uL2Rpc3BhdGNoZXIvZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHsgQWN0aW9uUGF5bG9hZCB9IGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL3BheWxvYWRzXCI7XG5pbXBvcnQgU3RpY2tlcnBpY2tlciBmcm9tIFwiLi9TdGlja2VycGlja2VyXCI7XG5pbXBvcnQgeyBtYWtlUm9vbVBlcm1hbGluaywgUm9vbVBlcm1hbGlua0NyZWF0b3IgfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvcGVybWFsaW5rcy9QZXJtYWxpbmtzXCI7XG5pbXBvcnQgRTJFSWNvbiBmcm9tIFwiLi9FMkVJY29uXCI7XG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vLi4vLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IHsgYWJvdmVMZWZ0T2YsIE1lbnVQcm9wcyB9IGZyb20gXCIuLi8uLi9zdHJ1Y3R1cmVzL0NvbnRleHRNZW51XCI7XG5pbXBvcnQgUmVwbHlQcmV2aWV3IGZyb20gXCIuL1JlcGx5UHJldmlld1wiO1xuaW1wb3J0IHsgVVBEQVRFX0VWRU5UIH0gZnJvbSBcIi4uLy4uLy4uL3N0b3Jlcy9Bc3luY1N0b3JlXCI7XG5pbXBvcnQgVm9pY2VSZWNvcmRDb21wb3NlclRpbGUgZnJvbSBcIi4vVm9pY2VSZWNvcmRDb21wb3NlclRpbGVcIjtcbmltcG9ydCB7IFZvaWNlUmVjb3JkaW5nU3RvcmUgfSBmcm9tIFwiLi4vLi4vLi4vc3RvcmVzL1ZvaWNlUmVjb3JkaW5nU3RvcmVcIjtcbmltcG9ydCB7IFJlY29yZGluZ1N0YXRlIH0gZnJvbSBcIi4uLy4uLy4uL2F1ZGlvL1ZvaWNlUmVjb3JkaW5nXCI7XG5pbXBvcnQgUmVzaXplTm90aWZpZXIgZnJvbSBcIi4uLy4uLy4uL3V0aWxzL1Jlc2l6ZU5vdGlmaWVyXCI7XG5pbXBvcnQgeyBFMkVTdGF0dXMgfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvU2hpZWxkVXRpbHNcIjtcbmltcG9ydCBTZW5kTWVzc2FnZUNvbXBvc2VyLCB7IFNlbmRNZXNzYWdlQ29tcG9zZXIgYXMgU2VuZE1lc3NhZ2VDb21wb3NlckNsYXNzIH0gZnJvbSBcIi4vU2VuZE1lc3NhZ2VDb21wb3NlclwiO1xuaW1wb3J0IHsgQ29tcG9zZXJJbnNlcnRQYXlsb2FkIH0gZnJvbSBcIi4uLy4uLy4uL2Rpc3BhdGNoZXIvcGF5bG9hZHMvQ29tcG9zZXJJbnNlcnRQYXlsb2FkXCI7XG5pbXBvcnQgeyBBY3Rpb24gfSBmcm9tIFwiLi4vLi4vLi4vZGlzcGF0Y2hlci9hY3Rpb25zXCI7XG5pbXBvcnQgRWRpdG9yTW9kZWwgZnJvbSBcIi4uLy4uLy4uL2VkaXRvci9tb2RlbFwiO1xuaW1wb3J0IFVJU3RvcmUsIHsgVUlfRVZFTlRTIH0gZnJvbSBcIi4uLy4uLy4uL3N0b3Jlcy9VSVN0b3JlXCI7XG5pbXBvcnQgUm9vbUNvbnRleHQgZnJvbSBcIi4uLy4uLy4uL2NvbnRleHRzL1Jvb21Db250ZXh0XCI7XG5pbXBvcnQgeyBTZXR0aW5nVXBkYXRlZFBheWxvYWQgfSBmcm9tIFwiLi4vLi4vLi4vZGlzcGF0Y2hlci9wYXlsb2Fkcy9TZXR0aW5nVXBkYXRlZFBheWxvYWRcIjtcbmltcG9ydCBNZXNzYWdlQ29tcG9zZXJCdXR0b25zIGZyb20gXCIuL01lc3NhZ2VDb21wb3NlckJ1dHRvbnNcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uLCB7IEJ1dHRvbkV2ZW50IH0gZnJvbSBcIi4uL2VsZW1lbnRzL0FjY2Vzc2libGVCdXR0b25cIjtcbmltcG9ydCB7IFZpZXdSb29tUGF5bG9hZCB9IGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL3BheWxvYWRzL1ZpZXdSb29tUGF5bG9hZFwiO1xuaW1wb3J0IHsgaXNMb2NhbFJvb20gfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvbG9jYWxSb29tL2lzTG9jYWxSb29tXCI7XG5pbXBvcnQgeyBGZWF0dXJlcyB9IGZyb20gXCIuLi8uLi8uLi9zZXR0aW5ncy9TZXR0aW5nc1wiO1xuaW1wb3J0IHsgVm9pY2VNZXNzYWdlUmVjb3JkaW5nIH0gZnJvbSBcIi4uLy4uLy4uL2F1ZGlvL1ZvaWNlTWVzc2FnZVJlY29yZGluZ1wiO1xuaW1wb3J0IHsgU2VuZFd5c2l3eWdDb21wb3Nlciwgc2VuZE1lc3NhZ2UsIGdldENvbnZlcnNpb25GdW5jdGlvbnMgfSBmcm9tIFwiLi93eXNpd3lnX2NvbXBvc2VyL1wiO1xuaW1wb3J0IHsgTWF0cml4Q2xpZW50UHJvcHMsIHdpdGhNYXRyaXhDbGllbnRIT0MgfSBmcm9tIFwiLi4vLi4vLi4vY29udGV4dHMvTWF0cml4Q2xpZW50Q29udGV4dFwiO1xuaW1wb3J0IHsgc2V0VXBWb2ljZUJyb2FkY2FzdFByZVJlY29yZGluZyB9IGZyb20gXCIuLi8uLi8uLi92b2ljZS1icm9hZGNhc3QvdXRpbHMvc2V0VXBWb2ljZUJyb2FkY2FzdFByZVJlY29yZGluZ1wiO1xuaW1wb3J0IHsgU2RrQ29udGV4dENsYXNzIH0gZnJvbSBcIi4uLy4uLy4uL2NvbnRleHRzL1NES0NvbnRleHRcIjtcbmltcG9ydCB7IFZvaWNlQnJvYWRjYXN0SW5mb1N0YXRlIH0gZnJvbSBcIi4uLy4uLy4uL3ZvaWNlLWJyb2FkY2FzdFwiO1xuaW1wb3J0IHsgY3JlYXRlQ2FudFN0YXJ0Vm9pY2VNZXNzYWdlQnJvYWRjYXN0RGlhbG9nIH0gZnJvbSBcIi4uL2RpYWxvZ3MvQ2FudFN0YXJ0Vm9pY2VNZXNzYWdlQnJvYWRjYXN0RGlhbG9nXCI7XG5pbXBvcnQgeyBVSUZlYXR1cmUgfSBmcm9tIFwiLi4vLi4vLi4vc2V0dGluZ3MvVUlGZWF0dXJlXCI7XG5pbXBvcnQgeyBmb3JtYXRUaW1lTGVmdCB9IGZyb20gXCIuLi8uLi8uLi9EYXRlVXRpbHNcIjtcblxuLy8gVGhlIHByZWZpeCB1c2VkIHdoZW4gcGVyc2lzdGluZyBlZGl0b3IgZHJhZnRzIHRvIGxvY2Fsc3RvcmFnZS5cbmV4cG9ydCBjb25zdCBXWVNJV1lHX0VESVRPUl9TVEFURV9TVE9SQUdFX1BSRUZJWCA9IFwibXhfd3lzaXd5Z19zdGF0ZV9cIjtcblxubGV0IGluc3RhbmNlQ291bnQgPSAwO1xuXG5pbnRlcmZhY2UgSVNlbmRCdXR0b25Qcm9wcyB7XG4gICAgb25DbGljazogKGV2OiBCdXR0b25FdmVudCkgPT4gdm9pZDtcbiAgICB0aXRsZT86IHN0cmluZzsgLy8gZGVmYXVsdHMgdG8gc29tZXRoaW5nIGdlbmVyaWNcbn1cblxuZnVuY3Rpb24gU2VuZEJ1dHRvbihwcm9wczogSVNlbmRCdXR0b25Qcm9wcyk6IEpTWC5FbGVtZW50IHtcbiAgICByZXR1cm4gKFxuICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvblxuICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfTWVzc2FnZUNvbXBvc2VyX3NlbmRNZXNzYWdlXCJcbiAgICAgICAgICAgIG9uQ2xpY2s9e3Byb3BzLm9uQ2xpY2t9XG4gICAgICAgICAgICB0aXRsZT17cHJvcHMudGl0bGUgPz8gX3QoXCJjb21wb3NlcnxzZW5kX2J1dHRvbl90aXRsZVwiKX1cbiAgICAgICAgICAgIGRhdGEtdGVzdGlkPVwic2VuZG1lc3NhZ2VidG5cIlxuICAgICAgICAvPlxuICAgICk7XG59XG5cbmludGVyZmFjZSBJUHJvcHMgZXh0ZW5kcyBNYXRyaXhDbGllbnRQcm9wcyB7XG4gICAgcm9vbTogUm9vbTtcbiAgICByZXNpemVOb3RpZmllcjogUmVzaXplTm90aWZpZXI7XG4gICAgcGVybWFsaW5rQ3JlYXRvcj86IFJvb21QZXJtYWxpbmtDcmVhdG9yO1xuICAgIHJlcGx5VG9FdmVudD86IE1hdHJpeEV2ZW50O1xuICAgIHJlbGF0aW9uPzogSUV2ZW50UmVsYXRpb247XG4gICAgZTJlU3RhdHVzPzogRTJFU3RhdHVzO1xuICAgIGNvbXBhY3Q/OiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgSVN0YXRlIHtcbiAgICBjb21wb3NlckNvbnRlbnQ6IHN0cmluZztcbiAgICBpc0NvbXBvc2VyRW1wdHk6IGJvb2xlYW47XG4gICAgaGF2ZVJlY29yZGluZzogYm9vbGVhbjtcbiAgICByZWNvcmRpbmdUaW1lTGVmdFNlY29uZHM/OiBudW1iZXI7XG4gICAgbWU/OiBSb29tTWVtYmVyO1xuICAgIGlzTWVudU9wZW46IGJvb2xlYW47XG4gICAgaXNTdGlja2VyUGlja2VyT3BlbjogYm9vbGVhbjtcbiAgICBzaG93U3RpY2tlcnNCdXR0b246IGJvb2xlYW47XG4gICAgc2hvd1BvbGxzQnV0dG9uOiBib29sZWFuO1xuICAgIHNob3dWb2ljZUJyb2FkY2FzdEJ1dHRvbjogYm9vbGVhbjtcbiAgICBpc1d5c2l3eWdMYWJFbmFibGVkOiBib29sZWFuO1xuICAgIGlzUmljaFRleHRFbmFibGVkOiBib29sZWFuO1xuICAgIGluaXRpYWxDb21wb3NlckNvbnRlbnQ6IHN0cmluZztcbn1cblxudHlwZSBXeXNpd3lnQ29tcG9zZXJTdGF0ZSA9IHtcbiAgICBjb250ZW50OiBzdHJpbmc7XG4gICAgaXNSaWNoVGV4dDogYm9vbGVhbjtcbiAgICByZXBseUV2ZW50SWQ/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgY2xhc3MgTWVzc2FnZUNvbXBvc2VyIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50PElQcm9wcywgSVN0YXRlPiB7XG4gICAgcHJpdmF0ZSBkaXNwYXRjaGVyUmVmPzogc3RyaW5nO1xuICAgIHByaXZhdGUgbWVzc2FnZUNvbXBvc2VySW5wdXQgPSBjcmVhdGVSZWY8U2VuZE1lc3NhZ2VDb21wb3NlckNsYXNzPigpO1xuICAgIHByaXZhdGUgdm9pY2VSZWNvcmRpbmdCdXR0b24gPSBjcmVhdGVSZWY8Vm9pY2VSZWNvcmRDb21wb3NlclRpbGU+KCk7XG4gICAgcHJpdmF0ZSByZWY6IFJlYWN0LlJlZk9iamVjdDxIVE1MRGl2RWxlbWVudD4gPSBjcmVhdGVSZWYoKTtcbiAgICBwcml2YXRlIGluc3RhbmNlSWQ6IG51bWJlcjtcblxuICAgIHByaXZhdGUgX3ZvaWNlUmVjb3JkaW5nOiBPcHRpb25hbDxWb2ljZU1lc3NhZ2VSZWNvcmRpbmc+O1xuXG4gICAgcHVibGljIHN0YXRpYyBjb250ZXh0VHlwZSA9IFJvb21Db250ZXh0O1xuICAgIHB1YmxpYyBkZWNsYXJlIGNvbnRleHQ6IFJlYWN0LkNvbnRleHRUeXBlPHR5cGVvZiBSb29tQ29udGV4dD47XG5cbiAgICBwdWJsaWMgc3RhdGljIGRlZmF1bHRQcm9wcyA9IHtcbiAgICAgICAgY29tcGFjdDogZmFsc2UsXG4gICAgICAgIHNob3dWb2ljZUJyb2FkY2FzdEJ1dHRvbjogZmFsc2UsXG4gICAgICAgIGlzUmljaFRleHRFbmFibGVkOiB0cnVlLFxuICAgIH07XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IElQcm9wcywgY29udGV4dDogUmVhY3QuQ29udGV4dFR5cGU8dHlwZW9mIFJvb21Db250ZXh0Pikge1xuICAgICAgICBzdXBlcihwcm9wcywgY29udGV4dCk7XG4gICAgICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7IC8vIG90aGVyd2lzZSBSZWFjdCB3aWxsIG9ubHkgc2V0IGl0IHByaW9yIHRvIHJlbmRlciBkdWUgdG8gdHlwZSBkZWYgYWJvdmVcblxuICAgICAgICBWb2ljZVJlY29yZGluZ1N0b3JlLmluc3RhbmNlLm9uKFVQREFURV9FVkVOVCwgdGhpcy5vblZvaWNlU3RvcmVVcGRhdGUpO1xuXG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiYmVmb3JldW5sb2FkXCIsIHRoaXMuc2F2ZVd5c2l3eWdFZGl0b3JTdGF0ZSk7XG4gICAgICAgIGNvbnN0IGlzV3lzaXd5Z0xhYkVuYWJsZWQgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlPGJvb2xlYW4+KFwiZmVhdHVyZV93eXNpd3lnX2NvbXBvc2VyXCIpO1xuICAgICAgICBsZXQgaXNSaWNoVGV4dEVuYWJsZWQgPSB0cnVlO1xuICAgICAgICBsZXQgaW5pdGlhbENvbXBvc2VyQ29udGVudCA9IFwiXCI7XG4gICAgICAgIGlmIChpc1d5c2l3eWdMYWJFbmFibGVkKSB7XG4gICAgICAgICAgICBjb25zdCB3eXNpd3lnU3RhdGUgPSB0aGlzLnJlc3RvcmVXeXNpd3lnRWRpdG9yU3RhdGUoKTtcbiAgICAgICAgICAgIGlmICh3eXNpd3lnU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBpc1JpY2hUZXh0RW5hYmxlZCA9IHd5c2l3eWdTdGF0ZS5pc1JpY2hUZXh0O1xuICAgICAgICAgICAgICAgIGluaXRpYWxDb21wb3NlckNvbnRlbnQgPSB3eXNpd3lnU3RhdGUuY29udGVudDtcbiAgICAgICAgICAgICAgICBpZiAod3lzaXd5Z1N0YXRlLnJlcGx5RXZlbnRJZCkge1xuICAgICAgICAgICAgICAgICAgICBkaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcInJlcGx5X3RvX2V2ZW50XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudDogdGhpcy5wcm9wcy5yb29tLmZpbmRFdmVudEJ5SWQod3lzaXd5Z1N0YXRlLnJlcGx5RXZlbnRJZCksXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0OiB0aGlzLmNvbnRleHQudGltZWxpbmVSZW5kZXJpbmdUeXBlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgaXNDb21wb3NlckVtcHR5OiBpbml0aWFsQ29tcG9zZXJDb250ZW50Py5sZW5ndGggPT09IDAsXG4gICAgICAgICAgICBjb21wb3NlckNvbnRlbnQ6IGluaXRpYWxDb21wb3NlckNvbnRlbnQsXG4gICAgICAgICAgICBoYXZlUmVjb3JkaW5nOiBmYWxzZSxcbiAgICAgICAgICAgIHJlY29yZGluZ1RpbWVMZWZ0U2Vjb25kczogdW5kZWZpbmVkLCAvLyB3aGVuIHNldCB0byBhIG51bWJlciwgc2hvd3MgYSB0b2FzdFxuICAgICAgICAgICAgaXNNZW51T3BlbjogZmFsc2UsXG4gICAgICAgICAgICBpc1N0aWNrZXJQaWNrZXJPcGVuOiBmYWxzZSxcbiAgICAgICAgICAgIHNob3dTdGlja2Vyc0J1dHRvbjogU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcIk1lc3NhZ2VDb21wb3NlcklucHV0LnNob3dTdGlja2Vyc0J1dHRvblwiKSxcbiAgICAgICAgICAgIHNob3dQb2xsc0J1dHRvbjogU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcIk1lc3NhZ2VDb21wb3NlcklucHV0LnNob3dQb2xsc0J1dHRvblwiKSxcbiAgICAgICAgICAgIHNob3dWb2ljZUJyb2FkY2FzdEJ1dHRvbjogU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShGZWF0dXJlcy5Wb2ljZUJyb2FkY2FzdCksXG4gICAgICAgICAgICBpc1d5c2l3eWdMYWJFbmFibGVkOiBpc1d5c2l3eWdMYWJFbmFibGVkLFxuICAgICAgICAgICAgaXNSaWNoVGV4dEVuYWJsZWQ6IGlzUmljaFRleHRFbmFibGVkLFxuICAgICAgICAgICAgaW5pdGlhbENvbXBvc2VyQ29udGVudDogaW5pdGlhbENvbXBvc2VyQ29udGVudCxcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmluc3RhbmNlSWQgPSBpbnN0YW5jZUNvdW50Kys7XG5cbiAgICAgICAgU2V0dGluZ3NTdG9yZS5tb25pdG9yU2V0dGluZyhcIk1lc3NhZ2VDb21wb3NlcklucHV0LnNob3dTdGlja2Vyc0J1dHRvblwiLCBudWxsKTtcbiAgICAgICAgU2V0dGluZ3NTdG9yZS5tb25pdG9yU2V0dGluZyhcIk1lc3NhZ2VDb21wb3NlcklucHV0LnNob3dQb2xsc0J1dHRvblwiLCBudWxsKTtcbiAgICAgICAgU2V0dGluZ3NTdG9yZS5tb25pdG9yU2V0dGluZyhGZWF0dXJlcy5Wb2ljZUJyb2FkY2FzdCwgbnVsbCk7XG4gICAgICAgIFNldHRpbmdzU3RvcmUubW9uaXRvclNldHRpbmcoXCJmZWF0dXJlX3d5c2l3eWdfY29tcG9zZXJcIiwgbnVsbCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgZWRpdG9yU3RhdGVLZXkoKTogc3RyaW5nIHtcbiAgICAgICAgbGV0IGtleSA9IFdZU0lXWUdfRURJVE9SX1NUQVRFX1NUT1JBR0VfUFJFRklYICsgdGhpcy5wcm9wcy5yb29tLnJvb21JZDtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMucmVsYXRpb24/LnJlbF90eXBlID09PSBUSFJFQURfUkVMQVRJT05fVFlQRS5uYW1lKSB7XG4gICAgICAgICAgICBrZXkgKz0gYF8ke3RoaXMucHJvcHMucmVsYXRpb24uZXZlbnRfaWR9YDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ga2V5O1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVzdG9yZVd5c2l3eWdFZGl0b3JTdGF0ZSgpOiBXeXNpd3lnQ29tcG9zZXJTdGF0ZSB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGNvbnN0IGpzb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmVkaXRvclN0YXRlS2V5KTtcbiAgICAgICAgaWYgKGpzb24pIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RhdGU6IFd5c2l3eWdDb21wb3NlclN0YXRlID0gSlNPTi5wYXJzZShqc29uKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3RhdGU7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzYXZlV3lzaXd5Z0VkaXRvclN0YXRlID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAodGhpcy5zaG91bGRTYXZlV3lzaXd5Z0VkaXRvclN0YXRlKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgaXNSaWNoVGV4dEVuYWJsZWQsIGNvbXBvc2VyQ29udGVudCB9ID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgICAgIGNvbnN0IHJlcGx5RXZlbnRJZCA9IHRoaXMucHJvcHMucmVwbHlUb0V2ZW50ID8gdGhpcy5wcm9wcy5yZXBseVRvRXZlbnQuZ2V0SWQoKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGNvbnN0IGl0ZW06IFd5c2l3eWdDb21wb3NlclN0YXRlID0ge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGNvbXBvc2VyQ29udGVudCxcbiAgICAgICAgICAgICAgICBpc1JpY2hUZXh0OiBpc1JpY2hUZXh0RW5hYmxlZCxcbiAgICAgICAgICAgICAgICByZXBseUV2ZW50SWQ6IHJlcGx5RXZlbnRJZCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSh0aGlzLmVkaXRvclN0YXRlS2V5LCBKU09OLnN0cmluZ2lmeShpdGVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmNsZWFyU3RvcmVkRWRpdG9yU3RhdGUoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBzaG91bGQgc2F2ZSBzdGF0ZSB3aGVuIHd5c2l3eWcgaXMgZW5hYmxlZCBhbmQgaGFzIGNvbnRlbnRzIG9yIHJlcGx5IGlzIG9wZW5cbiAgICBwcml2YXRlIHNob3VsZFNhdmVXeXNpd3lnRWRpdG9yU3RhdGUgPSAoKTogYm9vbGVhbiA9PiB7XG4gICAgICAgIGNvbnN0IHsgaXNXeXNpd3lnTGFiRW5hYmxlZCwgaXNDb21wb3NlckVtcHR5IH0gPSB0aGlzLnN0YXRlO1xuICAgICAgICByZXR1cm4gaXNXeXNpd3lnTGFiRW5hYmxlZCAmJiAoIWlzQ29tcG9zZXJFbXB0eSB8fCAhIXRoaXMucHJvcHMucmVwbHlUb0V2ZW50KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBjbGVhclN0b3JlZEVkaXRvclN0YXRlKCk6IHZvaWQge1xuICAgICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbSh0aGlzLmVkaXRvclN0YXRlS2V5KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldCB2b2ljZVJlY29yZGluZygpOiBPcHRpb25hbDxWb2ljZU1lc3NhZ2VSZWNvcmRpbmc+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZvaWNlUmVjb3JkaW5nO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2V0IHZvaWNlUmVjb3JkaW5nKHJlYzogT3B0aW9uYWw8Vm9pY2VNZXNzYWdlUmVjb3JkaW5nPikge1xuICAgICAgICBpZiAodGhpcy5fdm9pY2VSZWNvcmRpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuX3ZvaWNlUmVjb3JkaW5nLm9mZihSZWNvcmRpbmdTdGF0ZS5TdGFydGVkLCB0aGlzLm9uUmVjb3JkaW5nU3RhcnRlZCk7XG4gICAgICAgICAgICB0aGlzLl92b2ljZVJlY29yZGluZy5vZmYoUmVjb3JkaW5nU3RhdGUuRW5kaW5nU29vbiwgdGhpcy5vblJlY29yZGluZ0VuZGluZ1Nvb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdm9pY2VSZWNvcmRpbmcgPSByZWM7XG5cbiAgICAgICAgaWYgKHJlYykge1xuICAgICAgICAgICAgLy8gRGVsYXkgc2F5aW5nIHdlIGhhdmUgYSByZWNvcmRpbmcgdW50aWwgaXQgaXMgc3RhcnRlZCwgYXMgd2UgbWlnaHQgbm90IHlldFxuICAgICAgICAgICAgLy8gaGF2ZSBBL1YgcGVybWlzc2lvbnNcbiAgICAgICAgICAgIHJlYy5vbihSZWNvcmRpbmdTdGF0ZS5TdGFydGVkLCB0aGlzLm9uUmVjb3JkaW5nU3RhcnRlZCk7XG5cbiAgICAgICAgICAgI