From 9b5b05314832ab0d57901b7755819b65835ddced Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 21 Jun 2023 17:29:44 +0100
Subject: [PATCH] Use MatrixClientPeg::safeGet for strict typing (#10989)
---
src/IdentityAuthClient.tsx | 4 +-
src/LegacyCallHandler.tsx | 48 ++++++++++---------
src/Lifecycle.ts | 12 ++---
src/MatrixClientPeg.ts | 4 +-
src/MediaDeviceHandler.ts | 10 ++--
src/Notifier.ts | 35 +++++++-------
src/Presence.ts | 4 +-
src/ScalarAuthClient.ts | 6 +--
src/ScalarMessaging.ts | 6 +--
src/SecurityManager.ts | 10 ++--
src/Unread.ts | 2 +-
src/VoipUserMapper.ts | 21 ++++----
.../security/CreateKeyBackupDialog.tsx | 9 ++--
.../security/CreateSecretStorageDialog.tsx | 27 +++++------
.../security/NewRecoveryMethodDialog.tsx | 4 +-
src/audio/PlaybackQueue.ts | 2 +-
src/autocomplete/NotifProvider.tsx | 4 +-
src/autocomplete/RoomProvider.tsx | 2 +-
src/autocomplete/SpaceProvider.tsx | 2 +-
src/autocomplete/UserProvider.tsx | 14 +++---
src/components/structures/MessagePanel.tsx | 13 +++--
src/components/structures/RoomSearchView.tsx | 2 +-
src/components/structures/TimelinePanel.tsx | 3 +-
.../views/dialogs/ConfirmRedactDialog.tsx | 2 +-
.../ManualDeviceKeyVerificationDialog.tsx | 2 +-
.../views/right_panel/VerificationPanel.tsx | 4 +-
src/components/views/rooms/EventTile.tsx | 2 +-
.../views/rooms/SearchResultTile.tsx | 13 ++++-
.../views/settings/CrossSigningPanel.tsx | 6 +--
.../tabs/user/MjolnirUserSettingsTab.tsx | 8 ++--
.../tabs/user/SecurityUserSettingsTab.tsx | 20 ++++----
.../views/toasts/VerificationRequestToast.tsx | 8 ++--
src/customisations/Media.ts | 2 +-
src/events/EventTileFactory.tsx | 17 ++++---
src/indexing/EventIndex.ts | 20 ++++----
src/integrations/IntegrationManagers.ts | 2 +-
src/linkify-matrix.ts | 2 +-
src/mjolnir/BanList.ts | 6 +--
src/mjolnir/Mjolnir.ts | 7 ++-
src/modules/ProxiedModuleApi.ts | 2 +-
src/sentry.ts | 2 +-
src/settings/SettingsStore.ts | 2 +-
.../controllers/NotificationControllers.ts | 2 +-
src/toasts/DesktopNotificationsToast.ts | 2 +-
src/toasts/IncomingCallToast.tsx | 2 +-
src/toasts/IncomingLegacyCallToast.tsx | 2 +-
src/toasts/UnverifiedSessionToast.tsx | 2 +-
src/utils/EventRenderingUtils.ts | 2 +-
src/utils/exportUtils/HtmlExport.tsx | 5 +-
src/utils/exportUtils/JSONExport.ts | 2 +-
src/utils/exportUtils/PlainTextExport.ts | 2 +-
.../hooks/useVoiceBroadcastPlayback.ts | 2 +-
.../hooks/useVoiceBroadcastRecording.tsx | 2 +-
src/widgets/CapabilityText.tsx | 2 +-
src/widgets/Jitsi.ts | 2 +-
src/widgets/ManagedHybrid.ts | 4 +-
test/Unread-test.ts | 4 +-
.../structures/MessagePanel-test.tsx | 12 +++--
.../security/CreateKeyBackupDialog-test.tsx | 4 +-
.../views/rooms/RoomPreviewBar-test.tsx | 4 +-
60 files changed, 225 insertions(+), 203 deletions(-)
diff --git a/src/IdentityAuthClient.tsx b/src/IdentityAuthClient.tsx
index 28e88a49f7..c27640c6c4 100644
--- a/src/IdentityAuthClient.tsx
+++ b/src/IdentityAuthClient.tsx
@@ -59,7 +59,7 @@ export default class IdentityAuthClient {
}
private get matrixClient(): MatrixClient {
- return this.tempClient ? this.tempClient : MatrixClientPeg.get();
+ return this.tempClient ? this.tempClient : MatrixClientPeg.safeGet();
}
private writeToken(): void {
@@ -176,7 +176,7 @@ export default class IdentityAuthClient {
}
public async registerForToken(check = true): Promise {
- const hsOpenIdToken = await MatrixClientPeg.get().getOpenIdToken();
+ const hsOpenIdToken = await MatrixClientPeg.safeGet().getOpenIdToken();
// XXX: The spec is `token`, but we used `access_token` for a Sydent release.
const { access_token: accessToken, token } = await this.matrixClient.registerWithIdentityServer(hsOpenIdToken);
const identityAccessToken = token ? token : accessToken;
diff --git a/src/LegacyCallHandler.tsx b/src/LegacyCallHandler.tsx
index 08636e5011..1414fc2893 100644
--- a/src/LegacyCallHandler.tsx
+++ b/src/LegacyCallHandler.tsx
@@ -192,7 +192,7 @@ export default class LegacyCallHandler extends EventEmitter {
if (this.shouldObeyAssertedfIdentity()) {
const nativeUser = this.assertedIdentityNativeUsers.get(call.callId);
if (nativeUser) {
- const room = findDMForUser(MatrixClientPeg.get(), nativeUser);
+ const room = findDMForUser(MatrixClientPeg.safeGet(), nativeUser);
if (room) return room.roomId;
}
}
@@ -214,7 +214,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
if (SettingsStore.getValue(UIFeature.Voip)) {
- MatrixClientPeg.get().on(CallEventHandlerEvent.Incoming, this.onCallIncoming);
+ MatrixClientPeg.safeGet().on(CallEventHandlerEvent.Incoming, this.onCallIncoming);
}
this.checkProtocols(CHECK_PROTOCOLS_ATTEMPTS);
@@ -271,7 +271,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
public isForcedSilent(): boolean {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
return localNotificationsAreSilenced(cli);
}
@@ -311,7 +311,7 @@ export default class LegacyCallHandler extends EventEmitter {
private async checkProtocols(maxTries: number): Promise {
try {
- const protocols = await MatrixClientPeg.get().getThirdpartyProtocols();
+ const protocols = await MatrixClientPeg.safeGet().getThirdpartyProtocols();
if (protocols[PROTOCOL_PSTN] !== undefined) {
this.supportsPstnProtocol = Boolean(protocols[PROTOCOL_PSTN]);
@@ -358,7 +358,7 @@ export default class LegacyCallHandler extends EventEmitter {
public async pstnLookup(phoneNumber: string): Promise {
try {
- return await MatrixClientPeg.get().getThirdpartyUser(
+ return await MatrixClientPeg.safeGet().getThirdpartyUser(
this.pstnSupportPrefixed ? PROTOCOL_PSTN_PREFIXED : PROTOCOL_PSTN,
{
"m.id.phone": phoneNumber,
@@ -372,7 +372,7 @@ export default class LegacyCallHandler extends EventEmitter {
public async sipVirtualLookup(nativeMxid: string): Promise {
try {
- return await MatrixClientPeg.get().getThirdpartyUser(PROTOCOL_SIP_VIRTUAL, {
+ return await MatrixClientPeg.safeGet().getThirdpartyUser(PROTOCOL_SIP_VIRTUAL, {
native_mxid: nativeMxid,
});
} catch (e) {
@@ -383,7 +383,7 @@ export default class LegacyCallHandler extends EventEmitter {
public async sipNativeLookup(virtualMxid: string): Promise {
try {
- return await MatrixClientPeg.get().getThirdpartyUser(PROTOCOL_SIP_NATIVE, {
+ return await MatrixClientPeg.safeGet().getThirdpartyUser(PROTOCOL_SIP_NATIVE, {
virtual_mxid: virtualMxid,
});
} catch (e) {
@@ -394,7 +394,7 @@ export default class LegacyCallHandler extends EventEmitter {
private onCallIncoming = (call: MatrixCall): void => {
// if the runtime env doesn't do VoIP, stop here.
- if (!MatrixClientPeg.get().supportsVoip()) {
+ if (!MatrixClientPeg.get()?.supportsVoip()) {
return;
}
@@ -415,7 +415,7 @@ export default class LegacyCallHandler extends EventEmitter {
// get ready to send encrypted events in the room, so if the user does answer
// the call, we'll be ready to send. NB. This is the protocol-level room ID not
// the mapped one: that's where we'll send the events.
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
const room = cli.getRoom(call.roomId);
if (room) cli.prepareToEncrypt(room);
};
@@ -463,7 +463,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
public getAllActiveCallsForPip(roomId: string): MatrixCall[] {
- const room = MatrixClientPeg.get().getRoom(roomId);
+ const room = MatrixClientPeg.safeGet().getRoom(roomId);
if (room && WidgetLayoutStore.instance.hasMaximisedWidget(room)) {
// This checks if there is space for the call view in the aux panel
// If there is no space any call should be displayed in PiP
@@ -570,7 +570,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
if (
- MatrixClientPeg.get().getTurnServers().length === 0 &&
+ MatrixClientPeg.safeGet().getTurnServers().length === 0 &&
SettingsStore.getValue("fallbackICEServerAllowed") === null
) {
this.showICEFallbackPrompt();
@@ -638,7 +638,7 @@ export default class LegacyCallHandler extends EventEmitter {
// this if we want the actual, native room to exist (which we do). This is why it's
// important to only obey asserted identity in trusted environments, since anyone you're
// on a call with can cause you to send a room invite to someone.
- await ensureDMExists(MatrixClientPeg.get(), newNativeAssertedIdentity);
+ await ensureDMExists(MatrixClientPeg.safeGet(), newNativeAssertedIdentity);
const newMappedRoomId = this.roomIdForCall(call);
logger.log(`Old room ID: ${mappedRoomId}, new room ID: ${newMappedRoomId}`);
@@ -678,7 +678,7 @@ export default class LegacyCallHandler extends EventEmitter {
switch (newState) {
case CallState.Ringing: {
- const incomingCallPushRule = new PushProcessor(MatrixClientPeg.get()).getPushRuleById(
+ const incomingCallPushRule = new PushProcessor(MatrixClientPeg.safeGet()).getPushRuleById(
RuleId.IncomingCall,
);
const pushRuleEnabled = incomingCallPushRule?.enabled;
@@ -825,7 +825,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
private showICEFallbackPrompt(): void {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
Modal.createDialog(
QuestionDialog,
{
@@ -907,6 +907,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
private async placeMatrixCall(roomId: string, type: CallType, transferee?: MatrixCall): Promise {
+ const cli = MatrixClientPeg.safeGet();
const mappedRoomId = (await VoipUserMapper.sharedInstance().getOrCreateVirtualRoomForRoom(roomId)) || roomId;
logger.debug("Mapped real room " + roomId + " to room ID " + mappedRoomId);
@@ -916,15 +917,15 @@ export default class LegacyCallHandler extends EventEmitter {
// in this queue, and since we're about to place a new call, they can only be events from
// previous calls that are probably stale by now, so just cancel them.
if (mappedRoomId !== roomId) {
- const mappedRoom = MatrixClientPeg.get().getRoom(mappedRoomId);
+ const mappedRoom = cli.getRoom(mappedRoomId);
if (mappedRoom?.getPendingEvents().length) {
Resend.cancelUnsentEvents(mappedRoom);
}
}
- const timeUntilTurnCresExpire = MatrixClientPeg.get().getTurnServersExpiry() - Date.now();
+ const timeUntilTurnCresExpire = cli.getTurnServersExpiry() - Date.now();
logger.log("Current turn creds expire in " + timeUntilTurnCresExpire + " ms");
- const call = MatrixClientPeg.get().createCall(mappedRoomId)!;
+ const call = cli.createCall(mappedRoomId)!;
try {
this.addCallForRoom(roomId, call);
@@ -953,6 +954,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
public async placeCall(roomId: string, type: CallType, transferee?: MatrixCall): Promise {
+ const cli = MatrixClientPeg.safeGet();
// Pause current broadcast, if any
SdkContextClass.instance.voiceBroadcastPlaybacksStore.getCurrent()?.pause();
@@ -969,7 +971,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
// if the runtime env doesn't do VoIP, whine.
- if (!MatrixClientPeg.get().supportsVoip()) {
+ if (!cli.supportsVoip()) {
Modal.createDialog(ErrorDialog, {
title: _t("Calls are unsupported"),
description: _t("You cannot place calls in this browser."),
@@ -977,7 +979,7 @@ export default class LegacyCallHandler extends EventEmitter {
return;
}
- if (MatrixClientPeg.get().getSyncState() === SyncState.Error) {
+ if (cli.getSyncState() === SyncState.Error) {
Modal.createDialog(ErrorDialog, {
title: _t("Connectivity to the server has been lost"),
description: _t("You cannot place calls without a connection to the server."),
@@ -994,7 +996,7 @@ export default class LegacyCallHandler extends EventEmitter {
return;
}
- const room = MatrixClientPeg.get().getRoom(roomId);
+ const room = cli.getRoom(roomId);
if (!room) {
logger.error(`Room ${roomId} does not exist.`);
return;
@@ -1095,7 +1097,7 @@ export default class LegacyCallHandler extends EventEmitter {
nativeUserId = userId;
}
- const roomId = await ensureDMExists(MatrixClientPeg.get(), nativeUserId);
+ const roomId = await ensureDMExists(MatrixClientPeg.safeGet(), nativeUserId);
if (!roomId) {
throw new Error("Failed to ensure DM exists for dialing number");
}
@@ -1135,7 +1137,7 @@ export default class LegacyCallHandler extends EventEmitter {
public async startTransferToMatrixID(call: MatrixCall, destination: string, consultFirst: boolean): Promise {
if (consultFirst) {
- const dmRoomId = await ensureDMExists(MatrixClientPeg.get(), destination);
+ const dmRoomId = await ensureDMExists(MatrixClientPeg.safeGet(), destination);
if (!dmRoomId) {
logger.log("Failed to transfer call, could not ensure dm exists");
Modal.createDialog(ErrorDialog, {
@@ -1194,7 +1196,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
private async placeJitsiCall(roomId: string, type: CallType): Promise {
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
logger.info(`Place conference call in ${roomId}`);
dis.dispatch({ action: "appsDrawer", show: true });
diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts
index 6f49a0a0b6..a1d00d86ad 100644
--- a/src/Lifecycle.ts
+++ b/src/Lifecycle.ts
@@ -278,7 +278,7 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise | v
}
})
.then(() => {
- return MatrixClientPeg.get().store.deleteAllData();
+ return MatrixClientPeg.safeGet().store.deleteAllData();
})
.then(() => {
PlatformPeg.get()?.reload();
@@ -541,8 +541,8 @@ export async function setLoggedIn(credentials: IMatrixClientCreds): Promise {
- const oldUserId = MatrixClientPeg.get().getUserId();
- const oldDeviceId = MatrixClientPeg.get().getDeviceId();
+ const oldUserId = MatrixClientPeg.safeGet().getUserId();
+ const oldDeviceId = MatrixClientPeg.safeGet().getDeviceId();
stopMatrixClient(); // unsets MatrixClientPeg.get()
localStorage.removeItem("mx_soft_logout");
@@ -603,7 +603,7 @@ async function doSetLoggedIn(credentials: IMatrixClientCreds, clearStorageEnable
}
MatrixClientPeg.replaceUsingCreds(credentials);
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
setSentryUser(credentials.userId);
@@ -724,7 +724,7 @@ export function logout(): void {
PosthogAnalytics.instance.logout();
- if (MatrixClientPeg.get().isGuest()) {
+ if (MatrixClientPeg.get()!.isGuest()) {
// logout doesn't work for guest sessions
// Also we sometimes want to re-log in a guest session if we abort the login.
// defer until next tick because it calls a synchronous dispatch, and we are likely here from a dispatch.
@@ -733,7 +733,7 @@ export function logout(): void {
}
_isLoggingOut = true;
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.get()!;
PlatformPeg.get()?.destroyPickleKey(client.getSafeUserId(), client.getDeviceId() ?? "");
client.logout(true).then(onLoggedOut, (err) => {
// Just throwing an error here is going to be very unhelpful
diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts
index 979f679f46..fabed4f61c 100644
--- a/src/MatrixClientPeg.ts
+++ b/src/MatrixClientPeg.ts
@@ -73,7 +73,7 @@ export interface IMatrixClientPeg {
*/
getHomeserverName(): string | null;
- get(): MatrixClient;
+ get(): MatrixClient | null;
safeGet(): MatrixClient;
unset(): void;
assign(): Promise;
@@ -142,7 +142,7 @@ class MatrixClientPegClass implements IMatrixClientPeg {
// used if we tear it down & recreate it with a different store
private currentClientCreds: IMatrixClientCreds | null = null;
- public get(): MatrixClient {
+ public get(): MatrixClient | null {
return this.matrixClient;
}
diff --git a/src/MediaDeviceHandler.ts b/src/MediaDeviceHandler.ts
index 7e66fbc3df..f194b5e204 100644
--- a/src/MediaDeviceHandler.ts
+++ b/src/MediaDeviceHandler.ts
@@ -99,14 +99,14 @@ export default class MediaDeviceHandler extends EventEmitter {
const audioDeviceId = SettingsStore.getValue("webrtc_audioinput");
const videoDeviceId = SettingsStore.getValue("webrtc_videoinput");
- await MatrixClientPeg.get().getMediaHandler().setAudioInput(audioDeviceId);
- await MatrixClientPeg.get().getMediaHandler().setVideoInput(videoDeviceId);
+ await MatrixClientPeg.safeGet().getMediaHandler().setAudioInput(audioDeviceId);
+ await MatrixClientPeg.safeGet().getMediaHandler().setVideoInput(videoDeviceId);
await MediaDeviceHandler.updateAudioSettings();
}
private static async updateAudioSettings(): Promise {
- await MatrixClientPeg.get().getMediaHandler().setAudioSettings({
+ await MatrixClientPeg.safeGet().getMediaHandler().setAudioSettings({
autoGainControl: MediaDeviceHandler.getAudioAutoGainControl(),
echoCancellation: MediaDeviceHandler.getAudioEchoCancellation(),
noiseSuppression: MediaDeviceHandler.getAudioNoiseSuppression(),
@@ -125,7 +125,7 @@ export default class MediaDeviceHandler extends EventEmitter {
*/
public async setAudioInput(deviceId: string): Promise {
SettingsStore.setValue("webrtc_audioinput", null, SettingLevel.DEVICE, deviceId);
- return MatrixClientPeg.get().getMediaHandler().setAudioInput(deviceId);
+ return MatrixClientPeg.safeGet().getMediaHandler().setAudioInput(deviceId);
}
/**
@@ -135,7 +135,7 @@ export default class MediaDeviceHandler extends EventEmitter {
*/
public async setVideoInput(deviceId: string): Promise {
SettingsStore.setValue("webrtc_videoinput", null, SettingLevel.DEVICE, deviceId);
- return MatrixClientPeg.get().getMediaHandler().setVideoInput(deviceId);
+ return MatrixClientPeg.safeGet().getMediaHandler().setVideoInput(deviceId);
}
public async setDevice(deviceId: string, kind: MediaDeviceKindEnum): Promise {
diff --git a/src/Notifier.ts b/src/Notifier.ts
index 4a36338729..fed04dd68d 100644
--- a/src/Notifier.ts
+++ b/src/Notifier.ts
@@ -91,7 +91,7 @@ const msgTypeHandlers: Record string | null> = {
return null;
}
- return TextForEvent.textForEvent(event, MatrixClientPeg.get());
+ return TextForEvent.textForEvent(event, MatrixClientPeg.safeGet());
},
};
@@ -111,13 +111,13 @@ class NotifierClass {
if (msgType && msgTypeHandlers.hasOwnProperty(msgType)) {
return msgTypeHandlers[msgType](ev);
}
- return TextForEvent.textForEvent(ev, MatrixClientPeg.get());
+ return TextForEvent.textForEvent(ev, MatrixClientPeg.safeGet());
}
// XXX: exported for tests
public displayPopupNotification(ev: MatrixEvent, room: Room): void {
const plaf = PlatformPeg.get();
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
if (!plaf) {
return;
}
@@ -215,7 +215,7 @@ class NotifierClass {
// XXX: Exported for tests
public async playAudioNotification(ev: MatrixEvent, room: Room): Promise {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
if (localNotificationsAreSilenced(cli)) {
return;
}
@@ -246,20 +246,21 @@ class NotifierClass {
}
public start(): void {
- MatrixClientPeg.get().on(RoomEvent.Timeline, this.onEvent);
- MatrixClientPeg.get().on(RoomEvent.Receipt, this.onRoomReceipt);
- MatrixClientPeg.get().on(MatrixEventEvent.Decrypted, this.onEventDecrypted);
- MatrixClientPeg.get().on(ClientEvent.Sync, this.onSyncStateChange);
+ const cli = MatrixClientPeg.safeGet();
+ cli.on(RoomEvent.Timeline, this.onEvent);
+ cli.on(RoomEvent.Receipt, this.onRoomReceipt);
+ cli.on(MatrixEventEvent.Decrypted, this.onEventDecrypted);
+ cli.on(ClientEvent.Sync, this.onSyncStateChange);
this.toolbarHidden = false;
this.isSyncing = false;
}
public stop(): void {
if (MatrixClientPeg.get()) {
- MatrixClientPeg.get().removeListener(RoomEvent.Timeline, this.onEvent);
- MatrixClientPeg.get().removeListener(RoomEvent.Receipt, this.onRoomReceipt);
- MatrixClientPeg.get().removeListener(MatrixEventEvent.Decrypted, this.onEventDecrypted);
- MatrixClientPeg.get().removeListener(ClientEvent.Sync, this.onSyncStateChange);
+ MatrixClientPeg.get()!.removeListener(RoomEvent.Timeline, this.onEvent);
+ MatrixClientPeg.get()!.removeListener(RoomEvent.Receipt, this.onRoomReceipt);
+ MatrixClientPeg.get()!.removeListener(MatrixEventEvent.Decrypted, this.onEventDecrypted);
+ MatrixClientPeg.get()!.removeListener(ClientEvent.Sync, this.onSyncStateChange);
}
this.isSyncing = false;
}
@@ -400,7 +401,7 @@ class NotifierClass {
// wait for first non-cached sync to complete
if (![SyncState.Stopped, SyncState.Error].includes(state) && !data?.fromCache) {
- createLocalNotificationSettingsIfNeeded(MatrixClientPeg.get());
+ createLocalNotificationSettingsIfNeeded(MatrixClientPeg.safeGet());
}
};
@@ -413,9 +414,9 @@ class NotifierClass {
): void => {
if (!data.liveEvent) return; // only notify for new things, not old.
if (!this.isSyncing) return; // don't alert for any messages initially
- if (ev.getSender() === MatrixClientPeg.get().getUserId()) return;
+ if (ev.getSender() === MatrixClientPeg.safeGet().getUserId()) return;
- MatrixClientPeg.get().decryptEventIfNeeded(ev);
+ MatrixClientPeg.safeGet().decryptEventIfNeeded(ev);
// If it's an encrypted event and the type is still 'm.room.encrypted',
// it hasn't yet been decrypted, so wait until it is.
@@ -473,14 +474,14 @@ class NotifierClass {
roomId = nativeRoomId;
}
}
- const room = MatrixClientPeg.get().getRoom(roomId);
+ const room = MatrixClientPeg.safeGet().getRoom(roomId);
if (!room) {
// e.g we are in the process of joining a room.
// Seen in the cypress lazy-loading test.
return;
}
- const actions = MatrixClientPeg.get().getPushActionsForEvent(ev);
+ const actions = MatrixClientPeg.safeGet().getPushActionsForEvent(ev);
if (actions?.notify) {
this.performCustomEventHandling(ev);
diff --git a/src/Presence.ts b/src/Presence.ts
index 02d2ef0e7e..a8ba8b40c4 100644
--- a/src/Presence.ts
+++ b/src/Presence.ts
@@ -97,12 +97,12 @@ class Presence {
const oldState = this.state;
this.state = newState;
- if (MatrixClientPeg.get().isGuest()) {
+ if (MatrixClientPeg.safeGet().isGuest()) {
return; // don't try to set presence when a guest; it won't work.
}
try {
- await MatrixClientPeg.get().setPresence({ presence: this.state });
+ await MatrixClientPeg.safeGet().setPresence({ presence: this.state });
logger.info("Presence:", newState);
} catch (err) {
logger.error("Failed to set presence:", err);
diff --git a/src/ScalarAuthClient.ts b/src/ScalarAuthClient.ts
index ca181ebb8f..07dc478876 100644
--- a/src/ScalarAuthClient.ts
+++ b/src/ScalarAuthClient.ts
@@ -131,7 +131,7 @@ export default class ScalarAuthClient {
private checkToken(token: string): Promise {
return this.getAccountName(token)
.then((userId) => {
- const me = MatrixClientPeg.get().getUserId();
+ const me = MatrixClientPeg.safeGet().getUserId();
if (userId !== me) {
throw new Error("Scalar token is owned by someone else: " + me);
}
@@ -157,7 +157,7 @@ export default class ScalarAuthClient {
const parsedImRestUrl = parseUrl(this.apiUrl);
parsedImRestUrl.pathname = "";
return startTermsFlow(
- MatrixClientPeg.get(),
+ MatrixClientPeg.safeGet(),
[new Service(SERVICE_TYPES.IM, parsedImRestUrl.toString(), token)],
this.termsInteractionCallback,
).then(() => {
@@ -171,7 +171,7 @@ export default class ScalarAuthClient {
public registerForToken(): Promise {
// Get openid bearer token from the HS as the first part of our dance
- return MatrixClientPeg.get()
+ return MatrixClientPeg.safeGet()
.getOpenIdToken()
.then((tokenObject) => {
// Now we can send that to scalar and exchange it for a scalar token
diff --git a/src/ScalarMessaging.ts b/src/ScalarMessaging.ts
index fa0849bf30..b3a0c5640b 100644
--- a/src/ScalarMessaging.ts
+++ b/src/ScalarMessaging.ts
@@ -411,7 +411,7 @@ function kickUser(event: MessageEvent, roomId: string, userId: string): voi
}
function setWidget(event: MessageEvent, roomId: string | null): void {
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
const widgetId = event.data.widget_id;
let widgetType = event.data.type;
const widgetUrl = event.data.url;
@@ -535,7 +535,7 @@ function getRoomEncState(event: MessageEvent, roomId: string): void {
sendError(event, _t("This room is not recognised."));
return;
}
- const roomIsEncrypted = MatrixClientPeg.get().isRoomEncrypted(roomId);
+ const roomIsEncrypted = MatrixClientPeg.safeGet().isRoomEncrypted(roomId);
sendResponse(event, roomIsEncrypted);
}
@@ -715,7 +715,7 @@ function returnStateEvent(event: MessageEvent, roomId: string, eventType: s
async function getOpenIdToken(event: MessageEvent): Promise {
try {
- const tokenObject = await MatrixClientPeg.get().getOpenIdToken();
+ const tokenObject = await MatrixClientPeg.safeGet().getOpenIdToken();
sendResponse(event, tokenObject);
} catch (ex) {
logger.warn("Unable to fetch openId token.", ex);
diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts
index c1a59bce74..52c5a8f852 100644
--- a/src/SecurityManager.ts
+++ b/src/SecurityManager.ts
@@ -99,7 +99,7 @@ async function getSecretStorageKey({
}: {
keys: Record;
}): Promise<[string, Uint8Array]> {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
let keyId = await cli.getDefaultSecretStorageKeyId();
let keyInfo!: ISecretStorageKeyInfo;
if (keyId) {
@@ -127,7 +127,7 @@ async function getSecretStorageKey({
}
if (dehydrationCache.key) {
- if (await MatrixClientPeg.get().checkSecretStorageKey(dehydrationCache.key, keyInfo)) {
+ if (await MatrixClientPeg.safeGet().checkSecretStorageKey(dehydrationCache.key, keyInfo)) {
cacheSecretStorageKey(keyId, keyInfo, dehydrationCache.key);
return [keyId, dehydrationCache.key];
}
@@ -152,7 +152,7 @@ async function getSecretStorageKey({
keyInfo,
checkPrivateKey: async (input: KeyParams): Promise => {
const key = await inputToKey(input);
- return MatrixClientPeg.get().checkSecretStorageKey(key, keyInfo);
+ return MatrixClientPeg.safeGet().checkSecretStorageKey(key, keyInfo);
},
},
/* className= */ undefined,
@@ -244,7 +244,7 @@ async function onSecretRequested(
deviceTrust: DeviceTrustLevel,
): Promise {
logger.log("onSecretRequested", userId, deviceId, requestId, name, deviceTrust);
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
if (userId !== client.getUserId()) {
return;
}
@@ -324,9 +324,9 @@ export async function promptForBackupPassphrase(): Promise {
* @param {bool} [forceReset] Reset secret storage even if it's already set up
*/
export async function accessSecretStorage(func = async (): Promise => {}, forceReset = false): Promise {
- const cli = MatrixClientPeg.get();
secretStorageBeingAccessed = true;
try {
+ const cli = MatrixClientPeg.safeGet();
if (!(await cli.hasSecretStorageKey()) || forceReset) {
// This dialog calls bootstrap itself after guiding the user through
// passphrase creation.
diff --git a/src/Unread.ts b/src/Unread.ts
index 3b1826b3a6..03a816c680 100644
--- a/src/Unread.ts
+++ b/src/Unread.ts
@@ -52,7 +52,7 @@ export function eventTriggersUnreadCount(client: MatrixClient, ev: MatrixEvent):
}
if (ev.isRedacted()) return false;
- return haveRendererForEvent(ev, false /* hidden messages should never trigger unread counts anyways */);
+ return haveRendererForEvent(ev, client, false /* hidden messages should never trigger unread counts anyways */);
}
export function doesRoomHaveUnreadMessages(room: Room): boolean {
diff --git a/src/VoipUserMapper.ts b/src/VoipUserMapper.ts
index 0214ab9cbe..d1f5b5817c 100644
--- a/src/VoipUserMapper.ts
+++ b/src/VoipUserMapper.ts
@@ -58,8 +58,9 @@ export default class VoipUserMapper {
const virtualUser = await this.getVirtualUserForRoom(roomId);
if (!virtualUser) return null;
- const virtualRoomId = await ensureVirtualRoomExists(MatrixClientPeg.get(), virtualUser, roomId);
- MatrixClientPeg.get().setRoomAccountData(virtualRoomId!, VIRTUAL_ROOM_EVENT_TYPE, {
+ const cli = MatrixClientPeg.safeGet();
+ const virtualRoomId = await ensureVirtualRoomExists(cli, virtualUser, roomId);
+ cli.setRoomAccountData(virtualRoomId!, VIRTUAL_ROOM_EVENT_TYPE, {
native_room: roomId,
});
@@ -76,7 +77,7 @@ export default class VoipUserMapper {
const virtualUser = await this.getVirtualUserForRoom(roomId);
if (!virtualUser) return undefined;
- return findDMForUser(MatrixClientPeg.get(), virtualUser);
+ return findDMForUser(MatrixClientPeg.safeGet(), virtualUser);
}
public nativeRoomForVirtualRoom(roomId: string): string | null {
@@ -88,12 +89,13 @@ export default class VoipUserMapper {
return cachedNativeRoomId;
}
- const virtualRoom = MatrixClientPeg.get().getRoom(roomId);
+ const cli = MatrixClientPeg.safeGet();
+ const virtualRoom = cli.getRoom(roomId);
if (!virtualRoom) return null;
const virtualRoomEvent = virtualRoom.getAccountData(VIRTUAL_ROOM_EVENT_TYPE);
if (!virtualRoomEvent || !virtualRoomEvent.getContent()) return null;
const nativeRoomID = virtualRoomEvent.getContent()["native_room"];
- const nativeRoom = MatrixClientPeg.get().getRoom(nativeRoomID);
+ const nativeRoom = cli.getRoom(nativeRoomID);
if (!nativeRoom || nativeRoom.getMyMembership() !== "join") return null;
return nativeRoomID;
@@ -112,7 +114,7 @@ export default class VoipUserMapper {
if (!roomCreateEvent || !roomCreateEvent.getContent()) return false;
// we only look at this for rooms we created (so inviters can't just cause rooms
// to be invisible)
- if (roomCreateEvent.getSender() !== MatrixClientPeg.get().getUserId()) return false;
+ if (roomCreateEvent.getSender() !== MatrixClientPeg.safeGet().getUserId()) return false;
const claimedNativeRoomId = roomCreateEvent.getContent()[VIRTUAL_ROOM_EVENT_TYPE];
return Boolean(claimedNativeRoomId);
}
@@ -132,19 +134,20 @@ export default class VoipUserMapper {
}
if (result[0].fields.is_virtual) {
+ const cli = MatrixClientPeg.safeGet();
const nativeUser = result[0].userid;
- const nativeRoom = findDMForUser(MatrixClientPeg.get(), nativeUser);
+ const nativeRoom = findDMForUser(cli, nativeUser);
if (nativeRoom) {
// It's a virtual room with a matching native room, so set the room account data. This
// will make sure we know where how to map calls and also allow us know not to display
// it in the future.
- MatrixClientPeg.get().setRoomAccountData(invitedRoom.roomId, VIRTUAL_ROOM_EVENT_TYPE, {
+ cli.setRoomAccountData(invitedRoom.roomId, VIRTUAL_ROOM_EVENT_TYPE, {
native_room: nativeRoom.roomId,
});
// also auto-join the virtual room if we have a matching native room
// (possibly we should only join if we've also joined the native room, then we'd also have
// to make sure we joined virtual rooms on joining a native one)
- MatrixClientPeg.get().joinRoom(invitedRoom.roomId);
+ cli.joinRoom(invitedRoom.roomId);
// also put this room in the virtual room ID cache so isVirtualRoom return the right answer
// in however long it takes for the echo of setAccountData to come down the sync
diff --git a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx
index 822e9fd46b..d07c86daa1 100644
--- a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx
+++ b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx
@@ -72,14 +72,15 @@ export default class CreateKeyBackupDialog extends React.PureComponent => {
- info = await MatrixClientPeg.get().prepareKeyBackupVersion(null /* random key */, {
+ info = await cli.prepareKeyBackupVersion(null /* random key */, {
secureSecretStorage: true,
});
- info = await MatrixClientPeg.get().createKeyBackupVersion(info);
+ info = await cli.createKeyBackupVersion(info);
});
- await MatrixClientPeg.get().scheduleAllGroupSessionsForBackup();
+ await cli.scheduleAllGroupSessionsForBackup();
this.setState({
phase: Phase.Done,
});
@@ -90,7 +91,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
try {
- const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
+ const cli = MatrixClientPeg.safeGet();
+ const backupInfo = await cli.getKeyBackupVersion();
const backupSigStatus =
// we may not have started crypto yet, in which case we definitely don't trust the backup
- backupInfo && MatrixClientPeg.get().isCryptoEnabled()
- ? await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo)
- : null;
+ backupInfo && cli.isCryptoEnabled() ? await cli.isKeyBackupTrusted(backupInfo) : null;
const { forceReset } = this.props;
const phase = backupInfo && !forceReset ? Phase.Migrate : Phase.ChooseKeyPassphrase;
@@ -204,7 +203,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
try {
- await MatrixClientPeg.get().uploadDeviceSigningKeys(undefined, {} as CrossSigningKeys);
+ await MatrixClientPeg.safeGet().uploadDeviceSigningKeys(undefined, {} as CrossSigningKeys);
// We should never get here: the server should always require
// UI auth to upload device signing keys. If we do, we upload
// no keys which would be a no-op.
@@ -235,7 +234,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent => {
if (this.state.passPhraseKeySelected === SecureBackupSetupMethod.Key) {
- this.recoveryKey = await MatrixClientPeg.get().createRecoveryKeyFromPassphrase();
+ this.recoveryKey = await MatrixClientPeg.safeGet().createRecoveryKeyFromPassphrase();
this.setState({
copied: false,
downloaded: false,
@@ -286,11 +285,11 @@ export default class CreateSecretStorageDialog extends React.PureComponent
);
- let content;
- if (MatrixClientPeg.get().getKeyBackupEnabled()) {
+ let content: JSX.Element | undefined;
+ if (MatrixClientPeg.safeGet().getKeyBackupEnabled()) {
content = (
{newMethodDetected}
diff --git a/src/audio/PlaybackQueue.ts b/src/audio/PlaybackQueue.ts
index 6ae899704b..c9b61cc2f6 100644
--- a/src/audio/PlaybackQueue.ts
+++ b/src/audio/PlaybackQueue.ts
@@ -64,7 +64,7 @@ export class PlaybackQueue {
}
public static forRoom(roomId: string): PlaybackQueue {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
const room = cli.getRoom(roomId);
if (!room) throw new Error("Unknown room");
if (PlaybackQueue.queues.has(room.roomId)) {
diff --git a/src/autocomplete/NotifProvider.tsx b/src/autocomplete/NotifProvider.tsx
index d4a4793ab5..51373a7403 100644
--- a/src/autocomplete/NotifProvider.tsx
+++ b/src/autocomplete/NotifProvider.tsx
@@ -38,9 +38,9 @@ export default class NotifProvider extends AutocompleteProvider {
force = false,
limit = -1,
): Promise
{
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
- if (!this.room.currentState.mayTriggerNotifOfType("room", client.credentials.userId!)) return [];
+ if (!this.room.currentState.mayTriggerNotifOfType("room", client.getSafeUserId())) return [];
const { command, range } = this.getCurrentCommand(query, selection, force);
if (
diff --git a/src/autocomplete/RoomProvider.tsx b/src/autocomplete/RoomProvider.tsx
index 48f1582be0..a28777e65d 100644
--- a/src/autocomplete/RoomProvider.tsx
+++ b/src/autocomplete/RoomProvider.tsx
@@ -65,7 +65,7 @@ export default class RoomProvider extends AutocompleteProvider {
}
protected getRooms(): Room[] {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
// filter out spaces here as they get their own autocomplete provider
return cli
diff --git a/src/autocomplete/SpaceProvider.tsx b/src/autocomplete/SpaceProvider.tsx
index 3f6bd30e3e..4c6b8a3259 100644
--- a/src/autocomplete/SpaceProvider.tsx
+++ b/src/autocomplete/SpaceProvider.tsx
@@ -24,7 +24,7 @@ import RoomProvider from "./RoomProvider";
export default class SpaceProvider extends RoomProvider {
protected getRooms(): Room[] {
- return MatrixClientPeg.get()
+ return MatrixClientPeg.safeGet()
.getVisibleRooms(SettingsStore.getValue("feature_dynamic_room_predecessors"))
.filter((r) => r.isSpaceRoom());
}
diff --git a/src/autocomplete/UserProvider.tsx b/src/autocomplete/UserProvider.tsx
index 3d4c542c48..51a9806408 100644
--- a/src/autocomplete/UserProvider.tsx
+++ b/src/autocomplete/UserProvider.tsx
@@ -60,15 +60,13 @@ export default class UserProvider extends AutocompleteProvider {
shouldMatchWordsOnly: false,
});
- MatrixClientPeg.get().on(RoomEvent.Timeline, this.onRoomTimeline);
- MatrixClientPeg.get().on(RoomStateEvent.Update, this.onRoomStateUpdate);
+ MatrixClientPeg.safeGet().on(RoomEvent.Timeline, this.onRoomTimeline);
+ MatrixClientPeg.safeGet().on(RoomStateEvent.Update, this.onRoomStateUpdate);
}
public destroy(): void {
- if (MatrixClientPeg.get()) {
- MatrixClientPeg.get().removeListener(RoomEvent.Timeline, this.onRoomTimeline);
- MatrixClientPeg.get().removeListener(RoomStateEvent.Update, this.onRoomStateUpdate);
- }
+ MatrixClientPeg.get()?.removeListener(RoomEvent.Timeline, this.onRoomTimeline);
+ MatrixClientPeg.get()?.removeListener(RoomStateEvent.Update, this.onRoomStateUpdate);
}
private onRoomTimeline = (
@@ -155,7 +153,7 @@ export default class UserProvider extends AutocompleteProvider {
lastSpoken[event.getSender()!] = event.getTs();
}
- const currentUserId = MatrixClientPeg.get().credentials.userId;
+ const currentUserId = MatrixClientPeg.safeGet().credentials.userId;
this.users = this.room.getJoinedMembers().filter(({ userId }) => userId !== currentUserId);
this.users = this.users.concat(this.room.getMembersWithMembership("invite"));
@@ -167,7 +165,7 @@ export default class UserProvider extends AutocompleteProvider {
public onUserSpoke(user: RoomMember | null): void {
if (!this.users) return;
if (!user) return;
- if (user.userId === MatrixClientPeg.get().credentials.userId) return;
+ if (user.userId === MatrixClientPeg.safeGet().getSafeUserId()) return;
// Move the user that spoke to the front of the array
this.users.splice(
diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx
index 687ab1f56a..479e6d6aa9 100644
--- a/src/components/structures/MessagePanel.tsx
+++ b/src/components/structures/MessagePanel.tsx
@@ -25,6 +25,7 @@ import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
import { M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon";
import { isSupportedReceiptType } from "matrix-js-sdk/src/utils";
import { Optional } from "matrix-events-sdk";
+import { MatrixClient } from "matrix-js-sdk/src/matrix";
import shouldHideEvent from "../../shouldHideEvent";
import { wantsDateSeparator } from "../../DateUtils";
@@ -73,6 +74,7 @@ const groupedStateEvents = [
export function shouldFormContinuation(
prevEvent: MatrixEvent | null,
mxEvent: MatrixEvent,
+ matrixClient: MatrixClient,
showHiddenEvents: boolean,
timelineRenderingType?: TimelineRenderingType,
): boolean {
@@ -110,7 +112,7 @@ export function shouldFormContinuation(
}
// if we don't have tile for previous event then it was shown by showHiddenEvents and has no SenderProfile
- if (!haveRendererForEvent(prevEvent, showHiddenEvents)) return false;
+ if (!haveRendererForEvent(prevEvent, matrixClient, showHiddenEvents)) return false;
return true;
}
@@ -481,7 +483,7 @@ export default class MessagePanel extends React.Component {
return true;
}
- if (!haveRendererForEvent(mxEv, this.showHiddenEvents)) {
+ if (!haveRendererForEvent(mxEv, MatrixClientPeg.safeGet(), this.showHiddenEvents)) {
return false; // no tile = no show
}
@@ -736,6 +738,7 @@ export default class MessagePanel extends React.Component {
ret.push(dateSeparator);
}
+ const cli = MatrixClientPeg.safeGet();
let lastInSection = true;
if (nextEventWithTile) {
const nextEv = nextEventWithTile;
@@ -743,14 +746,14 @@ export default class MessagePanel extends React.Component {
lastInSection =
willWantDateSeparator ||
mxEv.getSender() !== nextEv.getSender() ||
- getEventDisplayInfo(MatrixClientPeg.safeGet(), nextEv, this.showHiddenEvents).isInfoMessage ||
- !shouldFormContinuation(mxEv, nextEv, this.showHiddenEvents, this.context.timelineRenderingType);
+ getEventDisplayInfo(cli, nextEv, this.showHiddenEvents).isInfoMessage ||
+ !shouldFormContinuation(mxEv, nextEv, cli, this.showHiddenEvents, this.context.timelineRenderingType);
}
// is this a continuation of the previous message?
const continuation =
!wantsDateSeparator &&
- shouldFormContinuation(prevEvent, mxEv, this.showHiddenEvents, this.context.timelineRenderingType);
+ shouldFormContinuation(prevEvent, mxEv, cli, this.showHiddenEvents, this.context.timelineRenderingType);
const eventId = mxEv.getId()!;
const highlight = eventId === this.props.highlightedEventId;
diff --git a/src/components/structures/RoomSearchView.tsx b/src/components/structures/RoomSearchView.tsx
index 83a63387d5..d0f2c362be 100644
--- a/src/components/structures/RoomSearchView.tsx
+++ b/src/components/structures/RoomSearchView.tsx
@@ -237,7 +237,7 @@ export const RoomSearchView = forwardRef(
continue;
}
- if (!haveRendererForEvent(mxEv, roomContext.showHiddenEvents)) {
+ if (!haveRendererForEvent(mxEv, client, roomContext.showHiddenEvents)) {
// XXX: can this ever happen? It will make the result count
// not match the displayed count.
continue;
diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx
index 103e6d844b..fc9b29d69f 100644
--- a/src/components/structures/TimelinePanel.tsx
+++ b/src/components/structures/TimelinePanel.tsx
@@ -1965,7 +1965,8 @@ class TimelinePanel extends React.Component {
!!ev.status || // local echo
(ignoreOwn && ev.getSender() === myUserId); // own message
const isWithoutTile =
- !haveRendererForEvent(ev, this.context?.showHiddenEvents) || shouldHideEvent(ev, this.context);
+ !haveRendererForEvent(ev, MatrixClientPeg.safeGet(), this.context?.showHiddenEvents) ||
+ shouldHideEvent(ev, this.context);
if (isWithoutTile || !node) {
// don't start counting if the event should be ignored,
diff --git a/src/components/views/dialogs/ConfirmRedactDialog.tsx b/src/components/views/dialogs/ConfirmRedactDialog.tsx
index 9c1fa2b181..0cf77871c0 100644
--- a/src/components/views/dialogs/ConfirmRedactDialog.tsx
+++ b/src/components/views/dialogs/ConfirmRedactDialog.tsx
@@ -75,7 +75,7 @@ export function createRedactEventDialog({
onFinished: async (proceed, reason): Promise => {
if (!proceed) return;
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
const withRelTypes: Pick = {};
// redact related events if this is a voice broadcast started event and
diff --git a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx
index d81d6e76ca..0946f2dbb9 100644
--- a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx
+++ b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx
@@ -37,7 +37,7 @@ export function ManualDeviceKeyVerificationDialog({
device,
onFinished,
}: IManualDeviceKeyVerificationDialogProps): JSX.Element {
- const mxClient = MatrixClientPeg.get();
+ const mxClient = MatrixClientPeg.safeGet();
const onLegacyFinished = useCallback(
(confirm: boolean) => {
diff --git a/src/components/views/right_panel/VerificationPanel.tsx b/src/components/views/right_panel/VerificationPanel.tsx
index 6782c967a2..0abee5e81f 100644
--- a/src/components/views/right_panel/VerificationPanel.tsx
+++ b/src/components/views/right_panel/VerificationPanel.tsx
@@ -203,9 +203,9 @@ export default class VerificationPanel extends React.PureComponent
let replyChain: JSX.Element | undefined;
if (
- haveRendererForEvent(this.props.mxEvent, this.context.showHiddenEvents) &&
+ haveRendererForEvent(this.props.mxEvent, MatrixClientPeg.safeGet(), this.context.showHiddenEvents) &&
shouldDisplayReply(this.props.mxEvent)
) {
replyChain = (
diff --git a/src/components/views/rooms/SearchResultTile.tsx b/src/components/views/rooms/SearchResultTile.tsx
index a4b369150e..c7366c6c14 100644
--- a/src/components/views/rooms/SearchResultTile.tsx
+++ b/src/components/views/rooms/SearchResultTile.tsx
@@ -27,6 +27,7 @@ import { shouldFormContinuation } from "../../structures/MessagePanel";
import { wantsDateSeparator } from "../../../DateUtils";
import LegacyCallEventGrouper, { buildLegacyCallEventGroupers } from "../../structures/LegacyCallEventGrouper";
import { haveRendererForEvent } from "../../../events/EventTileFactory";
+import { MatrixClientPeg } from "../../../MatrixClientPeg";
interface IProps {
// a list of strings to be highlighted in the results
@@ -69,6 +70,7 @@ export default class SearchResultTile extends React.Component {
const isTwelveHour = SettingsStore.getValue("showTwelveHourTimestamps");
const alwaysShowTimestamps = SettingsStore.getValue("alwaysShowTimestamps");
+ const cli = MatrixClientPeg.safeGet();
for (let j = 0; j < timeline.length; j++) {
const mxEv = timeline[j];
let highlights: string[] | undefined;
@@ -77,14 +79,20 @@ export default class SearchResultTile extends React.Component {
highlights = this.props.searchHighlights;
}
- if (haveRendererForEvent(mxEv, this.context?.showHiddenEvents)) {
+ if (haveRendererForEvent(mxEv, cli, this.context?.showHiddenEvents)) {
// do we need a date separator since the last event?
const prevEv = timeline[j - 1];
// is this a continuation of the previous message?
const continuation =
prevEv &&
!wantsDateSeparator(prevEv.getDate() || undefined, mxEv.getDate() || undefined) &&
- shouldFormContinuation(prevEv, mxEv, this.context?.showHiddenEvents, TimelineRenderingType.Search);
+ shouldFormContinuation(
+ prevEv,
+ mxEv,
+ cli,
+ this.context?.showHiddenEvents,
+ TimelineRenderingType.Search,
+ );
let lastInSection = true;
const nextEv = timeline[j + 1];
@@ -99,6 +107,7 @@ export default class SearchResultTile extends React.Component {
!shouldFormContinuation(
mxEv,
nextEv,
+ cli,
this.context?.showHiddenEvents,
TimelineRenderingType.Search,
);
diff --git a/src/components/views/settings/CrossSigningPanel.tsx b/src/components/views/settings/CrossSigningPanel.tsx
index f5b893e4ea..ed53bd274c 100644
--- a/src/components/views/settings/CrossSigningPanel.tsx
+++ b/src/components/views/settings/CrossSigningPanel.tsx
@@ -51,7 +51,7 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
}
public componentDidMount(): void {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
cli.on(ClientEvent.AccountData, this.onAccountData);
cli.on(CryptoEvent.UserTrustStatusChanged, this.onStatusChanged);
cli.on(CryptoEvent.KeysChanged, this.onStatusChanged);
@@ -89,7 +89,7 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
};
private async getUpdatedStatus(): Promise {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
const crypto = cli.getCrypto();
if (!crypto) return;
@@ -127,7 +127,7 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
private bootstrapCrossSigning = async ({ forceReset = false }): Promise => {
this.setState({ error: undefined });
try {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
await cli.bootstrapCrossSigning({
authUploadDeviceSigningKeys: async (makeRequest): Promise => {
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
diff --git a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx
index 150db726a7..92981407fb 100644
--- a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx
+++ b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx
@@ -89,7 +89,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
this.setState({ busy: true });
try {
- const room = await MatrixClientPeg.get().joinRoom(this.state.newList);
+ const room = await MatrixClientPeg.safeGet().joinRoom(this.state.newList);
await Mjolnir.sharedInstance().subscribeToList(room.roomId);
this.setState({ newList: "" }); // this will also cause the new rule to be rendered
} catch (e) {
@@ -125,7 +125,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
this.setState({ busy: true });
try {
await Mjolnir.sharedInstance().unsubscribeFromList(list.roomId);
- await MatrixClientPeg.get().leave(list.roomId);
+ await MatrixClientPeg.safeGet().leave(list.roomId);
} catch (e) {
logger.error(e);
@@ -139,7 +139,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
}
private viewListRules(list: BanList): void {
- const room = MatrixClientPeg.get().getRoom(list.roomId);
+ const room = MatrixClientPeg.safeGet().getRoom(list.roomId);
const name = room ? room.name : list.roomId;
const renderRules = (rules: ListRule[]): JSX.Element => {
@@ -210,7 +210,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
const tiles: JSX.Element[] = [];
for (const list of lists) {
- const room = MatrixClientPeg.get().getRoom(list.roomId);
+ const room = MatrixClientPeg.safeGet().getRoom(list.roomId);
const name = room ? (
{room.name} ({list.roomId}
)
diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx
index c902577b61..e77627323e 100644
--- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx
+++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx
@@ -93,7 +93,7 @@ export default class SecurityUserSettingsTab extends React.Component room.roomId));
this.state = {
- ignoredUserIds: MatrixClientPeg.get().getIgnoredUsers(),
+ ignoredUserIds: MatrixClientPeg.safeGet().getIgnoredUsers(),
waitingUnignored: [],
managingInvites: false,
invitedRoomIds,
@@ -102,7 +102,7 @@ export default class SecurityUserSettingsTab extends React.Component {
if (action === "ignore_state_changed") {
- const ignoredUserIds = MatrixClientPeg.get().getIgnoredUsers();
+ const ignoredUserIds = MatrixClientPeg.safeGet().getIgnoredUsers();
const newWaitingUnignored = this.state.waitingUnignored.filter((e) => ignoredUserIds.includes(e));
this.setState({ ignoredUserIds, waitingUnignored: newWaitingUnignored });
}
@@ -110,15 +110,15 @@ export default class SecurityUserSettingsTab extends React.Component this.setState({ versions }));
}
public componentWillUnmount(): void {
if (this.dispatcherRef) dis.unregister(this.dispatcherRef);
- MatrixClientPeg.get().removeListener(RoomEvent.MyMembership, this.onMyMembership);
+ MatrixClientPeg.safeGet().removeListener(RoomEvent.MyMembership, this.onMyMembership);
}
private onMyMembership = (room: Room, membership: string): void => {
@@ -159,15 +159,15 @@ export default class SecurityUserSettingsTab extends React.Component ({ waitingUnignored: [...waitingUnignored, userId] }));
- MatrixClientPeg.get().setIgnoredUsers(currentlyIgnoredUserIds);
+ MatrixClientPeg.safeGet().setIgnoredUsers(currentlyIgnoredUserIds);
}
};
private getInvitedRooms = (): Room[] => {
- return MatrixClientPeg.get()
+ return MatrixClientPeg.safeGet()
.getRooms()
.filter((r) => {
- return r.hasMembershipState(MatrixClientPeg.get().getUserId()!, "invite");
+ return r.hasMembershipState(MatrixClientPeg.safeGet().getUserId()!, "invite");
});
};
@@ -180,7 +180,7 @@ export default class SecurityUserSettingsTab extends React.Component
{_t(
diff --git a/src/components/views/toasts/VerificationRequestToast.tsx b/src/components/views/toasts/VerificationRequestToast.tsx
index 9f2aa89312..0e9a7781f6 100644
--- a/src/components/views/toasts/VerificationRequestToast.tsx
+++ b/src/components/views/toasts/VerificationRequestToast.tsx
@@ -75,7 +75,7 @@ export default class VerificationRequestToast extends React.PureComponent({
@@ -165,12 +165,12 @@ export default class VerificationRequestToast extends React.PureComponent {
- cli = cli ?? MatrixClientPeg.get(); // because param defaults don't do the correct thing
+ cli = cli ?? MatrixClientPeg.safeGet(); // because param defaults don't do the correct thing
const factory = pickFactory(props.mxEvent, cli, showHiddenEvents);
if (!factory) return undefined;
@@ -378,7 +378,7 @@ export function renderReplyTile(
showHiddenEvents: boolean,
cli?: MatrixClient,
): Optional {
- cli = cli ?? MatrixClientPeg.get(); // because param defaults don't do the correct thing
+ cli = cli ?? MatrixClientPeg.safeGet(); // because param defaults don't do the correct thing
const factory = pickFactory(props.mxEvent, cli, showHiddenEvents);
if (!factory) return undefined;
@@ -426,7 +426,11 @@ export function isMessageEvent(ev: MatrixEvent): boolean {
);
}
-export function haveRendererForEvent(mxEvent: MatrixEvent, showHiddenEvents: boolean): boolean {
+export function haveRendererForEvent(
+ mxEvent: MatrixEvent,
+ matrixClient: MatrixClient,
+ showHiddenEvents: boolean,
+): boolean {
// Only show "Message deleted" tile for plain message events, encrypted events,
// and state events as they'll likely still contain enough keys to be relevant.
if (mxEvent.isRedacted() && !mxEvent.isEncrypted() && !isMessageEvent(mxEvent) && !mxEvent.isState()) {
@@ -436,14 +440,13 @@ export function haveRendererForEvent(mxEvent: MatrixEvent, showHiddenEvents: boo
// No tile for replacement events since they update the original tile
if (mxEvent.isRelation(RelationType.Replace)) return false;
- const cli = MatrixClientPeg.get();
- const handler = pickFactory(mxEvent, cli, showHiddenEvents);
+ const handler = pickFactory(mxEvent, matrixClient, showHiddenEvents);
if (!handler) return false;
if (handler === TextualEventFactory) {
- return hasText(mxEvent, cli, showHiddenEvents);
+ return hasText(mxEvent, matrixClient, 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);
+ const predecessor = matrixClient.getRoom(mxEvent.getRoomId())?.findPredecessor(dynamicPredecessorsEnabled);
return Boolean(predecessor);
} else if (
ElementCall.CALL_EVENT_TYPE.names.some((eventType) => handler === STATE_EVENT_TILE_TYPES.get(eventType))
diff --git a/src/indexing/EventIndex.ts b/src/indexing/EventIndex.ts
index 2abecef074..5a24b2ae36 100644
--- a/src/indexing/EventIndex.ts
+++ b/src/indexing/EventIndex.ts
@@ -69,7 +69,7 @@ export default class EventIndex extends EventEmitter {
* Register event listeners that are necessary for the event index to work.
*/
public registerListeners(): void {
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
client.on(ClientEvent.Sync, this.onSync);
client.on(RoomEvent.Timeline, this.onRoomTimeline);
@@ -96,7 +96,7 @@ export default class EventIndex extends EventEmitter {
public async addInitialCheckpoints(): Promise {
const indexManager = PlatformPeg.get()?.getEventIndexingManager();
if (!indexManager) return;
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
const rooms = client.getRooms();
const isRoomEncrypted = (room: Room): boolean => {
@@ -200,7 +200,7 @@ export default class EventIndex extends EventEmitter {
): Promise => {
if (!room) return; // notification timeline, we'll get this event again with a room specific timeline
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
// We only index encrypted rooms locally.
if (!client.isRoomEncrypted(ev.getRoomId()!)) return;
@@ -220,7 +220,7 @@ export default class EventIndex extends EventEmitter {
};
private onRoomStateEvent = async (ev: MatrixEvent, state: RoomState): Promise => {
- if (!MatrixClientPeg.get().isRoomEncrypted(state.roomId)) return;
+ if (!MatrixClientPeg.safeGet().isRoomEncrypted(state.roomId)) return;
if (ev.getType() === EventType.RoomEncryption && !(await this.isRoomIndexed(state.roomId))) {
logger.log("EventIndex: Adding a checkpoint for a newly encrypted room", state.roomId);
@@ -254,7 +254,7 @@ export default class EventIndex extends EventEmitter {
*/
private onTimelineReset = async (room: Room | undefined): Promise => {
if (!room) return;
- if (!MatrixClientPeg.get().isRoomEncrypted(room.roomId)) return;
+ if (!MatrixClientPeg.safeGet().isRoomEncrypted(room.roomId)) return;
logger.log("EventIndex: Adding a checkpoint because of a limited timeline", room.roomId);
@@ -364,7 +364,7 @@ export default class EventIndex extends EventEmitter {
private async addRoomCheckpoint(roomId: string, fullCrawl = false): Promise {
const indexManager = PlatformPeg.get()?.getEventIndexingManager();
if (!indexManager) return;
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
const room = client.getRoom(roomId);
if (!room) return;
@@ -410,7 +410,7 @@ export default class EventIndex extends EventEmitter {
private async crawlerFunc(): Promise {
let cancelled = false;
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
const indexManager = PlatformPeg.get()?.getEventIndexingManager();
if (!indexManager) return;
@@ -707,7 +707,7 @@ export default class EventIndex extends EventEmitter {
fromEvent?: string,
direction: string = EventTimeline.BACKWARDS,
): Promise {
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
const indexManager = PlatformPeg.get()?.getEventIndexingManager();
if (!indexManager) return [];
@@ -942,7 +942,7 @@ export default class EventIndex extends EventEmitter {
return null;
}
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
if (this.currentCheckpoint !== null) {
return client.getRoom(this.currentCheckpoint.roomId);
@@ -966,7 +966,7 @@ export default class EventIndex extends EventEmitter {
crawlingRooms.add(this.currentCheckpoint.roomId);
}
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
const rooms = client.getRooms();
const isRoomEncrypted = (room: Room): boolean => {
diff --git a/src/integrations/IntegrationManagers.ts b/src/integrations/IntegrationManagers.ts
index 38e5bcb96f..3464bbc20e 100644
--- a/src/integrations/IntegrationManagers.ts
+++ b/src/integrations/IntegrationManagers.ts
@@ -55,7 +55,7 @@ export class IntegrationManagers {
public startWatching(): void {
this.stopWatching();
- this.client = MatrixClientPeg.get();
+ this.client = MatrixClientPeg.safeGet();
this.client.on(ClientEvent.AccountData, this.onAccountData);
this.client.on(ClientEvent.ClientWellKnown, this.setupHomeserverManagers);
this.compileManagers();
diff --git a/src/linkify-matrix.ts b/src/linkify-matrix.ts
index d753bc21d7..085143f198 100644
--- a/src/linkify-matrix.ts
+++ b/src/linkify-matrix.ts
@@ -197,7 +197,7 @@ export const options: Opts = {
case Type.RoomAlias:
case Type.UserId:
default: {
- return tryTransformEntityToPermalink(MatrixClientPeg.get(), href) ?? "";
+ return tryTransformEntityToPermalink(MatrixClientPeg.safeGet(), href) ?? "";
}
}
},
diff --git a/src/mjolnir/BanList.ts b/src/mjolnir/BanList.ts
index 7eec5d3b26..0d82a4c080 100644
--- a/src/mjolnir/BanList.ts
+++ b/src/mjolnir/BanList.ts
@@ -70,7 +70,7 @@ export class BanList {
public async banEntity(kind: string, entity: string, reason: string): Promise {
const type = ruleTypeToStable(kind);
if (!type) return; // unknown rule type
- await MatrixClientPeg.get().sendStateEvent(
+ await MatrixClientPeg.safeGet().sendStateEvent(
this._roomId,
type,
{
@@ -87,7 +87,7 @@ export class BanList {
const type = ruleTypeToStable(kind);
if (!type) return; // unknown rule type
// Empty state event is effectively deleting it.
- await MatrixClientPeg.get().sendStateEvent(this._roomId, type, {}, "rule:" + entity);
+ await MatrixClientPeg.safeGet().sendStateEvent(this._roomId, type, {}, "rule:" + entity);
this._rules = this._rules.filter((r) => {
if (r.kind !== ruleTypeToStable(kind)) return true;
if (r.entity !== entity) return true;
@@ -98,7 +98,7 @@ export class BanList {
public updateList(): void {
this._rules = [];
- const room = MatrixClientPeg.get().getRoom(this._roomId);
+ const room = MatrixClientPeg.safeGet().getRoom(this._roomId);
if (!room) return;
for (const eventType of ALL_RULE_TYPES) {
diff --git a/src/mjolnir/Mjolnir.ts b/src/mjolnir/Mjolnir.ts
index 6df52f808a..303db61f8b 100644
--- a/src/mjolnir/Mjolnir.ts
+++ b/src/mjolnir/Mjolnir.ts
@@ -67,7 +67,7 @@ export class Mjolnir {
public setup(): void {
if (!MatrixClientPeg.get()) return;
this.updateLists(SettingsStore.getValue("mjolnirRooms"));
- MatrixClientPeg.get().on(RoomStateEvent.Events, this.onEvent);
+ MatrixClientPeg.get()!.on(RoomStateEvent.Events, this.onEvent);
}
public stop(): void {
@@ -81,14 +81,13 @@ export class Mjolnir {
this.dispatcherRef = null;
}
- if (!MatrixClientPeg.get()) return;
- MatrixClientPeg.get().removeListener(RoomStateEvent.Events, this.onEvent);
+ MatrixClientPeg.get()?.removeListener(RoomStateEvent.Events, this.onEvent);
}
public async getOrCreatePersonalList(): Promise {
let personalRoomId = SettingsStore.getValue("mjolnirPersonalRoom");
if (!personalRoomId) {
- const resp = await MatrixClientPeg.get().createRoom({
+ const resp = await MatrixClientPeg.safeGet().createRoom({
name: _t("My Ban List"),
topic: _t("This is your list of users/servers you have blocked - don't leave the room!"),
preset: Preset.PrivateChat,
diff --git a/src/modules/ProxiedModuleApi.ts b/src/modules/ProxiedModuleApi.ts
index 5d93c67eec..e66d3cbe10 100644
--- a/src/modules/ProxiedModuleApi.ts
+++ b/src/modules/ProxiedModuleApi.ts
@@ -189,7 +189,7 @@ export class ProxiedModuleApi implements ModuleApi {
roomId = getCachedRoomIDForAlias(parts.roomIdOrAlias);
if (!roomId) {
// alias resolution failed
- const result = await MatrixClientPeg.get().getRoomIdForAlias(parts.roomIdOrAlias);
+ const result = await MatrixClientPeg.safeGet().getRoomIdForAlias(parts.roomIdOrAlias);
roomId = result.room_id;
if (!servers) servers = result.servers; // use provided servers first, if available
}
diff --git a/src/sentry.ts b/src/sentry.ts
index 61098bf59d..909a21ed1c 100644
--- a/src/sentry.ts
+++ b/src/sentry.ts
@@ -165,7 +165,7 @@ function getDeviceContext(client: MatrixClient): DeviceContext {
}
async function getContexts(): Promise {
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
return {
user: getUserContext(client),
crypto: await getCryptoContext(client),
diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts
index a51faa2cee..7169494f4c 100644
--- a/src/settings/SettingsStore.ts
+++ b/src/settings/SettingsStore.ts
@@ -611,7 +611,7 @@ export default class SettingsStore {
}
private static migrateHiddenReadReceipts(): void {
- if (MatrixClientPeg.get().isGuest()) return; // not worth it
+ if (MatrixClientPeg.safeGet().isGuest()) return; // not worth it
// We wait for the first sync to ensure that the user's existing account data has loaded, as otherwise
// getValue() for an account-level setting like sendReadReceipts will return `null`.
diff --git a/src/settings/controllers/NotificationControllers.ts b/src/settings/controllers/NotificationControllers.ts
index aae9b16ba2..1827ab98ec 100644
--- a/src/settings/controllers/NotificationControllers.ts
+++ b/src/settings/controllers/NotificationControllers.ts
@@ -28,7 +28,7 @@ import { SettingLevel } from "../SettingLevel";
// default action on this rule is dont_notify, but it could be something else
export function isPushNotifyDisabled(): boolean {
// Return the value of the master push rule as a default
- const processor = new PushProcessor(MatrixClientPeg.get());
+ const processor = new PushProcessor(MatrixClientPeg.safeGet());
const masterRule = processor.getPushRuleById(".m.rule.master");
if (!masterRule) {
diff --git a/src/toasts/DesktopNotificationsToast.ts b/src/toasts/DesktopNotificationsToast.ts
index 856c6d9dd6..73f5ff3c15 100644
--- a/src/toasts/DesktopNotificationsToast.ts
+++ b/src/toasts/DesktopNotificationsToast.ts
@@ -23,7 +23,7 @@ import { getLocalNotificationAccountDataEventType } from "../utils/notifications
const onAccept = (): void => {
Notifier.setEnabled(true);
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
const eventType = getLocalNotificationAccountDataEventType(cli.deviceId!);
cli.setAccountData(eventType, {
is_silenced: false,
diff --git a/src/toasts/IncomingCallToast.tsx b/src/toasts/IncomingCallToast.tsx
index 72df4fd122..1dd7a0343c 100644
--- a/src/toasts/IncomingCallToast.tsx
+++ b/src/toasts/IncomingCallToast.tsx
@@ -67,7 +67,7 @@ interface Props {
export function IncomingCallToast({ callEvent }: Props): JSX.Element {
const roomId = callEvent.getRoomId()!;
- const room = MatrixClientPeg.get().getRoom(roomId) ?? undefined;
+ const room = MatrixClientPeg.safeGet().getRoom(roomId) ?? undefined;
const call = useCall(roomId);
const dismissToast = useCallback((): void => {
diff --git a/src/toasts/IncomingLegacyCallToast.tsx b/src/toasts/IncomingLegacyCallToast.tsx
index 33a904afe7..7464f806f1 100644
--- a/src/toasts/IncomingLegacyCallToast.tsx
+++ b/src/toasts/IncomingLegacyCallToast.tsx
@@ -92,7 +92,7 @@ export default class IncomingLegacyCallToast extends React.Component => {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
const onAccept = (): void => {
DeviceListener.sharedInstance().dismissUnverifiedSessions([deviceId]);
diff --git a/src/utils/EventRenderingUtils.ts b/src/utils/EventRenderingUtils.ts
index eda5a14320..ebbd688c9c 100644
--- a/src/utils/EventRenderingUtils.ts
+++ b/src/utils/EventRenderingUtils.ts
@@ -101,7 +101,7 @@ export function getEventDisplayInfo(
// source tile when there's no regular tile for an event and also for
// replace relations (which otherwise would display as a confusing
// duplicate of the thing they are replacing).
- if (hideEvent || !haveRendererForEvent(mxEvent, showHiddenEvents)) {
+ if (hideEvent || !haveRendererForEvent(mxEvent, matrixClient, showHiddenEvents)) {
// forcefully ask for a factory for a hidden event (hidden event setting is checked internally)
factory = pickFactory(mxEvent, matrixClient, showHiddenEvents, true);
if (factory === JSONEventFactory) {
diff --git a/src/utils/exportUtils/HtmlExport.tsx b/src/utils/exportUtils/HtmlExport.tsx
index 0dd315819a..7863ae01b1 100644
--- a/src/utils/exportUtils/HtmlExport.tsx
+++ b/src/utils/exportUtils/HtmlExport.tsx
@@ -429,11 +429,12 @@ export default class HTMLExporter extends Exporter {
true,
);
if (this.cancelled) return this.cleanUp();
- if (!haveRendererForEvent(event, false)) continue;
+ if (!haveRendererForEvent(event, this.room.client, false)) continue;
content += this.needsDateSeparator(event, prevEvent) ? this.getDateSeparator(event) : "";
const shouldBeJoined =
- !this.needsDateSeparator(event, prevEvent) && shouldFormContinuation(prevEvent, event, false);
+ !this.needsDateSeparator(event, prevEvent) &&
+ shouldFormContinuation(prevEvent, event, this.room.client, false);
const body = await this.createMessageBody(event, shouldBeJoined);
this.totalSize += Buffer.byteLength(body);
content += body;
diff --git a/src/utils/exportUtils/JSONExport.ts b/src/utils/exportUtils/JSONExport.ts
index 17546790c7..a78f11caa4 100644
--- a/src/utils/exportUtils/JSONExport.ts
+++ b/src/utils/exportUtils/JSONExport.ts
@@ -93,7 +93,7 @@ export default class JSONExporter extends Exporter {
true,
);
if (this.cancelled) return this.cleanUp();
- if (!haveRendererForEvent(event, false)) continue;
+ if (!haveRendererForEvent(event, this.room.client, false)) continue;
this.messages.push(await this.getJSONString(event));
}
return this.createJSONString();
diff --git a/src/utils/exportUtils/PlainTextExport.ts b/src/utils/exportUtils/PlainTextExport.ts
index a6e509fc94..504ebc442b 100644
--- a/src/utils/exportUtils/PlainTextExport.ts
+++ b/src/utils/exportUtils/PlainTextExport.ts
@@ -120,7 +120,7 @@ export default class PlainTextExporter extends Exporter {
true,
);
if (this.cancelled) return this.cleanUp();
- if (!haveRendererForEvent(event, false)) continue;
+ if (!haveRendererForEvent(event, this.room.client, false)) continue;
const textForEvent = await this.plainTextForEvent(event);
content += textForEvent && `${new Date(event.getTs()).toLocaleString()} - ${textForEvent}\n`;
}
diff --git a/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts b/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts
index 1e4c02fe00..bbf4600f25 100644
--- a/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts
+++ b/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts
@@ -41,7 +41,7 @@ export const useVoiceBroadcastPlayback = (
toggle(): void;
room: Room;
} => {
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
const room = client.getRoom(playback.infoEvent.getRoomId());
if (!room) {
diff --git a/src/voice-broadcast/hooks/useVoiceBroadcastRecording.tsx b/src/voice-broadcast/hooks/useVoiceBroadcastRecording.tsx
index f9df59ae41..fe6d00a996 100644
--- a/src/voice-broadcast/hooks/useVoiceBroadcastRecording.tsx
+++ b/src/voice-broadcast/hooks/useVoiceBroadcastRecording.tsx
@@ -58,7 +58,7 @@ export const useVoiceBroadcastRecording = (
stopRecording(): void;
toggleRecording(): void;
} => {
- const client = MatrixClientPeg.get();
+ const client = MatrixClientPeg.safeGet();
const roomId = recording.infoEvent.getRoomId();
const room = client.getRoom(roomId);
diff --git a/src/widgets/CapabilityText.tsx b/src/widgets/CapabilityText.tsx
index d0dffd399e..bbb0ebfb96 100644
--- a/src/widgets/CapabilityText.tsx
+++ b/src/widgets/CapabilityText.tsx
@@ -149,7 +149,7 @@ export class CapabilityText {
return { primary: _t("The above, but in any room you are joined or invited to as well") };
} else {
const roomId = getTimelineRoomIDFromCapability(capability);
- const room = MatrixClientPeg.get().getRoom(roomId);
+ const room = MatrixClientPeg.safeGet().getRoom(roomId);
return {
primary: _t(
"The above, but in as well",
diff --git a/src/widgets/Jitsi.ts b/src/widgets/Jitsi.ts
index af250e91bf..eecab5ab67 100644
--- a/src/widgets/Jitsi.ts
+++ b/src/widgets/Jitsi.ts
@@ -62,7 +62,7 @@ export class Jitsi {
}
public start(): void {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
cli.on(ClientEvent.ClientWellKnown, this.update);
// call update initially in case we missed the first WellKnown.client event and for if no well-known present
this.update(cli.getClientWellKnown());
diff --git a/src/widgets/ManagedHybrid.ts b/src/widgets/ManagedHybrid.ts
index 21c432aa3b..e171a31af7 100644
--- a/src/widgets/ManagedHybrid.ts
+++ b/src/widgets/ManagedHybrid.ts
@@ -43,7 +43,7 @@ function getWidgetBuildUrl(roomId: string): string | undefined {
return SdkConfig.get().widget_build_url;
}
- const wellKnown = getCallBehaviourWellKnown(MatrixClientPeg.get());
+ const wellKnown = getCallBehaviourWellKnown(MatrixClientPeg.safeGet());
if (isDm && wellKnown?.ignore_dm) {
return undefined;
}
@@ -56,7 +56,7 @@ export function isManagedHybridWidgetEnabled(roomId: string): boolean {
}
export async function addManagedHybridWidget(roomId: string): Promise {
- const cli = MatrixClientPeg.get();
+ const cli = MatrixClientPeg.safeGet();
const room = cli.getRoom(roomId);
if (!room) {
return;
diff --git a/test/Unread-test.ts b/test/Unread-test.ts
index dc9c0f7a6b..ca67257357 100644
--- a/test/Unread-test.ts
+++ b/test/Unread-test.ts
@@ -81,13 +81,13 @@ describe("Unread", () => {
it("returns false for an event without a renderer", () => {
mocked(haveRendererForEvent).mockReturnValue(false);
expect(eventTriggersUnreadCount(client, alicesMessage)).toBe(false);
- expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, false);
+ expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, client, false);
});
it("returns true for an event with a renderer", () => {
mocked(haveRendererForEvent).mockReturnValue(true);
expect(eventTriggersUnreadCount(client, alicesMessage)).toBe(true);
- expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, false);
+ expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, client, false);
});
it("returns false for beacon locations", () => {
diff --git a/test/components/structures/MessagePanel-test.tsx b/test/components/structures/MessagePanel-test.tsx
index ec7382f5e7..01671fdb01 100644
--- a/test/components/structures/MessagePanel-test.tsx
+++ b/test/components/structures/MessagePanel-test.tsx
@@ -29,6 +29,7 @@ import RoomContext, { TimelineRenderingType } from "../../../src/contexts/RoomCo
import DMRoomMap from "../../../src/utils/DMRoomMap";
import * as TestUtilsMatrix from "../../test-utils";
import {
+ createTestClient,
getMockClientWithEventEmitter,
makeBeaconInfoEvent,
mockClientMethodsEvents,
@@ -773,16 +774,17 @@ describe("shouldFormContinuation", () => {
msg: "And here's another message in the main timeline after the thread root",
});
- expect(shouldFormContinuation(message1, message2, false)).toEqual(true);
- expect(shouldFormContinuation(message2, threadRoot, false)).toEqual(true);
- expect(shouldFormContinuation(threadRoot, message3, false)).toEqual(true);
+ const client = createTestClient();
+ expect(shouldFormContinuation(message1, message2, client, false)).toEqual(true);
+ expect(shouldFormContinuation(message2, threadRoot, client, false)).toEqual(true);
+ expect(shouldFormContinuation(threadRoot, message3, client, false)).toEqual(true);
const thread = {
length: 1,
replyToEvent: {},
} as unknown as Thread;
jest.spyOn(threadRoot, "getThread").mockReturnValue(thread);
- expect(shouldFormContinuation(message2, threadRoot, false)).toEqual(false);
- expect(shouldFormContinuation(threadRoot, message3, false)).toEqual(false);
+ expect(shouldFormContinuation(message2, threadRoot, client, false)).toEqual(false);
+ expect(shouldFormContinuation(threadRoot, message3, client, false)).toEqual(false);
});
});
diff --git a/test/components/views/dialogs/security/CreateKeyBackupDialog-test.tsx b/test/components/views/dialogs/security/CreateKeyBackupDialog-test.tsx
index e7a91f3715..b0d461b8f8 100644
--- a/test/components/views/dialogs/security/CreateKeyBackupDialog-test.tsx
+++ b/test/components/views/dialogs/security/CreateKeyBackupDialog-test.tsx
@@ -28,7 +28,7 @@ jest.mock("../../../../../src/SecurityManager", () => ({
describe("CreateKeyBackupDialog", () => {
beforeEach(() => {
- MatrixClientPeg.get = () => createTestClient();
+ MatrixClientPeg.safeGet = MatrixClientPeg.get = () => createTestClient();
});
it("should display the spinner when creating backup", () => {
@@ -42,7 +42,7 @@ describe("CreateKeyBackupDialog", () => {
it("should display the error message when backup creation failed", async () => {
const matrixClient = createTestClient();
mocked(matrixClient.scheduleAllGroupSessionsForBackup).mockRejectedValue("my error");
- MatrixClientPeg.get = () => matrixClient;
+ MatrixClientPeg.safeGet = MatrixClientPeg.get = () => matrixClient;
const { asFragment } = render();
diff --git a/test/components/views/rooms/RoomPreviewBar-test.tsx b/test/components/views/rooms/RoomPreviewBar-test.tsx
index e39c5fc6f6..cc418bcb0a 100644
--- a/test/components/views/rooms/RoomPreviewBar-test.tsx
+++ b/test/components/views/rooms/RoomPreviewBar-test.tsx
@@ -95,8 +95,8 @@ describe("", () => {
beforeEach(() => {
stubClient();
- MatrixClientPeg.get().getUserId = jest.fn().mockReturnValue(userId);
- MatrixClientPeg.get().getSafeUserId = jest.fn().mockReturnValue(userId);
+ MatrixClientPeg.get()!.getUserId = jest.fn().mockReturnValue(userId);
+ MatrixClientPeg.get()!.getSafeUserId = jest.fn().mockReturnValue(userId);
MatrixClientPeg.safeGet().getUserId = jest.fn().mockReturnValue(userId);
MatrixClientPeg.safeGet().getSafeUserId = jest.fn().mockReturnValue(userId);
});