matrix-react-sdk
Version:
SDK for matrix.org using React
905 lines (881 loc) • 132 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.hasText = hasText;
exports.textForEvent = textForEvent;
exports.textForLocationEvent = textForLocationEvent;
var _react = _interopRequireDefault(require("react"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _types = require("matrix-js-sdk/src/types");
var _logger = require("matrix-js-sdk/src/logger");
var _utils = require("matrix-js-sdk/src/utils");
var _languageHandler = require("./languageHandler");
var Roles = _interopRequireWildcard(require("./Roles"));
var _RoomInvite = require("./RoomInvite");
var _SettingsStore = _interopRequireDefault(require("./settings/SettingsStore"));
var _BanList = require("./mjolnir/BanList");
var _WidgetLayoutStore = require("./stores/widgets/WidgetLayoutStore");
var _RightPanelStorePhases = require("./stores/right-panel/RightPanelStorePhases");
var _dispatcher = _interopRequireDefault(require("./dispatcher/dispatcher"));
var _RoomSettingsDialog = require("./components/views/dialogs/RoomSettingsDialog");
var _AccessibleButton = _interopRequireDefault(require("./components/views/elements/AccessibleButton"));
var _RightPanelStore = _interopRequireDefault(require("./stores/right-panel/RightPanelStore"));
var _EventUtils = require("./utils/EventUtils");
var _Call = require("./models/Call");
var _voiceBroadcast = require("./voice-broadcast");
var _getSenderName = require("./utils/event/getSenderName");
var _PosthogTrackers = _interopRequireDefault(require("./PosthogTrackers.ts"));
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.
*/
function getRoomMemberDisplayname(client, event, userId = event.getSender()) {
const roomId = event.getRoomId();
const member = client.getRoom(roomId)?.getMember(userId);
return member?.name || member?.rawDisplayName || userId || (0, _languageHandler._t)("common|someone");
}
function textForCallEvent(event, client) {
const roomName = client.getRoom(event.getRoomId())?.name;
const isSupported = client.supportsVoip();
return isSupported ? () => (0, _languageHandler._t)("timeline|m.call|video_call_started", {
roomName
}) : () => (0, _languageHandler._t)("timeline|m.call|video_call_started_unsupported", {
roomName
});
}
// These functions are frequently used just to check whether an event has
// any text to display at all. For this reason they return deferred values
// to avoid the expense of looking up translations when they're not needed.
function textForCallInviteEvent(event, client) {
const senderName = (0, _getSenderName.getSenderName)(event);
// FIXME: Find a better way to determine this from the event?
const isVoice = !event.getContent().offer?.sdp?.includes("m=video");
const isSupported = client.supportsVoip();
// This ladder could be reduced down to a couple string variables, however other languages
// can have a hard time translating those strings. In an effort to make translations easier
// and more accurate, we break out the string-based variables to a couple booleans.
if (isVoice && isSupported) {
return () => (0, _languageHandler._t)("timeline|m.call.invite|voice_call", {
senderName
});
} else if (isVoice && !isSupported) {
return () => (0, _languageHandler._t)("timeline|m.call.invite|voice_call_unsupported", {
senderName
});
} else if (!isVoice && isSupported) {
return () => (0, _languageHandler._t)("timeline|m.call.invite|video_call", {
senderName
});
} else if (!isVoice && !isSupported) {
return () => (0, _languageHandler._t)("timeline|m.call.invite|video_call_unsupported", {
senderName
});
}
return null;
}
var Modification = /*#__PURE__*/function (Modification) {
Modification[Modification["None"] = 0] = "None";
Modification[Modification["Unset"] = 1] = "Unset";
Modification[Modification["Set"] = 2] = "Set";
Modification[Modification["Changed"] = 3] = "Changed";
return Modification;
}(Modification || {});
function getModification(prev, value) {
if (prev && value && prev !== value) {
return Modification.Changed;
}
if (prev && !value) {
return Modification.Unset;
}
if (!prev && value) {
return Modification.Set;
}
return Modification.None;
}
function textForMemberEvent(ev, client, allowJSX, showHiddenEvents) {
// XXX: SYJS-16 "sender is sometimes null for join messages"
const senderName = ev.sender?.name || getRoomMemberDisplayname(client, ev);
const targetName = ev.target?.name || getRoomMemberDisplayname(client, ev, ev.getStateKey());
const prevContent = ev.getPrevContent();
const content = ev.getContent();
const reason = content.reason;
switch (content.membership) {
case _types.KnownMembership.Invite:
{
const threePidContent = content.third_party_invite;
if (threePidContent) {
if (threePidContent.display_name) {
return () => (0, _languageHandler._t)("timeline|m.room.member|accepted_3pid_invite", {
targetName,
displayName: threePidContent.display_name
});
} else {
return () => (0, _languageHandler._t)("timeline|m.room.member|accepted_invite", {
targetName
});
}
} else {
return () => (0, _languageHandler._t)("timeline|m.room.member|invite", {
senderName,
targetName
});
}
}
case _types.KnownMembership.Ban:
return () => reason ? (0, _languageHandler._t)("timeline|m.room.member|ban_reason", {
senderName,
targetName,
reason
}) : (0, _languageHandler._t)("timeline|m.room.member|ban", {
senderName,
targetName
});
case _types.KnownMembership.Join:
if (prevContent && prevContent.membership === _types.KnownMembership.Join) {
const modDisplayname = getModification(prevContent.displayname, content.displayname);
const modAvatarUrl = getModification(prevContent.avatar_url, content.avatar_url);
if (modDisplayname !== Modification.None && modAvatarUrl !== Modification.None) {
// Compromise to provide the user with more context without needing 16 translations
return () => (0, _languageHandler._t)("timeline|m.room.member|change_name_avatar", {
// We're taking the display namke directly from the event content here so we need
// to strip direction override chars which the js-sdk would normally do when
// calculating the display name
oldDisplayName: (0, _utils.removeDirectionOverrideChars)(prevContent.displayname)
});
} else if (modDisplayname === Modification.Changed) {
return () => (0, _languageHandler._t)("timeline|m.room.member|change_name", {
// We're taking the display name directly from the event content here so we need
// to strip direction override chars which the js-sdk would normally do when
// calculating the display name
oldDisplayName: (0, _utils.removeDirectionOverrideChars)(prevContent.displayname),
displayName: (0, _utils.removeDirectionOverrideChars)(content.displayname)
});
} else if (modDisplayname === Modification.Set) {
return () => (0, _languageHandler._t)("timeline|m.room.member|set_name", {
senderName: ev.getSender(),
displayName: (0, _utils.removeDirectionOverrideChars)(content.displayname)
});
} else if (modDisplayname === Modification.Unset) {
return () => (0, _languageHandler._t)("timeline|m.room.member|remove_name", {
senderName,
oldDisplayName: (0, _utils.removeDirectionOverrideChars)(prevContent.displayname)
});
} else if (modAvatarUrl === Modification.Unset) {
return () => (0, _languageHandler._t)("timeline|m.room.member|remove_avatar", {
senderName
});
} else if (modAvatarUrl === Modification.Changed) {
return () => (0, _languageHandler._t)("timeline|m.room.member|change_avatar", {
senderName
});
} else if (modAvatarUrl === Modification.Set) {
return () => (0, _languageHandler._t)("timeline|m.room.member|set_avatar", {
senderName
});
} else if (showHiddenEvents ?? _SettingsStore.default.getValue("showHiddenEventsInTimeline")) {
// This is a null rejoin, it will only be visible if using 'show hidden events' (labs)
return () => (0, _languageHandler._t)("timeline|m.room.member|no_change", {
senderName
});
} else {
return null;
}
} else {
if (!ev.target) _logger.logger.warn("Join message has no target! -- " + ev.getContent().state_key);
return () => (0, _languageHandler._t)("timeline|m.room.member|join", {
targetName
});
}
case _types.KnownMembership.Leave:
if (ev.getSender() === ev.getStateKey()) {
if (prevContent.membership === _types.KnownMembership.Invite) {
return () => (0, _languageHandler._t)("timeline|m.room.member|reject_invite", {
targetName
});
} else {
return () => reason ? (0, _languageHandler._t)("timeline|m.room.member|left_reason", {
targetName,
reason
}) : (0, _languageHandler._t)("timeline|m.room.member|left", {
targetName
});
}
} else if (prevContent.membership === _types.KnownMembership.Ban) {
return () => (0, _languageHandler._t)("timeline|m.room.member|unban", {
senderName,
targetName
});
} else if (prevContent.membership === _types.KnownMembership.Invite) {
return () => reason ? (0, _languageHandler._t)("timeline|m.room.member|withdrew_invite_reason", {
senderName,
targetName,
reason
}) : (0, _languageHandler._t)("timeline|m.room.member|withdrew_invite", {
senderName,
targetName
});
} else if (prevContent.membership === _types.KnownMembership.Join) {
return () => reason ? (0, _languageHandler._t)("timeline|m.room.member|kick_reason", {
senderName,
targetName,
reason
}) : (0, _languageHandler._t)("timeline|m.room.member|kick", {
senderName,
targetName
});
} else {
return null;
}
}
return null;
}
function textForTopicEvent(ev) {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
return () => (0, _languageHandler._t)("timeline|m.room.topic", {
senderDisplayName,
topic: ev.getContent().topic
});
}
function textForRoomAvatarEvent(ev) {
const senderDisplayName = ev?.sender?.name || ev.getSender();
return () => (0, _languageHandler._t)("timeline|m.room.avatar|changed", {
senderDisplayName
});
}
function textForRoomNameEvent(ev) {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
if (!ev.getContent().name || ev.getContent().name.trim().length === 0) {
return () => (0, _languageHandler._t)("timeline|m.room.name|remove", {
senderDisplayName
});
}
if (ev.getPrevContent().name) {
return () => (0, _languageHandler._t)("timeline|m.room.name|change", {
senderDisplayName,
oldRoomName: ev.getPrevContent().name,
newRoomName: ev.getContent().name
});
}
return () => (0, _languageHandler._t)("timeline|m.room.name|set", {
senderDisplayName,
roomName: ev.getContent().name
});
}
function textForTombstoneEvent(ev) {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
return () => (0, _languageHandler._t)("timeline|m.room.tombstone", {
senderDisplayName
});
}
const onViewJoinRuleSettingsClick = () => {
_dispatcher.default.dispatch({
action: "open_room_settings",
initial_tab_id: _RoomSettingsDialog.RoomSettingsTab.Security
});
};
function textForJoinRulesEvent(ev, client, allowJSX) {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
switch (ev.getContent().join_rule) {
case _matrix.JoinRule.Public:
return () => (0, _languageHandler._t)("timeline|m.room.join_rules|public", {
senderDisplayName
});
case _matrix.JoinRule.Invite:
return () => (0, _languageHandler._t)("timeline|m.room.join_rules|invite", {
senderDisplayName
});
case _matrix.JoinRule.Knock:
return () => (0, _languageHandler._t)("timeline|m.room.join_rules|knock", {
senderDisplayName
});
case _matrix.JoinRule.Restricted:
if (allowJSX) {
return () => /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("timeline|m.room.join_rules|restricted_settings", {
senderDisplayName
}, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: onViewJoinRuleSettingsClick
}, sub)
}));
}
return () => (0, _languageHandler._t)("timeline|m.room.join_rules|restricted", {
senderDisplayName
});
default:
// The spec supports "knock" and "private", however nothing implements these.
return () => (0, _languageHandler._t)("timeline|m.room.join_rules|unknown", {
senderDisplayName,
rule: ev.getContent().join_rule
});
}
}
function textForGuestAccessEvent(ev) {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
switch (ev.getContent().guest_access) {
case _matrix.GuestAccess.CanJoin:
return () => (0, _languageHandler._t)("timeline|m.room.guest_access|can_join", {
senderDisplayName
});
case _matrix.GuestAccess.Forbidden:
return () => (0, _languageHandler._t)("timeline|m.room.guest_access|forbidden", {
senderDisplayName
});
default:
// There's no other options we can expect, however just for safety's sake we'll do this.
return () => (0, _languageHandler._t)("timeline|m.room.guest_access|unknown", {
senderDisplayName,
rule: ev.getContent().guest_access
});
}
}
function textForServerACLEvent(ev) {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
const prevContent = ev.getPrevContent();
const current = ev.getContent();
const prev = {
deny: Array.isArray(prevContent.deny) ? prevContent.deny : [],
allow: Array.isArray(prevContent.allow) ? prevContent.allow : [],
allow_ip_literals: prevContent.allow_ip_literals !== false
};
let getText;
if (prev.deny.length === 0 && prev.allow.length === 0) {
getText = () => (0, _languageHandler._t)("timeline|m.room.server_acl|set", {
senderDisplayName
});
} else {
getText = () => (0, _languageHandler._t)("timeline|m.room.server_acl|changed", {
senderDisplayName
});
}
if (!Array.isArray(current.allow)) {
current.allow = [];
}
// If we know for sure everyone is banned, mark the room as obliterated
if (current.allow.length === 0) {
return () => getText() + " " + (0, _languageHandler._t)("timeline|m.room.server_acl|all_servers_banned");
}
return getText;
}
function textForMessageEvent(ev, client) {
if ((0, _EventUtils.isLocationEvent)(ev)) {
return textForLocationEvent(ev);
}
return () => {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
let message = ev.getContent().body;
if (ev.isRedacted()) {
message = textForRedactedPollAndMessageEvent(ev, client);
}
if (ev.getContent().msgtype === _matrix.MsgType.Emote) {
message = "* " + senderDisplayName + " " + message;
} else if (ev.getContent().msgtype === _matrix.MsgType.Image) {
message = (0, _languageHandler._t)("timeline|m.image|sent", {
senderDisplayName
});
} else if (ev.getType() == _matrix.EventType.Sticker) {
message = (0, _languageHandler._t)("timeline|m.sticker", {
senderDisplayName
});
} else {
// in this case, parse it as a plain text message
message = senderDisplayName + ": " + message;
}
return message;
};
}
function textForCanonicalAliasEvent(ev) {
const senderName = (0, _getSenderName.getSenderName)(ev);
const oldAlias = ev.getPrevContent().alias;
const oldAltAliases = ev.getPrevContent().alt_aliases || [];
const newAlias = ev.getContent().alias;
const newAltAliases = ev.getContent().alt_aliases || [];
const removedAltAliases = oldAltAliases.filter(alias => !newAltAliases.includes(alias));
const addedAltAliases = newAltAliases.filter(alias => !oldAltAliases.includes(alias));
if (!removedAltAliases.length && !addedAltAliases.length) {
if (newAlias) {
return () => (0, _languageHandler._t)("timeline|m.room.canonical_alias|set", {
senderName,
address: ev.getContent().alias
});
} else if (oldAlias) {
return () => (0, _languageHandler._t)("timeline|m.room.canonical_alias|removed", {
senderName
});
}
} else if (newAlias === oldAlias) {
if (addedAltAliases.length && !removedAltAliases.length) {
return () => (0, _languageHandler._t)("timeline|m.room.canonical_alias|alt_added", {
senderName,
addresses: addedAltAliases.join(", "),
count: addedAltAliases.length
});
}
if (removedAltAliases.length && !addedAltAliases.length) {
return () => (0, _languageHandler._t)("timeline|m.room.canonical_alias|alt_removed", {
senderName,
addresses: removedAltAliases.join(", "),
count: removedAltAliases.length
});
}
if (removedAltAliases.length && addedAltAliases.length) {
return () => (0, _languageHandler._t)("timeline|m.room.canonical_alias|changed_alternative", {
senderName
});
}
} else {
// both alias and alt_aliases where modified
return () => (0, _languageHandler._t)("timeline|m.room.canonical_alias|changed_main_and_alternative", {
senderName
});
}
// in case there is no difference between the two events,
// say something as we can't simply hide the tile from here
return () => (0, _languageHandler._t)("timeline|m.room.canonical_alias|changed", {
senderName
});
}
function textForThreePidInviteEvent(event) {
const senderName = (0, _getSenderName.getSenderName)(event);
if (!(0, _RoomInvite.isValid3pidInvite)(event)) {
return () => (0, _languageHandler._t)("timeline|m.room.third_party_invite|revoked", {
senderName,
targetDisplayName: event.getPrevContent().display_name || (0, _languageHandler._t)("common|someone")
});
}
return () => (0, _languageHandler._t)("timeline|m.room.third_party_invite|sent", {
senderName,
targetDisplayName: event.getContent().display_name
});
}
function textForHistoryVisibilityEvent(event) {
const senderName = (0, _getSenderName.getSenderName)(event);
switch (event.getContent().history_visibility) {
case _matrix.HistoryVisibility.Invited:
return () => (0, _languageHandler._t)("timeline|m.room.history_visibility|invited", {
senderName
});
case _matrix.HistoryVisibility.Joined:
return () => (0, _languageHandler._t)("timeline|m.room.history_visibility|joined", {
senderName
});
case _matrix.HistoryVisibility.Shared:
return () => (0, _languageHandler._t)("timeline|m.room.history_visibility|shared", {
senderName
});
case _matrix.HistoryVisibility.WorldReadable:
return () => (0, _languageHandler._t)("timeline|m.room.history_visibility|world_readable", {
senderName
});
default:
return () => (0, _languageHandler._t)("timeline|m.room.history_visibility|unknown", {
senderName,
visibility: event.getContent().history_visibility
});
}
}
// Currently will only display a change if a user's power level is changed
function textForPowerEvent(event, client) {
const senderName = (0, _getSenderName.getSenderName)(event);
if (!event.getPrevContent()?.users || !event.getContent()?.users) {
return null;
}
const previousUserDefault = event.getPrevContent().users_default || 0;
const currentUserDefault = event.getContent().users_default || 0;
// Construct set of userIds
const users = [];
Object.keys(event.getContent().users).forEach(userId => {
if (users.indexOf(userId) === -1) users.push(userId);
});
Object.keys(event.getPrevContent().users).forEach(userId => {
if (users.indexOf(userId) === -1) users.push(userId);
});
const diffs = [];
users.forEach(userId => {
// Previous power level
let from = event.getPrevContent().users[userId];
if (!Number.isInteger(from)) {
from = previousUserDefault;
}
// Current power level
let to = event.getContent().users[userId];
if (!Number.isInteger(to)) {
to = currentUserDefault;
}
if (from === previousUserDefault && to === currentUserDefault) {
return;
}
if (to !== from) {
const name = getRoomMemberDisplayname(client, event, userId);
diffs.push({
userId,
name,
from,
to
});
}
});
if (!diffs.length) {
return null;
}
// XXX: This is also surely broken for i18n
return () => (0, _languageHandler._t)("timeline|m.room.power_levels|changed", {
senderName,
powerLevelDiffText: diffs.map(diff => (0, _languageHandler._t)("timeline|m.room.power_levels|user_from_to", {
userId: diff.name,
fromPowerLevel: Roles.textualPowerLevel(diff.from, previousUserDefault),
toPowerLevel: Roles.textualPowerLevel(diff.to, currentUserDefault)
})).join(", ")
});
}
const onPinnedMessagesClick = () => {
_PosthogTrackers.default.trackInteraction("PinnedMessageStateEventClick");
_RightPanelStore.default.instance.setCard({
phase: _RightPanelStorePhases.RightPanelPhases.PinnedMessages
}, false);
};
function textForPinnedEvent(event, client, allowJSX) {
const senderName = (0, _getSenderName.getSenderName)(event);
const roomId = event.getRoomId();
const pinned = event.getContent().pinned ?? [];
const previouslyPinned = event.getPrevContent().pinned ?? [];
const newlyPinned = pinned.filter(item => previouslyPinned.indexOf(item) < 0);
const newlyUnpinned = previouslyPinned.filter(item => pinned.indexOf(item) < 0);
if (newlyPinned.length === 1 && newlyUnpinned.length === 0) {
// A single message was pinned, include a link to that message.
if (allowJSX) {
const messageId = newlyPinned.pop();
return () => /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("timeline|m.room.pinned_events|pinned_link", {
senderName
}, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: () => {
_PosthogTrackers.default.trackInteraction("PinnedMessageStateEventClick");
(0, _EventUtils.highlightEvent)(roomId, messageId);
}
}, sub),
b: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: onPinnedMessagesClick
}, sub)
}));
}
return () => (0, _languageHandler._t)("timeline|m.room.pinned_events|pinned", {
senderName
});
}
if (newlyUnpinned.length === 1 && newlyPinned.length === 0) {
// A single message was unpinned, include a link to that message.
if (allowJSX) {
const messageId = newlyUnpinned.pop();
return () => /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("timeline|m.room.pinned_events|unpinned_link", {
senderName
}, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: () => {
_PosthogTrackers.default.trackInteraction("PinnedMessageStateEventClick");
(0, _EventUtils.highlightEvent)(roomId, messageId);
}
}, sub),
b: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: onPinnedMessagesClick
}, sub)
}));
}
return () => (0, _languageHandler._t)("timeline|m.room.pinned_events|unpinned", {
senderName
});
}
if (allowJSX) {
return () => /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("timeline|m.room.pinned_events|changed_link", {
senderName
}, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: onPinnedMessagesClick
}, sub)
}));
}
return () => (0, _languageHandler._t)("timeline|m.room.pinned_events|changed", {
senderName
});
}
function textForWidgetEvent(event) {
const senderName = (0, _getSenderName.getSenderName)(event);
const {
name: prevName,
type: prevType,
url: prevUrl
} = event.getPrevContent();
const {
name,
type,
url
} = event.getContent() || {};
let widgetName = name || prevName || type || prevType || "";
// Apply sentence case to widget name
if (widgetName && widgetName.length > 0) {
widgetName = widgetName[0].toUpperCase() + widgetName.slice(1);
}
// If the widget was removed, its content should be {}, but this is sufficiently
// equivalent to that condition.
if (url) {
if (prevUrl) {
return () => (0, _languageHandler._t)("timeline|m.widget|modified", {
widgetName,
senderName
});
} else {
return () => (0, _languageHandler._t)("timeline|m.widget|added", {
widgetName,
senderName
});
}
} else {
return () => (0, _languageHandler._t)("timeline|m.widget|removed", {
widgetName,
senderName
});
}
}
function textForWidgetLayoutEvent(event) {
const senderName = (0, _getSenderName.getSenderName)(event);
return () => (0, _languageHandler._t)("timeline|io.element.widgets.layout", {
senderName
});
}
function textForMjolnirEvent(event) {
const senderName = (0, _getSenderName.getSenderName)(event);
const {
entity: prevEntity
} = event.getPrevContent();
const {
entity,
recommendation,
reason
} = event.getContent();
// Rule removed
if (!entity) {
if (_BanList.USER_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|removed_rule_users", {
senderName,
glob: prevEntity
});
} else if (_BanList.ROOM_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|removed_rule_rooms", {
senderName,
glob: prevEntity
});
} else if (_BanList.SERVER_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|removed_rule_servers", {
senderName,
glob: prevEntity
});
}
// Unknown type. We'll say something, but we shouldn't end up here.
return () => (0, _languageHandler._t)("timeline|mjolnir|removed_rule", {
senderName,
glob: prevEntity
});
}
// Invalid rule
if (!recommendation || !reason) return () => (0, _languageHandler._t)("timeline|mjolnir|updated_invalid_rule", {
senderName
});
// Rule updated
if (entity === prevEntity) {
if (_BanList.USER_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|updated_rule_users", {
senderName,
glob: entity,
reason
});
} else if (_BanList.ROOM_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|updated_rule_rooms", {
senderName,
glob: entity,
reason
});
} else if (_BanList.SERVER_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|updated_rule_servers", {
senderName,
glob: entity,
reason
});
}
// Unknown type. We'll say something but we shouldn't end up here.
return () => (0, _languageHandler._t)("timeline|mjolnir|updated_rule", {
senderName,
glob: entity,
reason
});
}
// New rule
if (!prevEntity) {
if (_BanList.USER_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|created_rule_users", {
senderName,
glob: entity,
reason
});
} else if (_BanList.ROOM_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|created_rule_rooms", {
senderName,
glob: entity,
reason
});
} else if (_BanList.SERVER_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|created_rule_servers", {
senderName,
glob: entity,
reason
});
}
// Unknown type. We'll say something but we shouldn't end up here.
return () => (0, _languageHandler._t)("timeline|mjolnir|created_rule", {
senderName,
glob: entity,
reason
});
}
// else the entity !== prevEntity - count as a removal & add
if (_BanList.USER_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|changed_rule_users", {
senderName,
oldGlob: prevEntity,
newGlob: entity,
reason
});
} else if (_BanList.ROOM_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|changed_rule_rooms", {
senderName,
oldGlob: prevEntity,
newGlob: entity,
reason
});
} else if (_BanList.SERVER_RULE_TYPES.includes(event.getType())) {
return () => (0, _languageHandler._t)("timeline|mjolnir|changed_rule_servers", {
senderName,
oldGlob: prevEntity,
newGlob: entity,
reason
});
}
// Unknown type. We'll say something but we shouldn't end up here.
return () => (0, _languageHandler._t)("timeline|mjolnir|changed_rule_glob", {
senderName,
oldGlob: prevEntity,
newGlob: entity,
reason
});
}
function textForLocationEvent(event) {
return () => (0, _languageHandler._t)("timeline|m.location|full", {
senderName: (0, _getSenderName.getSenderName)(event)
});
}
function textForRedactedPollAndMessageEvent(ev, client) {
let message = (0, _languageHandler._t)("timeline|self_redaction");
const unsigned = ev.getUnsigned();
const redactedBecauseUserId = unsigned?.redacted_because?.sender;
if (redactedBecauseUserId && redactedBecauseUserId !== ev.getSender()) {
const room = client.getRoom(ev.getRoomId());
const sender = room?.getMember(redactedBecauseUserId);
message = (0, _languageHandler._t)("timeline|redaction", {
name: sender?.name || redactedBecauseUserId
});
}
return message;
}
function textForPollStartEvent(event, client) {
return () => {
let message = "";
if (event.isRedacted()) {
message = textForRedactedPollAndMessageEvent(event, client);
const senderDisplayName = event.sender?.name ?? event.getSender();
message = senderDisplayName + ": " + message;
} else {
message = (0, _languageHandler._t)("timeline|m.poll.start", {
senderName: (0, _getSenderName.getSenderName)(event),
pollQuestion: event.unstableExtensibleEvent?.question?.text
});
}
return message;
};
}
function textForPollEndEvent(event) {
return () => (0, _languageHandler._t)("timeline|m.poll.end|sender_ended", {
senderName: (0, _getSenderName.getSenderName)(event)
});
}
const handlers = {
[_matrix.EventType.RoomMessage]: textForMessageEvent,
[_matrix.EventType.Sticker]: textForMessageEvent,
[_matrix.EventType.CallInvite]: textForCallInviteEvent,
[_matrix.M_POLL_START.name]: textForPollStartEvent,
[_matrix.M_POLL_END.name]: textForPollEndEvent,
[_matrix.M_POLL_START.altName]: textForPollStartEvent,
[_matrix.M_POLL_END.altName]: textForPollEndEvent
};
const stateHandlers = {
[_matrix.EventType.RoomCanonicalAlias]: textForCanonicalAliasEvent,
[_matrix.EventType.RoomName]: textForRoomNameEvent,
[_matrix.EventType.RoomTopic]: textForTopicEvent,
[_matrix.EventType.RoomMember]: textForMemberEvent,
[_matrix.EventType.RoomAvatar]: textForRoomAvatarEvent,
[_matrix.EventType.RoomThirdPartyInvite]: textForThreePidInviteEvent,
[_matrix.EventType.RoomHistoryVisibility]: textForHistoryVisibilityEvent,
[_matrix.EventType.RoomPowerLevels]: textForPowerEvent,
[_matrix.EventType.RoomPinnedEvents]: textForPinnedEvent,
[_matrix.EventType.RoomServerAcl]: textForServerACLEvent,
[_matrix.EventType.RoomTombstone]: textForTombstoneEvent,
[_matrix.EventType.RoomJoinRules]: textForJoinRulesEvent,
[_matrix.EventType.RoomGuestAccess]: textForGuestAccessEvent,
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
"im.vector.modular.widgets": textForWidgetEvent,
[_WidgetLayoutStore.WIDGET_LAYOUT_EVENT_TYPE]: textForWidgetLayoutEvent,
[_voiceBroadcast.VoiceBroadcastInfoEventType]: _voiceBroadcast.textForVoiceBroadcastStoppedEvent
};
// Add all the Mjolnir stuff to the renderer
for (const evType of _BanList.ALL_RULE_TYPES) {
stateHandlers[evType] = textForMjolnirEvent;
}
// Add both stable and unstable m.call events
for (const evType of _Call.ElementCall.CALL_EVENT_TYPE.names) {
stateHandlers[evType] = textForCallEvent;
}
/**
* Determines whether the given event has text to display.
*
* @param client The Matrix Client instance for the logged-in user
* @param ev The event
* @param showHiddenEvents An optional cached setting value for showHiddenEventsInTimeline
* to avoid hitting the settings store
*/
function hasText(ev, client, showHiddenEvents) {
const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()];
return Boolean(handler?.(ev, client, false, showHiddenEvents));
}
/**
* Gets the textual content of the given event.
*
* @param ev The event
* @param client The Matrix Client instance for the logged-in user
* @param allowJSX Whether to output rich JSX content
* @param showHiddenEvents An optional cached setting value for showHiddenEventsInTimeline
* to avoid hitting the settings store
*/
function textForEvent(ev, client, allowJSX = false, showHiddenEvents) {
const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()];
return handler?.(ev, client, allowJSX, showHiddenEvents)?.() || "";
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9tYXRyaXgiLCJfdHlwZXMiLCJfbG9nZ2VyIiwiX3V0aWxzIiwiX2xhbmd1YWdlSGFuZGxlciIsIlJvbGVzIiwiX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQiLCJfUm9vbUludml0ZSIsIl9TZXR0aW5nc1N0b3JlIiwiX0Jhbkxpc3QiLCJfV2lkZ2V0TGF5b3V0U3RvcmUiLCJfUmlnaHRQYW5lbFN0b3JlUGhhc2VzIiwiX2Rpc3BhdGNoZXIiLCJfUm9vbVNldHRpbmdzRGlhbG9nIiwiX0FjY2Vzc2libGVCdXR0b24iLCJfUmlnaHRQYW5lbFN0b3JlIiwiX0V2ZW50VXRpbHMiLCJfQ2FsbCIsIl92b2ljZUJyb2FkY2FzdCIsIl9nZXRTZW5kZXJOYW1lIiwiX1Bvc3Rob2dUcmFja2VycyIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsImdldFJvb21NZW1iZXJEaXNwbGF5bmFtZSIsImNsaWVudCIsImV2ZW50IiwidXNlcklkIiwiZ2V0U2VuZGVyIiwicm9vbUlkIiwiZ2V0Um9vbUlkIiwibWVtYmVyIiwiZ2V0Um9vbSIsImdldE1lbWJlciIsIm5hbWUiLCJyYXdEaXNwbGF5TmFtZSIsIl90IiwidGV4dEZvckNhbGxFdmVudCIsInJvb21OYW1lIiwiaXNTdXBwb3J0ZWQiLCJzdXBwb3J0c1ZvaXAiLCJ0ZXh0Rm9yQ2FsbEludml0ZUV2ZW50Iiwic2VuZGVyTmFtZSIsImdldFNlbmRlck5hbWUiLCJpc1ZvaWNlIiwiZ2V0Q29udGVudCIsIm9mZmVyIiwic2RwIiwiaW5jbHVkZXMiLCJNb2RpZmljYXRpb24iLCJnZXRNb2RpZmljYXRpb24iLCJwcmV2IiwidmFsdWUiLCJDaGFuZ2VkIiwiVW5zZXQiLCJTZXQiLCJOb25lIiwidGV4dEZvck1lbWJlckV2ZW50IiwiZXYiLCJhbGxvd0pTWCIsInNob3dIaWRkZW5FdmVudHMiLCJzZW5kZXIiLCJ0YXJnZXROYW1lIiwidGFyZ2V0IiwiZ2V0U3RhdGVLZXkiLCJwcmV2Q29udGVudCIsImdldFByZXZDb250ZW50IiwiY29udGVudCIsInJlYXNvbiIsIm1lbWJlcnNoaXAiLCJLbm93bk1lbWJlcnNoaXAiLCJJbnZpdGUiLCJ0aHJlZVBpZENvbnRlbnQiLCJ0aGlyZF9wYXJ0eV9pbnZpdGUiLCJkaXNwbGF5X25hbWUiLCJkaXNwbGF5TmFtZSIsIkJhbiIsIkpvaW4iLCJtb2REaXNwbGF5bmFtZSIsImRpc3BsYXluYW1lIiwibW9kQXZhdGFyVXJsIiwiYXZhdGFyX3VybCIsIm9sZERpc3BsYXlOYW1lIiwicmVtb3ZlRGlyZWN0aW9uT3ZlcnJpZGVDaGFycyIsIlNldHRpbmdzU3RvcmUiLCJnZXRWYWx1ZSIsImxvZ2dlciIsIndhcm4iLCJzdGF0ZV9rZXkiLCJMZWF2ZSIsInRleHRGb3JUb3BpY0V2ZW50Iiwic2VuZGVyRGlzcGxheU5hbWUiLCJ0b3BpYyIsInRleHRGb3JSb29tQXZhdGFyRXZlbnQiLCJ0ZXh0Rm9yUm9vbU5hbWVFdmVudCIsInRyaW0iLCJsZW5ndGgiLCJvbGRSb29tTmFtZSIsIm5ld1Jvb21OYW1lIiwidGV4dEZvclRvbWJzdG9uZUV2ZW50Iiwib25WaWV3Sm9pblJ1bGVTZXR0aW5nc0NsaWNrIiwiZGVmYXVsdERpc3BhdGNoZXIiLCJkaXNwYXRjaCIsImFjdGlvbiIsImluaXRpYWxfdGFiX2lkIiwiUm9vbVNldHRpbmdzVGFiIiwiU2VjdXJpdHkiLCJ0ZXh0Rm9ySm9pblJ1bGVzRXZlbnQiLCJqb2luX3J1bGUiLCJKb2luUnVsZSIsIlB1YmxpYyIsIktub2NrIiwiUmVzdHJpY3RlZCIsImNyZWF0ZUVsZW1lbnQiLCJzdWIiLCJraW5kIiwib25DbGljayIsInJ1bGUiLCJ0ZXh0Rm9yR3Vlc3RBY2Nlc3NFdmVudCIsImd1ZXN0X2FjY2VzcyIsIkd1ZXN0QWNjZXNzIiwiQ2FuSm9pbiIsIkZvcmJpZGRlbiIsInRleHRGb3JTZXJ2ZXJBQ0xFdmVudCIsImN1cnJlbnQiLCJkZW55IiwiQXJyYXkiLCJpc0FycmF5IiwiYWxsb3ciLCJhbGxvd19pcF9saXRlcmFscyIsImdldFRleHQiLCJ0ZXh0Rm9yTWVzc2FnZUV2ZW50IiwiaXNMb2NhdGlvbkV2ZW50IiwidGV4dEZvckxvY2F0aW9uRXZlbnQiLCJtZXNzYWdlIiwiYm9keSIsImlzUmVkYWN0ZWQiLCJ0ZXh0Rm9yUmVkYWN0ZWRQb2xsQW5kTWVzc2FnZUV2ZW50IiwibXNndHlwZSIsIk1zZ1R5cGUiLCJFbW90ZSIsIkltYWdlIiwiZ2V0VHlwZSIsIkV2ZW50VHlwZSIsIlN0aWNrZXIiLCJ0ZXh0Rm9yQ2Fub25pY2FsQWxpYXNFdmVudCIsIm9sZEFsaWFzIiwiYWxpYXMiLCJvbGRBbHRBbGlhc2VzIiwiYWx0X2FsaWFzZXMiLCJuZXdBbGlhcyIsIm5ld0FsdEFsaWFzZXMiLCJyZW1vdmVkQWx0QWxpYXNlcyIsImZpbHRlciIsImFkZGVkQWx0QWxpYXNlcyIsImFkZHJlc3MiLCJhZGRyZXNzZXMiLCJqb2luIiwiY291bnQiLCJ0ZXh0Rm9yVGhyZWVQaWRJbnZpdGVFdmVudCIsImlzVmFsaWQzcGlkSW52aXRlIiwidGFyZ2V0RGlzcGxheU5hbWUiLCJ0ZXh0Rm9ySGlzdG9yeVZpc2liaWxpdHlFdmVudCIsImhpc3RvcnlfdmlzaWJpbGl0eSIsIkhpc3RvcnlWaXNpYmlsaXR5IiwiSW52aXRlZCIsIkpvaW5lZCIsIlNoYXJlZCIsIldvcmxkUmVhZGFibGUiLCJ2aXNpYmlsaXR5IiwidGV4dEZvclBvd2VyRXZlbnQiLCJ1c2VycyIsInByZXZpb3VzVXNlckRlZmF1bHQiLCJ1c2Vyc19kZWZhdWx0IiwiY3VycmVudFVzZXJEZWZhdWx0Iiwia2V5cyIsImZvckVhY2giLCJpbmRleE9mIiwicHVzaCIsImRpZmZzIiwiZnJvbSIsIk51bWJlciIsImlzSW50ZWdlciIsInRvIiwicG93ZXJMZXZlbERpZmZUZXh0IiwibWFwIiwiZGlmZiIsImZyb21Qb3dlckxldmVsIiwidGV4dHVhbFBvd2VyTGV2ZWwiLCJ0b1Bvd2VyTGV2ZWwiLCJvblBpbm5lZE1lc3NhZ2VzQ2xpY2siLCJQb3N0aG9nVHJhY2tlcnMiLCJ0cmFja0ludGVyYWN0aW9uIiwiUmlnaHRQYW5lbFN0b3JlIiwiaW5zdGFuY2UiLCJzZXRDYXJkIiwicGhhc2UiLCJSaWdodFBhbmVsUGhhc2VzIiwiUGlubmVkTWVzc2FnZXMiLCJ0ZXh0Rm9yUGlubmVkRXZlbnQiLCJwaW5uZWQiLCJwcmV2aW91c2x5UGlubmVkIiwibmV3bHlQaW5uZWQiLCJpdGVtIiwibmV3bHlVbnBpbm5lZCIsIm1lc3NhZ2VJZCIsInBvcCIsImhpZ2hsaWdodEV2ZW50IiwiYiIsInRleHRGb3JXaWRnZXRFdmVudCIsInByZXZOYW1lIiwidHlwZSIsInByZXZUeXBlIiwidXJsIiwicHJldlVybCIsIndpZGdldE5hbWUiLCJ0b1VwcGVyQ2FzZSIsInNsaWNlIiwidGV4dEZvcldpZGdldExheW91dEV2ZW50IiwidGV4dEZvck1qb2xuaXJFdmVudCIsImVudGl0eSIsInByZXZFbnRpdHkiLCJyZWNvbW1lbmRhdGlvbiIsIlVTRVJfUlVMRV9UWVBFUyIsImdsb2IiLCJST09NX1JVTEVfVFlQRVMiLCJTRVJWRVJfUlVMRV9UWVBFUyIsIm9sZEdsb2IiLCJuZXdHbG9iIiwidW5zaWduZWQiLCJnZXRVbnNpZ25lZCIsInJlZGFjdGVkQmVjYXVzZVVzZXJJZCIsInJlZGFjdGVkX2JlY2F1c2UiLCJyb29tIiwidGV4dEZvclBvbGxTdGFydEV2ZW50IiwicG9sbFF1ZXN0aW9uIiwidW5zdGFibGVFeHRlbnNpYmxlRXZlbnQiLCJxdWVzdGlvbiIsInRleHQiLCJ0ZXh0Rm9yUG9sbEVuZEV2ZW50IiwiaGFuZGxlcnMiLCJSb29tTWVzc2FnZSIsIkNhbGxJbnZpdGUiLCJNX1BPTExfU1RBUlQiLCJNX1BPTExfRU5EIiwiYWx0TmFtZSIsInN0YXRlSGFuZGxlcnMiLCJSb29tQ2Fub25pY2FsQWxpYXMiLCJSb29tTmFtZSIsIlJvb21Ub3BpYyIsIlJvb21NZW1iZXIiLCJSb29tQXZhdGFyIiwiUm9vbVRoaXJkUGFydHlJbnZpdGUiLCJSb29tSGlzdG9yeVZpc2liaWxpdHkiLCJSb29tUG93ZXJMZXZlbHMiLCJSb29tUGlubmVkRXZlbnRzIiwiUm9vbVNlcnZlckFjbCIsIlJvb21Ub21ic3RvbmUiLCJSb29tSm9pblJ1bGVzIiwiUm9vbUd1ZXN0QWNjZXNzIiwiV0lER0VUX0xBWU9VVF9FVkVOVF9UWVBFIiwiVm9pY2VCcm9hZGNhc3RJbmZvRXZlbnRUeXBlIiwidGV4dEZvclZvaWNlQnJvYWRjYXN0U3RvcHBlZEV2ZW50IiwiZXZUeXBlIiwiQUxMX1JVTEVfVFlQRVMiLCJFbGVtZW50Q2FsbCIsIkNBTExfRVZFTlRfVFlQRSIsIm5hbWVzIiwiaGFzVGV4dCIsImhhbmRsZXIiLCJpc1N0YXRlIiwiQm9vbGVhbiIsInRleHRGb3JFdmVudCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9UZXh0Rm9yRXZlbnQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE1LTIwMjIgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHtcbiAgICBNYXRyaXhFdmVudCxcbiAgICBNYXRyaXhDbGllbnQsXG4gICAgR3Vlc3RBY2Nlc3MsXG4gICAgSGlzdG9yeVZpc2liaWxpdHksXG4gICAgSm9pblJ1bGUsXG4gICAgRXZlbnRUeXBlLFxuICAgIE1zZ1R5cGUsXG4gICAgTV9QT0xMX1NUQVJULFxuICAgIE1fUE9MTF9FTkQsXG59IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcbmltcG9ydCB7IEtub3duTWVtYmVyc2hpcCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy90eXBlc1wiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuaW1wb3J0IHsgcmVtb3ZlRGlyZWN0aW9uT3ZlcnJpZGVDaGFycyB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy91dGlsc1wiO1xuaW1wb3J0IHsgUG9sbFN0YXJ0RXZlbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvZXh0ZW5zaWJsZV9ldmVudHNfdjEvUG9sbFN0YXJ0RXZlbnRcIjtcblxuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCAqIGFzIFJvbGVzIGZyb20gXCIuL1JvbGVzXCI7XG5pbXBvcnQgeyBpc1ZhbGlkM3BpZEludml0ZSB9IGZyb20gXCIuL1Jvb21JbnZpdGVcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCB7IEFMTF9SVUxFX1RZUEVTLCBST09NX1JVTEVfVFlQRVMsIFNFUlZFUl9SVUxFX1RZUEVTLCBVU0VSX1JVTEVfVFlQRVMgfSBmcm9tIFwiLi9tam9sbmlyL0Jhbkxpc3RcIjtcbmltcG9ydCB7IFdJREdFVF9MQVlPVVRfRVZFTlRfVFlQRSB9IGZyb20gXCIuL3N0b3Jlcy93aWRnZXRzL1dpZGdldExheW91dFN0b3JlXCI7XG5pbXBvcnQgeyBSaWdodFBhbmVsUGhhc2VzIH0gZnJvbSBcIi4vc3RvcmVzL3JpZ2h0LXBhbmVsL1JpZ2h0UGFuZWxTdG9yZVBoYXNlc1wiO1xuaW1wb3J0IGRlZmF1bHREaXNwYXRjaGVyIGZyb20gXCIuL2Rpc3BhdGNoZXIvZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHsgUm9vbVNldHRpbmdzVGFiIH0gZnJvbSBcIi4vY29tcG9uZW50cy92aWV3cy9kaWFsb2dzL1Jvb21TZXR0aW5nc0RpYWxvZ1wiO1xuaW1wb3J0IEFjY2Vzc2libGVCdXR0b24gZnJvbSBcIi4vY29tcG9uZW50cy92aWV3cy9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgUmlnaHRQYW5lbFN0b3JlIGZyb20gXCIuL3N0b3Jlcy9yaWdodC1wYW5lbC9SaWdodFBhbmVsU3RvcmVcIjtcbmltcG9ydCB7IGhpZ2hsaWdodEV2ZW50LCBpc0xvY2F0aW9uRXZlbnQgfSBmcm9tIFwiLi91dGlscy9FdmVudFV0aWxzXCI7XG5pbXBvcnQgeyBFbGVtZW50Q2FsbCB9IGZyb20gXCIuL21vZGVscy9DYWxsXCI7XG5pbXBvcnQgeyB0ZXh0Rm9yVm9pY2VCcm9hZGNhc3RTdG9wcGVkRXZlbnQsIFZvaWNlQnJvYWRjYXN0SW5mb0V2ZW50VHlwZSB9IGZyb20gXCIuL3ZvaWNlLWJyb2FkY2FzdFwiO1xuaW1wb3J0IHsgZ2V0U2VuZGVyTmFtZSB9IGZyb20gXCIuL3V0aWxzL2V2ZW50L2dldFNlbmRlck5hbWVcIjtcbmltcG9ydCBQb3N0aG9nVHJhY2tlcnMgZnJvbSBcIi4vUG9zdGhvZ1RyYWNrZXJzLnRzXCI7XG5cbmZ1bmN0aW9uIGdldFJvb21NZW1iZXJEaXNwbGF5bmFtZShjbGllbnQ6IE1hdHJpeENsaWVudCwgZXZlbnQ6IE1hdHJpeEV2ZW50LCB1c2VySWQgPSBldmVudC5nZXRTZW5kZXIoKSk6IHN0cmluZyB7XG4gICAgY29uc3Qgcm9vbUlkID0gZXZlbnQuZ2V0Um9vbUlkKCk7XG4gICAgY29uc3QgbWVtYmVyID0gY2xpZW50LmdldFJvb20ocm9vbUlkKT8uZ2V0TWVtYmVyKHVzZXJJZCEpO1xuICAgIHJldHVybiBtZW1iZXI/Lm5hbWUgfHwgbWVtYmVyPy5yYXdEaXNwbGF5TmFtZSB8fCB1c2VySWQgfHwgX3QoXCJjb21tb258c29tZW9uZVwiKTtcbn1cblxuZnVuY3Rpb24gdGV4dEZvckNhbGxFdmVudChldmVudDogTWF0cml4RXZlbnQsIGNsaWVudDogTWF0cml4Q2xpZW50KTogKCkgPT4gc3RyaW5nIHtcbiAgICBjb25zdCByb29tTmFtZSA9IGNsaWVudC5nZXRSb29tKGV2ZW50LmdldFJvb21JZCgpISk/Lm5hbWU7XG4gICAgY29uc3QgaXNTdXBwb3J0ZWQgPSBjbGllbnQuc3VwcG9ydHNWb2lwKCk7XG5cbiAgICByZXR1cm4gaXNTdXBwb3J0ZWRcbiAgICAgICAgPyAoKSA9PiBfdChcInRpbWVsaW5lfG0uY2FsbHx2aWRlb19jYWxsX3N0YXJ0ZWRcIiwgeyByb29tTmFtZSB9KVxuICAgICAgICA6ICgpID0+IF90KFwidGltZWxpbmV8bS5jYWxsfHZpZGVvX2NhbGxfc3RhcnRlZF91bnN1cHBvcnRlZFwiLCB7IHJvb21OYW1lIH0pO1xufVxuXG4vLyBUaGVzZSBmdW5jdGlvbnMgYXJlIGZyZXF1ZW50bHkgdXNlZCBqdXN0IHRvIGNoZWNrIHdoZXRoZXIgYW4gZXZlbnQgaGFzXG4vLyBhbnkgdGV4dCB0byBkaXNwbGF5IGF0IGFsbC4gRm9yIHRoaXMgcmVhc29uIHRoZXkgcmV0dXJuIGRlZmVycmVkIHZhbHVlc1xuLy8gdG8gYXZvaWQgdGhlIGV4cGVuc2Ugb2YgbG9va2luZyB1cCB0cmFuc2xhdGlvbnMgd2hlbiB0aGV5J3JlIG5vdCBuZWVkZWQuXG5cbmZ1bmN0aW9uIHRleHRGb3JDYWxsSW52aXRlRXZlbnQoZXZlbnQ6IE1hdHJpeEV2ZW50LCBjbGllbnQ6IE1hdHJpeENsaWVudCk6ICgoKSA9PiBzdHJpbmcpIHwgbnVsbCB7XG4gICAgY29uc3Qgc2VuZGVyTmFtZSA9IGdldFNlbmRlck5hbWUoZXZlbnQpO1xuICAgIC8vIEZJWE1FOiBGaW5kIGEgYmV0dGVyIHdheSB0byBkZXRlcm1pbmUgdGhpcyBmcm9tIHRoZSBldmVudD9cbiAgICBjb25zdCBpc1ZvaWNlID0gIWV2ZW50LmdldENvbnRlbnQoKS5vZmZlcj8uc2RwPy5pbmNsdWRlcyhcIm09dmlkZW9cIik7XG4gICAgY29uc3QgaXNTdXBwb3J0ZWQgPSBjbGllbnQuc3VwcG9ydHNWb2lwKCk7XG5cbiAgICAvLyBUaGlzIGxhZGRlciBjb3VsZCBiZSByZWR1Y2VkIGRvd24gdG8gYSBjb3VwbGUgc3RyaW5nIHZhcmlhYmxlcywgaG93ZXZlciBvdGhlciBsYW5ndWFnZXNcbiAgICAvLyBjYW4gaGF2ZSBhIGhhcmQgdGltZSB0cmFuc2xhdGluZyB0aG9zZSBzdHJpbmdzLiBJbiBhbiBlZmZvcnQgdG8gbWFrZSB0cmFuc2xhdGlvbnMgZWFzaWVyXG4gICAgLy8gYW5kIG1vcmUgYWNjdXJhdGUsIHdlIGJyZWFrIG91dCB0aGUgc3RyaW5nLWJhc2VkIHZhcmlhYmxlcyB0byBhIGNvdXBsZSBib29sZWFucy5cbiAgICBpZiAoaXNWb2ljZSAmJiBpc1N1cHBvcnRlZCkge1xuICAgICAgICByZXR1cm4gKCkgPT4gX3QoXCJ0aW1lbGluZXxtLmNhbGwuaW52aXRlfHZvaWNlX2NhbGxcIiwgeyBzZW5kZXJOYW1lIH0pO1xuICAgIH0gZWxzZSBpZiAoaXNWb2ljZSAmJiAhaXNTdXBwb3J0ZWQpIHtcbiAgICAgICAgcmV0dXJuICgpID0+IF90KFwidGltZWxpbmV8bS5jYWxsLmludml0ZXx2b2ljZV9jYWxsX3Vuc3VwcG9ydGVkXCIsIHsgc2VuZGVyTmFtZSB9KTtcbiAgICB9IGVsc2UgaWYgKCFpc1ZvaWNlICYmIGlzU3VwcG9ydGVkKSB7XG4gICAgICAgIHJldHVybiAoKSA9PiBfdChcInRpbWVsaW5lfG0uY2FsbC5pbnZpdGV8dmlkZW9fY2FsbFwiLCB7IHNlbmRlck5hbWUgfSk7XG4gICAgfSBlbHNlIGlmICghaXNWb2ljZSAmJiAhaXNTdXBwb3J0ZWQpIHtcbiAgICAgICAgcmV0dXJuICgpID0+IF90KFwidGltZWxpbmV8bS5jYWxsLmludml0ZXx2aWRlb19jYWxsX3Vuc3VwcG9ydGVkXCIsIHsgc2VuZGVyTmFtZSB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuZW51bSBNb2RpZmljYXRpb24ge1xuICAgIE5vbmUsXG4gICAgVW5zZXQsXG4gICAgU2V0LFxuICAgIENoYW5nZWQsXG59XG5cbmZ1bmN0aW9uIGdldE1vZGlmaWNhdGlvbihwcmV2Pzogc3RyaW5nLCB2YWx1ZT86IHN0cmluZyk6IE1vZGlmaWNhdGlvbiB7XG4gICAgaWYgKHByZXYgJiYgdmFsdWUgJiYgcHJldiAhPT0gdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIE1vZGlmaWNhdGlvbi5DaGFuZ2VkO1xuICAgIH1cbiAgICBpZiAocHJldiAmJiAhdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIE1vZGlmaWNhdGlvbi5VbnNldDtcbiAgICB9XG4gICAgaWYgKCFwcmV2ICYmIHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBNb2RpZmljYXRpb24uU2V0O1xuICAgIH1cblxuICAgIHJldHVybiBNb2RpZmljYXRpb24uTm9uZTtcbn1cblxuZnVuY3Rpb24gdGV4dEZvck1lbWJlckV2ZW50KFxuICAgIGV2OiBNYXRyaXhFdmVudCxcbiAgICBjbGllbnQ6IE1hdHJpeENsaWVudCxcbiAgICBhbGxvd0pTWDogYm9vbGVhbixcbiAgICBzaG93SGlkZGVuRXZlbnRzPzogYm9vbGVhbixcbik6ICgoKSA9PiBzdHJpbmcpIHwgbnVsbCB7XG4gICAgLy8gWFhYOiBTWUpTLTE2IFwic2VuZGVyIGlzIHNvbWV0aW1lcyBudWxsIGZvciBqb2luIG1lc3NhZ2VzXCJcbiAgICBjb25zdCBzZW5kZXJOYW1lID0gZXYuc2VuZGVyPy5uYW1lIHx8IGdldFJvb21NZW1iZXJEaXNwbGF5bmFtZShjbGllbnQsIGV2KTtcbiAgICBjb25zdCB0YXJnZXROYW1lID0gZXYudGFyZ2V0Py5uYW1lIHx8IGdldFJvb21NZW1iZXJEaXNwbGF5bmFtZShjbGllbnQsIGV2LCBldi5nZXRTdGF0ZUtleSgpKTtcbiAgICBjb25zdCBwcmV2Q29udGVudCA9IGV2LmdldFByZXZDb250ZW50KCk7XG4gICAgY29uc3QgY29udGVudCA9IGV2LmdldENvbnRlbnQoKTtcbiAgICBjb25zdCByZWFzb24gPSBjb250ZW50LnJlYXNvbjtcblxuICAgIHN3aXRjaCAoY29udGVudC5tZW1iZXJzaGlwKSB7XG4gICAgICAgIGNhc2UgS25vd25NZW1iZXJzaGlwLkludml0ZToge1xuICAgICAgICAgICAgY29uc3QgdGhyZWVQaWRDb250ZW50ID0gY29udGVudC50aGlyZF9wYXJ0eV9pbnZpdGU7XG4gICAgICAgICAgICBpZiAodGhyZWVQaWRDb250ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRocmVlUGlkQ29udGVudC5kaXNwbGF5X25hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICBfdChcInRpbWVsaW5lfG0ucm9vbS5tZW1iZXJ8YWNjZXB0ZWRfM3BpZF9pbnZpdGVcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheU5hbWU6IHRocmVlUGlkQ29udGVudC5kaXNwbGF5X25hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCkgPT4gX3QoXCJ0aW1lbGluZXxtLnJvb20ubWVtYmVyfGFjY2VwdGVkX2ludml0ZVwiLCB7IHRhcmdldE5hbWUgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKCkgPT4gX3QoXCJ0aW1lbGluZXxtLnJvb20ubWVtYmVyfGludml0ZVwiLCB7IHNlbmRlck5hbWUsIHRhcmdldE5hbWUgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSBLbm93bk1lbWJlcnNoaXAuQmFuOlxuICAgICAgICAgICAgcmV0dXJuICgpID0+XG4gICAgICAgICAgICAgICAgcmVhc29uXG4gICAgICAgICAgICAgICAgICAgID8gX3QoXCJ0aW1lbGluZXxtLnJvb20ubWVtYmVyfGJhbl9yZWFzb25cIiwgeyBzZW5kZXJOYW1lLCB0YXJnZXROYW1lLCByZWFzb24gfSlcbiAgICAgICAgICAgICAgICAgICAgOiBfdChcInRpbWVsaW5lfG0ucm9vbS5tZW1iZXJ8YmFuXCIsIHsgc2VuZGVyTmFtZSwgdGFyZ2V0TmFtZSB9KTtcbiAgICAgICAgY2FzZSBLbm93bk1lbWJlcnNoaXAuSm9pbjpcbiAgICAgICAgICAgIGlmIChwcmV2Q29udGVudCAmJiBwcmV2Q29udGVudC5tZW1iZXJzaGlwID09PSBLbm93bk1lbWJlcnNoaXAuSm9pbikge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1vZERpc3BsYXluYW1lID0gZ2V0TW9kaWZpY2F0aW9uKHByZXZDb250ZW50LmRpc3BsYXluYW1lLCBjb250ZW50LmRpc3BsYXluYW1lKTtcbiAgICAgICAgICAgICAgICBjb25zdCBtb2RBdmF0YXJVcmwgPSBnZXRNb2RpZmljYXRpb24ocHJldkNvbnRlbnQuYXZhdGFyX3VybCwgY29udGVudC5hdmF0YXJfdXJsKTtcblxuICAgICAgICAgICAgICAgIGlmIChtb2REaXNwbGF5bmFtZSAhPT0gTW9kaWZpY2F0aW9uLk5vbmUgJiYgbW9kQXZhdGFyVXJsICE9PSBNb2RpZmljYXRpb24uTm9uZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBDb21wcm9taXNlIHRvIHByb3ZpZGUgdGhlIHVzZXIgd2l0aCBtb3JlIGNvbnRleHQgd2