Use MatrixClientPeg::safeGet for strict typing (#10989)

This commit is contained in:
Michael Telatynski 2023-06-21 17:29:44 +01:00 committed by GitHub
parent d64018ce26
commit 9b5b053148
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 225 additions and 203 deletions

View file

@ -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<string> {
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;

View file

@ -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<void> {
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<ThirdpartyLookupResponse[]> {
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<ThirdpartyLookupResponse[]> {
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<ThirdpartyLookupResponse[]> {
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<void> {
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<void> {
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<void> {
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<void> {
const client = MatrixClientPeg.get();
const client = MatrixClientPeg.safeGet();
logger.info(`Place conference call in ${roomId}`);
dis.dispatch({ action: "appsDrawer", show: true });

View file

@ -278,7 +278,7 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> | 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<Matr
* @returns {Promise} promise which resolves to the new MatrixClient once it has been started
*/
export async function hydrateSession(credentials: IMatrixClientCreds): Promise<MatrixClient> {
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

View file

@ -73,7 +73,7 @@ export interface IMatrixClientPeg {
*/
getHomeserverName(): string | null;
get(): MatrixClient;
get(): MatrixClient | null;
safeGet(): MatrixClient;
unset(): void;
assign(): Promise<any>;
@ -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;
}

View file

@ -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<void> {
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<void> {
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<void> {
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<void> {

View file

@ -91,7 +91,7 @@ const msgTypeHandlers: Record<string, (event: MatrixEvent) => 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<void> {
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);

View file

@ -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);

View file

@ -131,7 +131,7 @@ export default class ScalarAuthClient {
private checkToken(token: string): Promise<string> {
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<string> {
// 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

View file

@ -411,7 +411,7 @@ function kickUser(event: MessageEvent<any>, roomId: string, userId: string): voi
}
function setWidget(event: MessageEvent<any>, 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<any>, 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<any>, roomId: string, eventType: s
async function getOpenIdToken(event: MessageEvent<any>): Promise<void> {
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);

View file

@ -99,7 +99,7 @@ async function getSecretStorageKey({
}: {
keys: Record<string, ISecretStorageKeyInfo>;
}): 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<boolean> => {
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<string | undefined> {
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<Uint8Array> {
* @param {bool} [forceReset] Reset secret storage even if it's already set up
*/
export async function accessSecretStorage(func = async (): Promise<void> => {}, forceReset = false): Promise<void> {
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.

View file

@ -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 {

View file

@ -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

View file

@ -72,14 +72,15 @@ export default class CreateKeyBackupDialog extends React.PureComponent<IProps, I
error: undefined,
});
let info: IKeyBackupInfo | undefined;
const cli = MatrixClientPeg.safeGet();
try {
await accessSecretStorage(async (): Promise<void> => {
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<IProps, I
// disable without deleting, we'll enable on next app reload since
// it is trusted.
if (info?.version) {
MatrixClientPeg.get().deleteKeyBackupVersion(info.version);
cli.deleteKeyBackupVersion(info.version);
}
this.setState({
error: e,

View file

@ -110,7 +110,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
public constructor(props: IProps) {
super(props);
const cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.safeGet();
let passPhraseKeySelected: SecureBackupSetupMethod;
const setupMethods = getSecureBackupSetupMethods(cli);
@ -157,7 +157,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
}
public componentWillUnmount(): void {
MatrixClientPeg.get().removeListener(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatusChange);
MatrixClientPeg.get()?.removeListener(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatusChange);
}
private getInitialPhase(): void {
@ -176,12 +176,11 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
private async fetchBackupInfo(): Promise<{ backupInfo?: IKeyBackupInfo; backupSigStatus?: TrustInfo }> {
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<IProp
private async queryKeyUploadAuth(): Promise<void> {
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<IProp
private onChooseKeyPassphraseFormSubmit = async (): Promise<void> => {
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<IProp
type: "m.login.password",
identifier: {
type: "m.id.user",
user: MatrixClientPeg.get().getUserId(),
user: MatrixClientPeg.safeGet().getSafeUserId(),
},
// TODO: Remove `user` once servers support proper UIA
// See https://github.com/matrix-org/synapse/issues/5665
user: MatrixClientPeg.get().getUserId(),
user: MatrixClientPeg.safeGet().getSafeUserId(),
password: this.state.accountPassword,
});
} else {
@ -311,7 +310,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
title: _t("Setting up keys"),
matrixClient: MatrixClientPeg.get(),
matrixClient: MatrixClientPeg.safeGet(),
makeRequest,
aestheticsForStagePhases: {
[SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics,
@ -331,7 +330,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
error: undefined,
});
const cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.safeGet();
const { forceReset } = this.props;
@ -457,7 +456,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
if (this.state.passPhrase !== this.state.passPhraseConfirm) return;
this.recoveryKey = await MatrixClientPeg.get().createRecoveryKeyFromPassphrase(this.state.passPhrase);
this.recoveryKey = await MatrixClientPeg.safeGet().createRecoveryKeyFromPassphrase(this.state.passPhrase);
this.setState({
copied: false,
downloaded: false,
@ -544,7 +543,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
}
private renderPhaseChooseKeyPassphrase(): JSX.Element {
const setupMethods = getSecureBackupSetupMethods(MatrixClientPeg.get());
const setupMethods = getSecureBackupSetupMethods(MatrixClientPeg.safeGet());
const optionKey = setupMethods.includes(SecureBackupSetupMethod.Key) ? this.renderOptionKey() : null;
const optionPassphrase = setupMethods.includes(SecureBackupSetupMethod.Passphrase)
? this.renderOptionPassphrase()

View file

@ -70,8 +70,8 @@ export default class NewRecoveryMethodDialog extends React.PureComponent<IProps>
</p>
);
let content;
if (MatrixClientPeg.get().getKeyBackupEnabled()) {
let content: JSX.Element | undefined;
if (MatrixClientPeg.safeGet().getKeyBackupEnabled()) {
content = (
<div>
{newMethodDetected}

View file

@ -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)) {

View file

@ -38,9 +38,9 @@ export default class NotifProvider extends AutocompleteProvider {
force = false,
limit = -1,
): Promise<ICompletion[]> {
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 (

View file

@ -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

View file

@ -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());
}

View file

@ -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(

View file

@ -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<IProps, IState> {
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<IProps, IState> {
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<IProps, IState> {
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;

View file

@ -237,7 +237,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(
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;

View file

@ -1965,7 +1965,8 @@ class TimelinePanel extends React.Component<IProps, IState> {
!!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,

View file

@ -75,7 +75,7 @@ export function createRedactEventDialog({
onFinished: async (proceed, reason): Promise<void> => {
if (!proceed) return;
const cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.safeGet();
const withRelTypes: Pick<IRedactOpts, "with_rel_types"> = {};
// redact related events if this is a voice broadcast started event and

View file

@ -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) => {

View file

@ -203,9 +203,9 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
private getDevice(): DeviceInfo | null {
const deviceId = this.props.request?.otherDeviceId;
const userId = MatrixClientPeg.get().getUserId();
const userId = MatrixClientPeg.safeGet().getUserId();
if (deviceId && userId) {
return MatrixClientPeg.get().getStoredDevice(userId, deviceId);
return MatrixClientPeg.safeGet().getStoredDevice(userId, deviceId);
} else {
return null;
}

View file

@ -1166,7 +1166,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
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 = (

View file

@ -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<IProps> {
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<IProps> {
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<IProps> {
!shouldFormContinuation(
mxEv,
nextEv,
cli,
this.context?.showHiddenEvents,
TimelineRenderingType.Search,
);

View file

@ -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<void> {
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<void> => {
this.setState({ error: undefined });
try {
const cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.safeGet();
await cli.bootstrapCrossSigning({
authUploadDeviceSigningKeys: async (makeRequest): Promise<void> => {
const { finished } = Modal.createDialog(InteractiveAuthDialog, {

View file

@ -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 ? (
<span>
{room.name} (<code>{list.roomId}</code>)

View file

@ -93,7 +93,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
const invitedRoomIds = new Set(this.getInvitedRooms().map((room) => 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<IProps, ISt
private onAction = ({ action }: ActionPayload): void => {
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<IProps, ISt
public componentDidMount(): void {
this.dispatcherRef = dis.register(this.onAction);
MatrixClientPeg.get().on(RoomEvent.MyMembership, this.onMyMembership);
MatrixClientPeg.get()
MatrixClientPeg.safeGet().on(RoomEvent.MyMembership, this.onMyMembership);
MatrixClientPeg.safeGet()
.getVersions()
.then((versions) => 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<IProps, ISt
if (index !== -1) {
currentlyIgnoredUserIds.splice(index, 1);
this.setState(({ waitingUnignored }) => ({ 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<IProps, ISt
const invitedRoomIdsValues = Array.from(this.state.invitedRoomIds);
// Execute all acceptances/rejections sequentially
const cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.safeGet();
const action = accept ? cli.joinRoom.bind(cli) : cli.leave.bind(cli);
for (let i = 0; i < invitedRoomIdsValues.length; i++) {
const roomId = invitedRoomIdsValues[i];
@ -298,7 +298,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
);
let warning;
if (!privateShouldBeEncrypted(MatrixClientPeg.get())) {
if (!privateShouldBeEncrypted(MatrixClientPeg.safeGet())) {
warning = (
<div className="mx_SecurityUserSettingsTab_warning">
{_t(

View file

@ -75,7 +75,7 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
this.checkRequestIsPending();
if (request.isSelfVerification) {
const cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.safeGet();
const device = request.otherDeviceId ? await cli.getDevice(request.otherDeviceId) : null;
const ip = device?.last_seen_ip;
this.setState({
@ -113,7 +113,7 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
ToastStore.sharedInstance().dismissToast(this.props.toastKey);
const { request } = this.props;
// no room id for to_device requests
const cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.safeGet();
try {
if (request.roomId) {
dis.dispatch<ViewRoomPayload>({
@ -165,12 +165,12 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
});
}
} else {
const client = MatrixClientPeg.safeGet();
const userId = request.otherUserId;
const roomId = request.roomId;
description = roomId ? userLabelForEventRoom(MatrixClientPeg.get(), userId, roomId) : userId;
description = roomId ? userLabelForEventRoom(client, userId, roomId) : userId;
// for legacy to_device verification requests
if (description === userId) {
const client = MatrixClientPeg.get();
const user = client.getUser(userId);
if (user && user.displayName) {
description = _t("%(name)s (%(userId)s)", { name: user.displayName, userId });

View file

@ -38,7 +38,7 @@ export class Media {
// Per above, this constructor signature can be whatever is helpful for you.
public constructor(private prepared: IPreparedMedia, client?: MatrixClient) {
this.client = client ?? MatrixClientPeg.get();
this.client = client ?? MatrixClientPeg.safeGet();
if (!this.client) {
throw new Error("No possible MatrixClient for media resolution. Please provide one or log in.");
}

View file

@ -300,7 +300,7 @@ export function renderTile(
showHiddenEvents: boolean,
cli?: MatrixClient,
): Optional<JSX.Element> {
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<JSX.Element> {
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))

View file

@ -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<void> {
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<void> => {
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<void> => {
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<void> => {
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<void> {
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<void> {
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<MatrixEvent[]> {
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 => {

View file

@ -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();

View file

@ -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) ?? "";
}
}
},

View file

@ -70,7 +70,7 @@ export class BanList {
public async banEntity(kind: string, entity: string, reason: string): Promise<any> {
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) {

View file

@ -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<BanList> {
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,

View file

@ -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
}

View file

@ -165,7 +165,7 @@ function getDeviceContext(client: MatrixClient): DeviceContext {
}
async function getContexts(): Promise<Contexts> {
const client = MatrixClientPeg.get();
const client = MatrixClientPeg.safeGet();
return {
user: getUserContext(client),
crypto: await getCryptoContext(client),

View file

@ -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`.

View file

@ -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) {

View file

@ -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,

View file

@ -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 => {

View file

@ -92,7 +92,7 @@ export default class IncomingLegacyCallToast extends React.Component<IProps, ISt
};
public render(): React.ReactNode {
const room = MatrixClientPeg.get().getRoom(this.roomId);
const room = MatrixClientPeg.safeGet().getRoom(this.roomId);
const isVoice = this.props.call.type === CallType.Voice;
const callForcedSilent = LegacyCallHandler.instance.isForcedSilent();

View file

@ -32,7 +32,7 @@ function toastKey(deviceId: string): string {
}
export const showToast = async (deviceId: string): Promise<void> => {
const cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.safeGet();
const onAccept = (): void => {
DeviceListener.sharedInstance().dismissUnverifiedSessions([deviceId]);

View file

@ -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) {

View file

@ -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;

View file

@ -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();

View file

@ -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`;
}

View file

@ -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) {

View file

@ -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);

View file

@ -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 <Room /> as well",

View file

@ -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());

View file

@ -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<void> {
const cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.safeGet();
const room = cli.getRoom(roomId);
if (!room) {
return;

View file

@ -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", () => {

View file

@ -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);
});
});

View file

@ -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(<CreateKeyBackupDialog onFinished={jest.fn()} />);

View file

@ -95,8 +95,8 @@ describe("<RoomPreviewBar />", () => {
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);
});