Add MatrixClientPeg::safeGet and use it in tests (#10985)
This commit is contained in:
parent
c47b587225
commit
6b46d6e4f8
88 changed files with 290 additions and 226 deletions
|
@ -38,7 +38,7 @@ import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } fro
|
|||
import SecurityCustomisations from "./customisations/Security";
|
||||
import { SlidingSyncManager } from "./SlidingSyncManager";
|
||||
import CryptoStoreTooNewDialog from "./components/views/dialogs/CryptoStoreTooNewDialog";
|
||||
import { _t } from "./languageHandler";
|
||||
import { _t, UserFriendlyError } from "./languageHandler";
|
||||
import { SettingLevel } from "./settings/SettingLevel";
|
||||
import MatrixClientBackedController from "./settings/controllers/MatrixClientBackedController";
|
||||
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
||||
|
@ -49,7 +49,7 @@ export interface IMatrixClientCreds {
|
|||
identityServerUrl?: string;
|
||||
userId: string;
|
||||
deviceId?: string;
|
||||
accessToken: string;
|
||||
accessToken?: string;
|
||||
guest?: boolean;
|
||||
pickleKey?: string;
|
||||
freshLogin?: boolean;
|
||||
|
@ -71,9 +71,10 @@ export interface IMatrixClientPeg {
|
|||
*
|
||||
* @returns {string} The homeserver name, if present.
|
||||
*/
|
||||
getHomeserverName(): string;
|
||||
getHomeserverName(): string | null;
|
||||
|
||||
get(): MatrixClient;
|
||||
safeGet(): MatrixClient;
|
||||
unset(): void;
|
||||
assign(): Promise<any>;
|
||||
start(): Promise<any>;
|
||||
|
@ -134,7 +135,7 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
|||
initialSyncLimit: 20,
|
||||
};
|
||||
|
||||
private matrixClient: MatrixClient = null;
|
||||
private matrixClient: MatrixClient | null = null;
|
||||
private justRegisteredUserId: string | null = null;
|
||||
|
||||
// the credentials used to init the current client object.
|
||||
|
@ -145,6 +146,13 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
|||
return this.matrixClient;
|
||||
}
|
||||
|
||||
public safeGet(): MatrixClient {
|
||||
if (!this.matrixClient) {
|
||||
throw new UserFriendlyError("User is not logged in");
|
||||
}
|
||||
return this.matrixClient;
|
||||
}
|
||||
|
||||
public unset(): void {
|
||||
this.matrixClient = null;
|
||||
|
||||
|
@ -215,6 +223,10 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
|||
};
|
||||
|
||||
public async assign(): Promise<any> {
|
||||
if (!this.matrixClient) {
|
||||
throw new Error("createClient must be called first");
|
||||
}
|
||||
|
||||
for (const dbType of ["indexeddb", "memory"]) {
|
||||
try {
|
||||
const promise = this.matrixClient.store.startup();
|
||||
|
@ -275,6 +287,10 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
|||
* Attempt to initialize the crypto layer on a newly-created MatrixClient
|
||||
*/
|
||||
private async initClientCrypto(): Promise<void> {
|
||||
if (!this.matrixClient) {
|
||||
throw new Error("createClient must be called first");
|
||||
}
|
||||
|
||||
const useRustCrypto = SettingsStore.getValue("feature_rust_crypto");
|
||||
|
||||
// we want to make sure that the same crypto implementation is used throughout the lifetime of a device,
|
||||
|
@ -317,11 +333,15 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
|||
const opts = await this.assign();
|
||||
|
||||
logger.log(`MatrixClientPeg: really starting MatrixClient`);
|
||||
await this.get().startClient(opts);
|
||||
await this.matrixClient!.startClient(opts);
|
||||
logger.log(`MatrixClientPeg: MatrixClient started`);
|
||||
}
|
||||
|
||||
public getCredentials(): IMatrixClientCreds {
|
||||
if (!this.matrixClient) {
|
||||
throw new Error("createClient must be called first");
|
||||
}
|
||||
|
||||
let copiedCredentials: IMatrixClientCreds | null = this.currentClientCreds;
|
||||
if (this.currentClientCreds?.userId !== this.matrixClient?.credentials?.userId) {
|
||||
// cached credentials belong to a different user - don't use them
|
||||
|
@ -335,12 +355,14 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
|||
identityServerUrl: this.matrixClient.idBaseUrl,
|
||||
userId: this.matrixClient.getSafeUserId(),
|
||||
deviceId: this.matrixClient.getDeviceId() ?? undefined,
|
||||
accessToken: this.matrixClient.getAccessToken(),
|
||||
accessToken: this.matrixClient.getAccessToken() ?? undefined,
|
||||
guest: this.matrixClient.isGuest(),
|
||||
};
|
||||
}
|
||||
|
||||
public getHomeserverName(): string {
|
||||
public getHomeserverName(): string | null {
|
||||
if (!this.matrixClient) return null;
|
||||
|
||||
const matches = /^@[^:]+:(.+)$/.exec(this.matrixClient.getSafeUserId());
|
||||
if (matches === null || matches.length < 1) {
|
||||
throw new Error("Failed to derive homeserver name from user ID!");
|
||||
|
|
|
@ -91,7 +91,7 @@ const msgTypeHandlers: Record<string, (event: MatrixEvent) => string | null> = {
|
|||
return null;
|
||||
}
|
||||
|
||||
return TextForEvent.textForEvent(event);
|
||||
return TextForEvent.textForEvent(event, MatrixClientPeg.get());
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -111,7 +111,7 @@ class NotifierClass {
|
|||
if (msgType && msgTypeHandlers.hasOwnProperty(msgType)) {
|
||||
return msgTypeHandlers[msgType](ev);
|
||||
}
|
||||
return TextForEvent.textForEvent(ev);
|
||||
return TextForEvent.textForEvent(ev, MatrixClientPeg.get());
|
||||
}
|
||||
|
||||
// XXX: exported for tests
|
||||
|
|
|
@ -22,6 +22,7 @@ import { GuestAccess, HistoryVisibility, JoinRule } from "matrix-js-sdk/src/@typ
|
|||
import { EventType, MsgType } from "matrix-js-sdk/src/@types/event";
|
||||
import { M_POLL_START, M_POLL_END } from "matrix-js-sdk/src/@types/polls";
|
||||
import { PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { _t } from "./languageHandler";
|
||||
import * as Roles from "./Roles";
|
||||
|
@ -31,7 +32,6 @@ import { ALL_RULE_TYPES, ROOM_RULE_TYPES, SERVER_RULE_TYPES, USER_RULE_TYPES } f
|
|||
import { WIDGET_LAYOUT_EVENT_TYPE } from "./stores/widgets/WidgetLayoutStore";
|
||||
import { RightPanelPhases } from "./stores/right-panel/RightPanelStorePhases";
|
||||
import defaultDispatcher from "./dispatcher/dispatcher";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import { RoomSettingsTab } from "./components/views/dialogs/RoomSettingsDialog";
|
||||
import AccessibleButton, { ButtonEvent } from "./components/views/elements/AccessibleButton";
|
||||
import RightPanelStore from "./stores/right-panel/RightPanelStore";
|
||||
|
@ -40,16 +40,15 @@ import { ElementCall } from "./models/Call";
|
|||
import { textForVoiceBroadcastStoppedEvent, VoiceBroadcastInfoEventType } from "./voice-broadcast";
|
||||
import { getSenderName } from "./utils/event/getSenderName";
|
||||
|
||||
function getRoomMemberDisplayname(event: MatrixEvent, userId = event.getSender()): string {
|
||||
const client = MatrixClientPeg.get();
|
||||
function getRoomMemberDisplayname(client: MatrixClient, event: MatrixEvent, userId = event.getSender()): string {
|
||||
const roomId = event.getRoomId();
|
||||
const member = client.getRoom(roomId)?.getMember(userId!);
|
||||
return member?.name || member?.rawDisplayName || userId || _t("Someone");
|
||||
}
|
||||
|
||||
function textForCallEvent(event: MatrixEvent): () => string {
|
||||
const roomName = MatrixClientPeg.get().getRoom(event.getRoomId()!)?.name;
|
||||
const isSupported = MatrixClientPeg.get().supportsVoip();
|
||||
function textForCallEvent(event: MatrixEvent, client: MatrixClient): () => string {
|
||||
const roomName = client.getRoom(event.getRoomId()!)?.name;
|
||||
const isSupported = client.supportsVoip();
|
||||
|
||||
return isSupported
|
||||
? () => _t("Video call started in %(roomName)s.", { roomName })
|
||||
|
@ -60,11 +59,11 @@ function textForCallEvent(event: MatrixEvent): () => string {
|
|||
// 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: MatrixEvent): (() => string) | null {
|
||||
function textForCallInviteEvent(event: MatrixEvent, client: MatrixClient): (() => string) | null {
|
||||
const senderName = getSenderName(event);
|
||||
// FIXME: Find a better way to determine this from the event?
|
||||
const isVoice = !event.getContent().offer?.sdp?.includes("m=video");
|
||||
const isSupported = MatrixClientPeg.get().supportsVoip();
|
||||
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
|
||||
|
@ -103,10 +102,15 @@ function getModification(prev?: string, value?: string): Modification {
|
|||
return Modification.None;
|
||||
}
|
||||
|
||||
function textForMemberEvent(ev: MatrixEvent, allowJSX: boolean, showHiddenEvents?: boolean): (() => string) | null {
|
||||
function textForMemberEvent(
|
||||
ev: MatrixEvent,
|
||||
client: MatrixClient,
|
||||
allowJSX: boolean,
|
||||
showHiddenEvents?: boolean,
|
||||
): (() => string) | null {
|
||||
// XXX: SYJS-16 "sender is sometimes null for join messages"
|
||||
const senderName = ev.sender?.name || getRoomMemberDisplayname(ev);
|
||||
const targetName = ev.target?.name || getRoomMemberDisplayname(ev, ev.getStateKey());
|
||||
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;
|
||||
|
@ -269,7 +273,7 @@ const onViewJoinRuleSettingsClick = (): void => {
|
|||
});
|
||||
};
|
||||
|
||||
function textForJoinRulesEvent(ev: MatrixEvent, allowJSX: boolean): () => Renderable {
|
||||
function textForJoinRulesEvent(ev: MatrixEvent, client: MatrixClient, allowJSX: boolean): () => Renderable {
|
||||
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
|
||||
switch (ev.getContent().join_rule) {
|
||||
case JoinRule.Public:
|
||||
|
@ -361,7 +365,7 @@ function textForServerACLEvent(ev: MatrixEvent): (() => string) | null {
|
|||
return getText;
|
||||
}
|
||||
|
||||
function textForMessageEvent(ev: MatrixEvent): (() => string) | null {
|
||||
function textForMessageEvent(ev: MatrixEvent, client: MatrixClient): (() => string) | null {
|
||||
if (isLocationEvent(ev)) {
|
||||
return textForLocationEvent(ev);
|
||||
}
|
||||
|
@ -370,7 +374,7 @@ function textForMessageEvent(ev: MatrixEvent): (() => string) | null {
|
|||
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
|
||||
let message = ev.getContent().body;
|
||||
if (ev.isRedacted()) {
|
||||
message = textForRedactedPollAndMessageEvent(ev);
|
||||
message = textForRedactedPollAndMessageEvent(ev, client);
|
||||
}
|
||||
|
||||
if (ev.getContent().msgtype === MsgType.Emote) {
|
||||
|
@ -496,7 +500,7 @@ function textForHistoryVisibilityEvent(event: MatrixEvent): (() => string) | nul
|
|||
}
|
||||
|
||||
// Currently will only display a change if a user's power level is changed
|
||||
function textForPowerEvent(event: MatrixEvent): (() => string) | null {
|
||||
function textForPowerEvent(event: MatrixEvent, client: MatrixClient): (() => string) | null {
|
||||
const senderName = getSenderName(event);
|
||||
if (!event.getPrevContent()?.users || !event.getContent()?.users) {
|
||||
return null;
|
||||
|
@ -533,7 +537,7 @@ function textForPowerEvent(event: MatrixEvent): (() => string) | null {
|
|||
return;
|
||||
}
|
||||
if (to !== from) {
|
||||
const name = getRoomMemberDisplayname(event, userId);
|
||||
const name = getRoomMemberDisplayname(client, event, userId);
|
||||
diffs.push({ userId, name, from, to });
|
||||
}
|
||||
});
|
||||
|
@ -561,7 +565,7 @@ const onPinnedMessagesClick = (): void => {
|
|||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.PinnedMessages }, false);
|
||||
};
|
||||
|
||||
function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): (() => Renderable) | null {
|
||||
function textForPinnedEvent(event: MatrixEvent, client: MatrixClient, allowJSX: boolean): (() => Renderable) | null {
|
||||
if (!SettingsStore.getValue("feature_pinning")) return null;
|
||||
const senderName = getSenderName(event);
|
||||
const roomId = event.getRoomId()!;
|
||||
|
@ -835,12 +839,12 @@ export function textForLocationEvent(event: MatrixEvent): () => string {
|
|||
});
|
||||
}
|
||||
|
||||
function textForRedactedPollAndMessageEvent(ev: MatrixEvent): string {
|
||||
function textForRedactedPollAndMessageEvent(ev: MatrixEvent, client: MatrixClient): string {
|
||||
let message = _t("Message deleted");
|
||||
const unsigned = ev.getUnsigned();
|
||||
const redactedBecauseUserId = unsigned?.redacted_because?.sender;
|
||||
if (redactedBecauseUserId && redactedBecauseUserId !== ev.getSender()) {
|
||||
const room = MatrixClientPeg.get().getRoom(ev.getRoomId());
|
||||
const room = client.getRoom(ev.getRoomId());
|
||||
const sender = room?.getMember(redactedBecauseUserId);
|
||||
message = _t("Message deleted by %(name)s", {
|
||||
name: sender?.name || redactedBecauseUserId,
|
||||
|
@ -850,12 +854,12 @@ function textForRedactedPollAndMessageEvent(ev: MatrixEvent): string {
|
|||
return message;
|
||||
}
|
||||
|
||||
function textForPollStartEvent(event: MatrixEvent): (() => string) | null {
|
||||
function textForPollStartEvent(event: MatrixEvent, client: MatrixClient): (() => string) | null {
|
||||
return () => {
|
||||
let message = "";
|
||||
|
||||
if (event.isRedacted()) {
|
||||
message = textForRedactedPollAndMessageEvent(event);
|
||||
message = textForRedactedPollAndMessageEvent(event, client);
|
||||
const senderDisplayName = event.sender?.name ?? event.getSender();
|
||||
message = senderDisplayName + ": " + message;
|
||||
} else {
|
||||
|
@ -879,7 +883,12 @@ function textForPollEndEvent(event: MatrixEvent): (() => string) | null {
|
|||
type Renderable = string | React.ReactNode | null;
|
||||
|
||||
interface IHandlers {
|
||||
[type: string]: (ev: MatrixEvent, allowJSX: boolean, showHiddenEvents?: boolean) => (() => Renderable) | null;
|
||||
[type: string]: (
|
||||
ev: MatrixEvent,
|
||||
client: MatrixClient,
|
||||
allowJSX: boolean,
|
||||
showHiddenEvents?: boolean,
|
||||
) => (() => Renderable) | null;
|
||||
}
|
||||
|
||||
const handlers: IHandlers = {
|
||||
|
@ -925,25 +934,39 @@ for (const evType of ElementCall.CALL_EVENT_TYPE.names) {
|
|||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export function hasText(ev: MatrixEvent, showHiddenEvents?: boolean): boolean {
|
||||
export function hasText(ev: MatrixEvent, client: MatrixClient, showHiddenEvents?: boolean): boolean {
|
||||
const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()];
|
||||
return Boolean(handler?.(ev, false, showHiddenEvents));
|
||||
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
|
||||
*/
|
||||
export function textForEvent(ev: MatrixEvent): string;
|
||||
export function textForEvent(ev: MatrixEvent, allowJSX: true, showHiddenEvents?: boolean): string | React.ReactNode;
|
||||
export function textForEvent(ev: MatrixEvent, allowJSX = false, showHiddenEvents?: boolean): string | React.ReactNode {
|
||||
export function textForEvent(ev: MatrixEvent, client: MatrixClient): string;
|
||||
export function textForEvent(
|
||||
ev: MatrixEvent,
|
||||
client: MatrixClient,
|
||||
allowJSX: true,
|
||||
showHiddenEvents?: boolean,
|
||||
): string | React.ReactNode;
|
||||
export function textForEvent(
|
||||
ev: MatrixEvent,
|
||||
client: MatrixClient,
|
||||
allowJSX = false,
|
||||
showHiddenEvents?: boolean,
|
||||
): string | React.ReactNode {
|
||||
const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()];
|
||||
return handler?.(ev, allowJSX, showHiddenEvents)?.() || "";
|
||||
return handler?.(ev, client, allowJSX, showHiddenEvents)?.() || "";
|
||||
}
|
||||
|
|
|
@ -1301,7 +1301,7 @@ class MainGrouper extends BaseGrouper {
|
|||
public add({ event: ev, shouldShow }: EventAndShouldShow): void {
|
||||
if (ev.getType() === EventType.RoomMember) {
|
||||
// We can ignore any events that don't actually have a message to display
|
||||
if (!hasText(ev, this.panel.showHiddenEvents)) return;
|
||||
if (!hasText(ev, MatrixClientPeg.get(), this.panel.showHiddenEvents)) return;
|
||||
}
|
||||
this.readMarker = this.readMarker || this.panel.readMarkerForEvent(ev.getId()!, ev === this.lastShownEvent);
|
||||
if (!this.panel.showHiddenEvents && !shouldShow) {
|
||||
|
|
|
@ -20,7 +20,7 @@ import { M_TEXT } from "matrix-js-sdk/src/@types/extensible_events";
|
|||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { Icon as PollIcon } from "../../../../res/img/element-icons/room/composer/poll.svg";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import MatrixClientContext, { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { textForEvent } from "../../../TextForEvent";
|
||||
import { Caption } from "../typography/Caption";
|
||||
|
@ -95,10 +95,11 @@ const usePollStartEvent = (event: MatrixEvent): { pollStartEvent?: MatrixEvent;
|
|||
};
|
||||
|
||||
export const MPollEndBody = React.forwardRef<any, IBodyProps>(({ mxEvent, ...props }, ref) => {
|
||||
const cli = useMatrixClientContext();
|
||||
const { pollStartEvent, isLoadingPollStartEvent } = usePollStartEvent(mxEvent);
|
||||
|
||||
if (!pollStartEvent) {
|
||||
const pollEndFallbackMessage = M_TEXT.findIn(mxEvent.getContent()) || textForEvent(mxEvent);
|
||||
const pollEndFallbackMessage = M_TEXT.findIn(mxEvent.getContent()) || textForEvent(mxEvent, cli);
|
||||
return (
|
||||
<>
|
||||
<PollIcon className="mx_MPollEndBody_icon" />
|
||||
|
|
|
@ -19,6 +19,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
|||
|
||||
import RoomContext from "../../../contexts/RoomContext";
|
||||
import * as TextForEvent from "../../../TextForEvent";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
|
||||
interface IProps {
|
||||
mxEvent: MatrixEvent;
|
||||
|
@ -28,7 +29,12 @@ export default class TextualEvent extends React.Component<IProps> {
|
|||
public static contextType = RoomContext;
|
||||
|
||||
public render(): React.ReactNode {
|
||||
const text = TextForEvent.textForEvent(this.props.mxEvent, true, this.context?.showHiddenEvents);
|
||||
const text = TextForEvent.textForEvent(
|
||||
this.props.mxEvent,
|
||||
MatrixClientPeg.get(),
|
||||
true,
|
||||
this.context?.showHiddenEvents,
|
||||
);
|
||||
if (!text) return null;
|
||||
return <div className="mx_TextualEvent">{text}</div>;
|
||||
}
|
||||
|
|
|
@ -255,7 +255,7 @@ export function pickFactory(
|
|||
return noEventFactoryFactory(); // improper event type to render
|
||||
}
|
||||
|
||||
if (STATE_EVENT_TILE_TYPES.get(evType) === TextualEventFactory && !hasText(mxEvent, showHiddenEvents)) {
|
||||
if (STATE_EVENT_TILE_TYPES.get(evType) === TextualEventFactory && !hasText(mxEvent, cli, showHiddenEvents)) {
|
||||
return noEventFactoryFactory();
|
||||
}
|
||||
|
||||
|
@ -435,7 +435,7 @@ export function haveRendererForEvent(mxEvent: MatrixEvent, showHiddenEvents: boo
|
|||
const handler = pickFactory(mxEvent, cli, showHiddenEvents);
|
||||
if (!handler) return false;
|
||||
if (handler === TextualEventFactory) {
|
||||
return hasText(mxEvent, showHiddenEvents);
|
||||
return hasText(mxEvent, cli, showHiddenEvents);
|
||||
} else if (handler === STATE_EVENT_TILE_TYPES.get(EventType.RoomCreate)) {
|
||||
const dynamicPredecessorsEnabled = SettingsStore.getValue("feature_dynamic_room_predecessors");
|
||||
const predecessor = cli.getRoom(mxEvent.getRoomId())?.findPredecessor(dynamicPredecessorsEnabled);
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
"We couldn't log you in": "We couldn't log you in",
|
||||
"We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.",
|
||||
"Try again": "Try again",
|
||||
"User is not logged in": "User is not logged in",
|
||||
"Database unexpectedly closed": "Database unexpectedly closed",
|
||||
"This may be caused by having the app open in multiple tabs or due to clearing browser data.": "This may be caused by having the app open in multiple tabs or due to clearing browser data.",
|
||||
"Reload": "Reload",
|
||||
|
|
|
@ -402,7 +402,7 @@ export default class HTMLExporter extends Exporter {
|
|||
// TODO: Handle callEvent errors
|
||||
logger.error(e);
|
||||
eventTile = await this.getEventTileMarkup(
|
||||
this.createModifiedEvent(textForEvent(mxEv), mxEv, false),
|
||||
this.createModifiedEvent(textForEvent(mxEv, this.room.client), mxEv, false),
|
||||
joined,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ export default class PlainTextExporter extends Exporter {
|
|||
} else mediaText = ` (${this.mediaOmitText})`;
|
||||
}
|
||||
if (this.isReply(mxEv)) return senderDisplayName + ": " + this.textForReplyEvent(mxEv.getContent()) + mediaText;
|
||||
else return textForEvent(mxEv) + mediaText;
|
||||
else return textForEvent(mxEv, this.room.client) + mediaText;
|
||||
};
|
||||
|
||||
protected async createOutput(events: MatrixEvent[]): Promise<string> {
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React, { ReactNode } from "react";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import AccessibleButton from "../../components/views/elements/AccessibleButton";
|
||||
|
@ -23,7 +23,7 @@ import { highlightEvent } from "../../utils/EventUtils";
|
|||
import { _t } from "../../languageHandler";
|
||||
import { getSenderName } from "../../utils/event/getSenderName";
|
||||
|
||||
export const textForVoiceBroadcastStoppedEvent = (event: MatrixEvent): (() => ReactNode) => {
|
||||
export const textForVoiceBroadcastStoppedEvent = (event: MatrixEvent, client: MatrixClient): (() => ReactNode) => {
|
||||
return (): ReactNode => {
|
||||
const ownUserId = MatrixClientPeg.get()?.getUserId();
|
||||
const startEventId = event.getRelation()?.event_id;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue