diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index 34b517b99c..be3d1e981f 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -74,7 +74,7 @@ class FilePanel extends React.Component { if (room?.roomId !== this.props.roomId) return; if (toStartOfTimeline || !data || !data.liveEvent || ev.isRedacted()) return; - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); client.decryptEventIfNeeded(ev); if (ev.isBeingDecrypted()) { @@ -109,11 +109,11 @@ class FilePanel extends React.Component { } public async componentDidMount(): Promise { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); await this.updateTimelineSet(this.props.roomId); - if (!MatrixClientPeg.get().isRoomEncrypted(this.props.roomId)) return; + if (!client.isRoomEncrypted(this.props.roomId)) return; // The timelineSets filter makes sure that encrypted events that contain // URLs never get added to the timeline, even if they are live events. @@ -133,7 +133,7 @@ class FilePanel extends React.Component { const client = MatrixClientPeg.get(); if (client === null) return; - if (!MatrixClientPeg.get().isRoomEncrypted(this.props.roomId)) return; + if (!client.isRoomEncrypted(this.props.roomId)) return; if (EventIndexPeg.get() !== null) { client.removeListener(RoomEvent.Timeline, this.onRoomTimeline); @@ -142,9 +142,9 @@ class FilePanel extends React.Component { } public async fetchFileEventsServer(room: Room): Promise { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); - const filter = new Filter(client.credentials.userId); + const filter = new Filter(client.getSafeUserId()); filter.setDefinition({ room: { timeline: { @@ -163,7 +163,7 @@ class FilePanel extends React.Component { direction: Direction, limit: number, ): Promise => { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); const eventIndex = EventIndexPeg.get(); const roomId = this.props.roomId; @@ -185,7 +185,7 @@ class FilePanel extends React.Component { }; public async updateTimelineSet(roomId: string): Promise { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); const room = client.getRoom(roomId); const eventIndex = EventIndexPeg.get(); @@ -221,7 +221,7 @@ class FilePanel extends React.Component { } public render(): React.ReactNode { - if (MatrixClientPeg.get().isGuest()) { + if (MatrixClientPeg.safeGet().isGuest()) { return (
@@ -256,7 +256,7 @@ class FilePanel extends React.Component {
); - const isRoomEncrypted = this.noRoom ? false : MatrixClientPeg.get().isRoomEncrypted(this.props.roomId); + const isRoomEncrypted = this.noRoom ? false : MatrixClientPeg.safeGet().isRoomEncrypted(this.props.roomId); if (this.state.timelineSet) { return ( diff --git a/src/components/structures/LegacyCallEventGrouper.ts b/src/components/structures/LegacyCallEventGrouper.ts index c87f08bfff..467b579410 100644 --- a/src/components/structures/LegacyCallEventGrouper.ts +++ b/src/components/structures/LegacyCallEventGrouper.ts @@ -129,7 +129,7 @@ export default class LegacyCallEventGrouper extends EventEmitter { public get callWasMissed(): boolean { return ( this.state === CallState.Ended && - ![...this.events].some((event) => event.sender?.userId === MatrixClientPeg.get().getUserId()) + ![...this.events].some((event) => event.sender?.userId === MatrixClientPeg.safeGet().getUserId()) ); } diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 6a03bc7aed..829a337256 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -32,6 +32,7 @@ import { throttle } from "lodash"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; import { RoomType } from "matrix-js-sdk/src/@types/event"; import { DecryptionError } from "matrix-js-sdk/src/crypto/algorithms"; +import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup"; // focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by various components import "focus-visible"; @@ -355,7 +356,7 @@ export default class MatrixChat extends React.PureComponent { } private async postLoginSetup(): Promise { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); const cryptoEnabled = cli.isCryptoEnabled(); if (!cryptoEnabled) { this.onLoggedIn(); @@ -574,11 +575,11 @@ export default class MatrixChat extends React.PureComponent { if (payload.event_type === "m.identity_server") { const fullUrl = payload.event_content ? payload.event_content["base_url"] : null; if (!fullUrl) { - MatrixClientPeg.get().setIdentityServerUrl(undefined); + MatrixClientPeg.safeGet().setIdentityServerUrl(undefined); localStorage.removeItem("mx_is_access_token"); localStorage.removeItem("mx_is_url"); } else { - MatrixClientPeg.get().setIdentityServerUrl(fullUrl); + MatrixClientPeg.safeGet().setIdentityServerUrl(fullUrl); localStorage.removeItem("mx_is_access_token"); // clear token localStorage.setItem("mx_is_url", fullUrl); // XXX: Do we still need this? } @@ -625,7 +626,7 @@ export default class MatrixChat extends React.PureComponent { this.notifyNewScreen("forgot_password"); break; case "start_chat": - createRoom(MatrixClientPeg.get(), { + createRoom(MatrixClientPeg.safeGet(), { dmUserId: payload.user_id, }); break; @@ -647,7 +648,7 @@ export default class MatrixChat extends React.PureComponent { // FIXME: controller shouldn't be loading a view :( const modal = Modal.createDialog(Spinner, undefined, "mx_Dialog_spinner"); - MatrixClientPeg.get() + MatrixClientPeg.safeGet() .leave(payload.room_id) .then( () => { @@ -755,7 +756,7 @@ export default class MatrixChat extends React.PureComponent { this.viewSomethingBehindModal(); break; case "view_invite": { - const room = MatrixClientPeg.get().getRoom(payload.roomId); + const room = MatrixClientPeg.safeGet().getRoom(payload.roomId); if (room?.isSpaceRoom()) { showSpaceInvite(room); } else { @@ -794,7 +795,7 @@ export default class MatrixChat extends React.PureComponent { Modal.createDialog(DialPadModal, {}, "mx_Dialog_dialPadWrapper"); break; case Action.OnLoggedIn: - this.stores.client = MatrixClientPeg.get(); + this.stores.client = MatrixClientPeg.safeGet(); if ( // Skip this handling for token login as that always calls onLoggedIn itself !this.tokenLogin && @@ -935,7 +936,7 @@ export default class MatrixChat extends React.PureComponent { } let presentedId = roomInfo.room_alias || roomInfo.room_id!; - const room = MatrixClientPeg.get().getRoom(roomInfo.room_id); + const room = MatrixClientPeg.safeGet().getRoom(roomInfo.room_id); if (room) { // Not all timeline events are decrypted ahead of time anymore // Only the critical ones for a typical UI are @@ -1062,14 +1063,14 @@ export default class MatrixChat extends React.PureComponent { const [shouldCreate, opts] = await modal.finished; if (shouldCreate) { - createRoom(MatrixClientPeg.get(), opts!); + createRoom(MatrixClientPeg.safeGet(), opts!); } } private chatCreateOrReuse(userId: string): void { const snakedConfig = new SnakedObject(this.props.config); // Use a deferred action to reshow the dialog once the user has registered - if (MatrixClientPeg.get().isGuest()) { + if (MatrixClientPeg.safeGet().isGuest()) { // No point in making 2 DMs with welcome bot. This assumes view_set_mxid will // result in a new DM with the welcome user. if (userId !== snakedConfig.get("welcome_user_id")) { @@ -1098,7 +1099,7 @@ export default class MatrixChat extends React.PureComponent { // TODO: Immutable DMs replaces this - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); const dmRoom = findDMForUser(client, userId); if (dmRoom) { @@ -1116,7 +1117,7 @@ export default class MatrixChat extends React.PureComponent { } private leaveRoomWarnings(roomId: string): JSX.Element[] { - const roomToLeave = MatrixClientPeg.get().getRoom(roomId); + const roomToLeave = MatrixClientPeg.safeGet().getRoom(roomId); const isSpace = roomToLeave?.isSpaceRoom(); // Show a warning if there are additional complications. const warnings: JSX.Element[] = []; @@ -1154,7 +1155,7 @@ export default class MatrixChat extends React.PureComponent { } private leaveRoom(roomId: string): void { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); const roomToLeave = cli.getRoom(roomId); const warnings = this.leaveRoomWarnings(roomId); @@ -1188,8 +1189,8 @@ export default class MatrixChat extends React.PureComponent { } private forgetRoom(roomId: string): void { - const room = MatrixClientPeg.get().getRoom(roomId); - MatrixClientPeg.get() + const room = MatrixClientPeg.safeGet().getRoom(roomId); + MatrixClientPeg.safeGet() .forget(roomId) .then(() => { // Switch to home page if we're currently viewing the forgotten room @@ -1212,7 +1213,7 @@ export default class MatrixChat extends React.PureComponent { } private async copyRoom(roomId: string): Promise { - const roomLink = makeRoomPermalink(MatrixClientPeg.get(), roomId); + const roomLink = makeRoomPermalink(MatrixClientPeg.safeGet(), roomId); const success = await copyPlaintext(roomLink); if (!success) { Modal.createDialog(ErrorDialog, { @@ -1246,7 +1247,7 @@ export default class MatrixChat extends React.PureComponent { const welcomeUserRooms = DMRoomMap.shared().getDMRoomsForUserId(welcomeUserId); if (welcomeUserRooms.length === 0) { - const roomId = await createRoom(MatrixClientPeg.get(), { + const roomId = await createRoom(MatrixClientPeg.safeGet(), { dmUserId: snakedConfig.get("welcome_user_id"), // Only view the welcome user if we're NOT looking at a room andView: !this.state.currentRoomId, @@ -1262,11 +1263,11 @@ export default class MatrixChat extends React.PureComponent { // the saved sync to be loaded). const saveWelcomeUser = (ev: MatrixEvent): void => { if (ev.getType() === EventType.Direct && ev.getContent()[welcomeUserId]) { - MatrixClientPeg.get().store.save(true); - MatrixClientPeg.get().removeListener(ClientEvent.AccountData, saveWelcomeUser); + MatrixClientPeg.safeGet().store.save(true); + MatrixClientPeg.safeGet().removeListener(ClientEvent.AccountData, saveWelcomeUser); } }; - MatrixClientPeg.get().on(ClientEvent.AccountData, saveWelcomeUser); + MatrixClientPeg.safeGet().on(ClientEvent.AccountData, saveWelcomeUser); return roomId; } @@ -1413,7 +1414,7 @@ export default class MatrixChat extends React.PureComponent { // Before defaulting to directory, show the last viewed room this.viewLastRoom(); } else { - if (MatrixClientPeg.get().isGuest()) { + if (MatrixClientPeg.safeGet().isGuest()) { dis.dispatch({ action: "view_welcome_page" }); } else { dis.dispatch({ action: Action.ViewHomePage }); @@ -1468,7 +1469,7 @@ export default class MatrixChat extends React.PureComponent { // to do the first sync this.firstSyncComplete = false; this.firstSyncPromise = defer(); - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); // Allow the JS SDK to reap timeline events. This reduces the amount of // memory consumed as the JS SDK stores multiple distinct copies of room @@ -1588,7 +1589,7 @@ export default class MatrixChat extends React.PureComponent { cli.on(MatrixEventEvent.Decrypted, (e, err) => dft.eventDecrypted(e, err as DecryptionError)); cli.on(ClientEvent.Room, (room) => { - if (MatrixClientPeg.get().isCryptoEnabled()) { + if (cli.isCryptoEnabled()) { const blacklistEnabled = SettingsStore.getValueAt( SettingLevel.ROOM_DEVICE, "blacklistUnverifiedDevices", @@ -1618,15 +1619,15 @@ export default class MatrixChat extends React.PureComponent { } }); cli.on(CryptoEvent.KeyBackupFailed, async (errcode): Promise => { - let haveNewVersion; - let newVersionInfo; + let haveNewVersion: boolean | undefined; + let newVersionInfo: IKeyBackupInfo | null = null; // if key backup is still enabled, there must be a new backup in place - if (MatrixClientPeg.get().getKeyBackupEnabled()) { + if (cli.getKeyBackupEnabled()) { haveNewVersion = true; } else { // otherwise check the server to see if there's a new one try { - newVersionInfo = await MatrixClientPeg.get().getKeyBackupVersion(); + newVersionInfo = await cli.getKeyBackupVersion(); if (newVersionInfo !== null) haveNewVersion = true; } catch (e) { logger.error("Saw key backup error but failed to check backup version!", e); @@ -1639,7 +1640,7 @@ export default class MatrixChat extends React.PureComponent { import( "../../async-components/views/dialogs/security/NewRecoveryMethodDialog" ) as unknown as Promise, - { newVersionInfo }, + { newVersionInfo: newVersionInfo! }, ); } else { Modal.createDialogAsync( @@ -1686,7 +1687,7 @@ export default class MatrixChat extends React.PureComponent { * @private */ private onClientStarted(): void { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); if (cli.isCryptoEnabled()) { const blacklistEnabled = SettingsStore.getValueAt(SettingLevel.DEVICE, "blacklistUnverifiedDevices"); @@ -1734,7 +1735,7 @@ export default class MatrixChat extends React.PureComponent { params: params, }); } else if (screen === "soft_logout") { - if (cli.getUserId() && !Lifecycle.isSoftLogout()) { + if (!!cli?.getUserId() && !Lifecycle.isSoftLogout()) { // Logged in - visit a room this.viewLastRoom(); } else { @@ -2057,7 +2058,7 @@ export default class MatrixChat extends React.PureComponent { {...this.props} {...this.state} ref={this.loggedInView} - matrixClient={MatrixClientPeg.get()} + matrixClient={MatrixClientPeg.safeGet()} onRegistered={this.onRegistered} currentRoomId={this.state.currentRoomId} /> diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index f73bea5aa3..687ab1f56a 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -473,7 +473,7 @@ export default class MessagePanel extends React.Component { } } - if (MatrixClientPeg.get().isUserIgnored(mxEv.getSender()!)) { + if (MatrixClientPeg.safeGet().isUserIgnored(mxEv.getSender()!)) { return false; // ignored = no show (only happens if the ignore happens after an event was received) } @@ -743,7 +743,7 @@ export default class MessagePanel extends React.Component { lastInSection = willWantDateSeparator || mxEv.getSender() !== nextEv.getSender() || - getEventDisplayInfo(MatrixClientPeg.get(), nextEv, this.showHiddenEvents).isInfoMessage || + getEventDisplayInfo(MatrixClientPeg.safeGet(), nextEv, this.showHiddenEvents).isInfoMessage || !shouldFormContinuation(mxEv, nextEv, this.showHiddenEvents, this.context.timelineRenderingType); } @@ -779,7 +779,7 @@ export default class MessagePanel extends React.Component { // We only want to consider "last successful" if the event is sent by us, otherwise of course // it's successful: we received it. - isLastSuccessful = isLastSuccessful && mxEv.getSender() === MatrixClientPeg.get().getUserId(); + isLastSuccessful = isLastSuccessful && mxEv.getSender() === MatrixClientPeg.safeGet().getUserId(); const callEventGrouper = this.props.callEventGroupers.get(mxEv.getContent().call_id); // use txnId as key if available so that we don't remount during sending @@ -833,7 +833,7 @@ export default class MessagePanel extends React.Component { // Get a list of read receipts that should be shown next to this event // Receipts are objects which have a 'userId', 'roomMember' and 'ts'. private getReadReceiptsForEvent(event: MatrixEvent): IReadReceiptProps[] | null { - const myUserId = MatrixClientPeg.get().credentials.userId; + const myUserId = MatrixClientPeg.safeGet().credentials.userId; // get list of read receipts, sorted most recent first const { room } = this.props; @@ -856,7 +856,7 @@ export default class MessagePanel extends React.Component { if (!r.userId || !isSupportedReceiptType(r.type) || r.userId === myUserId) { return; // ignore non-read receipts and receipts from self. } - if (MatrixClientPeg.get().isUserIgnored(r.userId)) { + if (MatrixClientPeg.safeGet().isUserIgnored(r.userId)) { return; // ignore ignored users } const member = room.getMember(r.userId); @@ -1301,7 +1301,7 @@ class MainGrouper extends BaseGrouper { public add({ event: ev, shouldShow }: EventAndShouldShow): void { if (ev.getType() === EventType.RoomMember) { // We can ignore any events that don't actually have a message to display - if (!hasText(ev, MatrixClientPeg.get(), this.panel.showHiddenEvents)) return; + if (!hasText(ev, MatrixClientPeg.safeGet(), this.panel.showHiddenEvents)) return; } this.readMarker = this.readMarker || this.panel.readMarkerForEvent(ev.getId()!, ev === this.lastShownEvent); if (!this.panel.showHiddenEvents && !shouldShow) { diff --git a/src/components/structures/NotificationPanel.tsx b/src/components/structures/NotificationPanel.tsx index cb580dd134..03ca356df3 100644 --- a/src/components/structures/NotificationPanel.tsx +++ b/src/components/structures/NotificationPanel.tsx @@ -63,8 +63,8 @@ export default class NotificationPanel extends React.PureComponent ); - let content; - const timelineSet = MatrixClientPeg.get().getNotifTimelineSet(); + let content: JSX.Element; + const timelineSet = MatrixClientPeg.safeGet().getNotifTimelineSet(); if (timelineSet) { // wrap a TimelinePanel with the jump-to-event bits turned off. content = ( diff --git a/src/components/structures/PipContainer.tsx b/src/components/structures/PipContainer.tsx index 6d761f9c79..6f249fd677 100644 --- a/src/components/structures/PipContainer.tsx +++ b/src/components/structures/PipContainer.tsx @@ -139,8 +139,8 @@ class PipContainerInner extends React.Component { LegacyCallHandler.instance.addListener(LegacyCallHandlerEvent.CallChangeRoom, this.updateCalls); LegacyCallHandler.instance.addListener(LegacyCallHandlerEvent.CallState, this.updateCalls); SdkContextClass.instance.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdate); - MatrixClientPeg.get().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); - const room = MatrixClientPeg.get()?.getRoom(this.state.viewedRoomId); + MatrixClientPeg.safeGet().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); + const room = MatrixClientPeg.safeGet().getRoom(this.state.viewedRoomId); if (room) { WidgetLayoutStore.instance.on(WidgetLayoutStore.emissionForRoom(room), this.updateCalls); } @@ -239,7 +239,7 @@ class PipContainerInner extends React.Component { let notDocked = false; // Sanity check the room - the widget may have been destroyed between render cycles, and // thus no room is associated anymore. - if (persistentWidgetId && persistentRoomId && MatrixClientPeg.get().getRoom(persistentRoomId)) { + if (persistentWidgetId && persistentRoomId && MatrixClientPeg.safeGet().getRoom(persistentRoomId)) { notDocked = !ActiveWidgetStore.instance.isDocked(persistentWidgetId, persistentRoomId); fromAnotherRoom = this.state.viewedRoomId !== persistentRoomId; } @@ -318,7 +318,7 @@ class PipContainerInner extends React.Component { pipContent.push(({ onStartMoving }) => ( { Array.from(dataTransfer.files), roomId, this.threadRelation, - MatrixClientPeg.get(), + MatrixClientPeg.safeGet(), TimelineRenderingType.Thread, ); } else { diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index 5b5e0365ef..103e6d844b 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -291,7 +291,7 @@ class TimelinePanel extends React.Component { readMarkerEventId: this.initialReadMarkerId, backPaginating: false, forwardPaginating: false, - clientSyncState: MatrixClientPeg.get().getSyncState(), + clientSyncState: MatrixClientPeg.safeGet().getSyncState(), isTwelveHour: SettingsStore.getValue("showTwelveHourTimestamps"), alwaysShowTimestamps: SettingsStore.getValue("alwaysShowTimestamps"), readMarkerInViewThresholdMs: SettingsStore.getValue("readMarkerInViewThresholdMs"), @@ -299,7 +299,7 @@ class TimelinePanel extends React.Component { }; this.dispatcherRef = dis.register(this.onAction); - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); cli.on(RoomEvent.Timeline, this.onRoomTimeline); cli.on(RoomEvent.TimelineReset, this.onRoomTimelineReset); cli.on(RoomEvent.Redaction, this.onRoomRedaction); @@ -788,7 +788,7 @@ class TimelinePanel extends React.Component { // read-marker when a remote echo of an event we have just sent takes // more than the timeout on userActiveRecently. // - const myUserId = MatrixClientPeg.get().credentials.userId; + const myUserId = MatrixClientPeg.safeGet().credentials.userId; callRMUpdated = false; if (ev.getSender() !== myUserId && !UserActivity.sharedInstance().userActiveRecently()) { updatedState.readMarkerVisible = true; @@ -881,7 +881,7 @@ class TimelinePanel extends React.Component { if (!this.hasTimelineSetFor(member.roomId)) return; // ignore events for other users - if (member.userId != MatrixClientPeg.get().credentials?.userId) return; + if (member.userId != MatrixClientPeg.safeGet().credentials?.userId) return; // We could skip an update if the power level change didn't cross the // threshold for `VISIBILITY_CHANGE_TYPE`. @@ -1276,7 +1276,7 @@ class TimelinePanel extends React.Component { } // now think about advancing it - const myUserId = MatrixClientPeg.get().credentials.userId; + const myUserId = MatrixClientPeg.safeGet().credentials.userId; for (i++; i < events.length; i++) { const ev = events[i]; if (ev.getSender() !== myUserId) { @@ -1557,7 +1557,7 @@ class TimelinePanel extends React.Component { * @param {boolean?} scrollIntoView whether to scroll the event into view. */ private loadTimeline(eventId?: string, pixelOffset?: number, offsetBase?: number, scrollIntoView = true): void { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); this.timelineWindow = new TimelineWindow(cli, this.props.timelineSet, { windowLimit: this.props.timelineCap }); this.overlayTimelineWindow = this.props.overlayTimelineSet ? new TimelineWindow(cli, this.props.overlayTimelineSet, { windowLimit: this.props.timelineCap }) @@ -1748,7 +1748,7 @@ class TimelinePanel extends React.Component { arrayFastClone(events) .reverse() .forEach((event) => { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); client.decryptEventIfNeeded(event); }); @@ -1796,7 +1796,7 @@ class TimelinePanel extends React.Component { * such events were found, then it returns 0. */ private checkForPreJoinUISI(events: MatrixEvent[]): number { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); const room = this.props.timelineSet.room; const isThreadTimeline = [TimelineRenderingType.Thread, TimelineRenderingType.ThreadsList].includes( @@ -1921,7 +1921,7 @@ class TimelinePanel extends React.Component { const messagePanelNode = ReactDOM.findDOMNode(messagePanel) as Element; if (!messagePanelNode) return null; // sometimes this happens for fresh rooms/post-sync const wrapperRect = messagePanelNode.getBoundingClientRect(); - const myUserId = MatrixClientPeg.get().credentials.userId; + const myUserId = MatrixClientPeg.safeGet().credentials.userId; const isNodeInView = (node?: HTMLElement): boolean => { if (node) { @@ -2121,7 +2121,7 @@ class TimelinePanel extends React.Component { canBackPaginate={this.state.canBackPaginate && this.state.firstVisibleEventIndex === 0} showUrlPreview={this.props.showUrlPreview} showReadReceipts={this.props.showReadReceipts} - ourUserId={MatrixClientPeg.get().getSafeUserId()} + ourUserId={MatrixClientPeg.safeGet().getSafeUserId()} stickyBottom={stickyBottom} onScroll={this.onMessageListScroll} onFillRequest={this.onMessageListFillRequest} diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index 99325da99b..2968c9eff3 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -291,7 +291,7 @@ export default class UserMenu extends React.Component { if (!this.state.contextMenuPosition) return null; let topSection: JSX.Element | undefined; - if (MatrixClientPeg.get().isGuest()) { + if (MatrixClientPeg.safeGet().isGuest()) { topSection = (
{_t( @@ -372,7 +372,7 @@ export default class UserMenu extends React.Component { ); - if (MatrixClientPeg.get().isGuest()) { + if (MatrixClientPeg.safeGet().isGuest()) { primaryOptionList = ( {homeButton} @@ -399,7 +399,7 @@ export default class UserMenu extends React.Component { {UserIdentifierCustomisations.getDisplayUserIdentifier( - MatrixClientPeg.get().getSafeUserId(), + MatrixClientPeg.safeGet().getSafeUserId(), { withDisplayName: true, }, @@ -428,7 +428,7 @@ export default class UserMenu extends React.Component { public render(): React.ReactNode { const avatarSize = 32; // should match border-radius of the avatar - const userId = MatrixClientPeg.get().getSafeUserId(); + const userId = MatrixClientPeg.safeGet().getSafeUserId(); const displayName = OwnProfileStore.instance.displayName || userId; const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize); diff --git a/src/components/structures/ViewSource.tsx b/src/components/structures/ViewSource.tsx index a4e10e12e0..d1e60ad12f 100644 --- a/src/components/structures/ViewSource.tsx +++ b/src/components/structures/ViewSource.tsx @@ -142,7 +142,7 @@ export default class ViewSource extends React.Component { } private canSendStateEvent(mxEvent: MatrixEvent): boolean { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); const room = cli.getRoom(mxEvent.getRoomId()); return !!room?.currentState.mayClientSendStateEvent(mxEvent.getType(), cli); } @@ -155,7 +155,7 @@ export default class ViewSource extends React.Component { const eventId = mxEvent.getId()!; const canEdit = mxEvent.isState() ? this.canSendStateEvent(mxEvent) - : canEditContent(MatrixClientPeg.get(), this.props.mxEvent); + : canEditContent(MatrixClientPeg.safeGet(), this.props.mxEvent); return (
diff --git a/src/components/structures/auth/Registration.tsx b/src/components/structures/auth/Registration.tsx index d8fd848320..7526930152 100644 --- a/src/components/structures/auth/Registration.tsx +++ b/src/components/structures/auth/Registration.tsx @@ -420,7 +420,7 @@ export default class Registration extends React.Component { if (!this.props.brand) { return Promise.resolve(); } - const matrixClient = MatrixClientPeg.get(); + const matrixClient = MatrixClientPeg.safeGet(); return matrixClient.getPushers().then( (resp) => { const pushers = resp.pushers; diff --git a/src/components/structures/auth/SetupEncryptionBody.tsx b/src/components/structures/auth/SetupEncryptionBody.tsx index 15d058b4da..7afa4f321b 100644 --- a/src/components/structures/auth/SetupEncryptionBody.tsx +++ b/src/components/structures/auth/SetupEncryptionBody.tsx @@ -87,7 +87,7 @@ export default class SetupEncryptionBody extends React.Component }; private onVerifyClick = (): void => { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); const userId = cli.getSafeUserId(); const requestPromise = cli.requestVerification(userId); @@ -142,7 +142,7 @@ export default class SetupEncryptionBody extends React.Component }; public render(): React.ReactNode { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); const { phase, lostKeys } = this.state; if (this.state.verificationRequest && cli.getUser(this.state.verificationRequest.otherUserId)) { diff --git a/src/components/structures/auth/SoftLogout.tsx b/src/components/structures/auth/SoftLogout.tsx index f8a058fc7b..932cdef475 100644 --- a/src/components/structures/auth/SoftLogout.tsx +++ b/src/components/structures/auth/SoftLogout.tsx @@ -94,7 +94,7 @@ export default class SoftLogout extends React.Component { this.initLogin(); - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); if (cli.isCryptoEnabled()) { cli.countSessionsNeedingBackup().then((remaining) => { this.setState({ keyBackupNeeded: remaining > 0 }); @@ -124,7 +124,7 @@ export default class SoftLogout extends React.Component { // Note: we don't use the existing Login class because it is heavily flow-based. We don't // care about login flows here, unless it is the single flow we support. - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); const flows = (await client.loginFlows()).flows; const loginViews = flows.map((f) => STATIC_FLOWS_TO_VIEWS[f.type]); @@ -148,16 +148,17 @@ export default class SoftLogout extends React.Component { this.setState({ busy: true }); - const hsUrl = MatrixClientPeg.get().getHomeserverUrl(); - const isUrl = MatrixClientPeg.get().getIdentityServerUrl(); + const cli = MatrixClientPeg.safeGet(); + const hsUrl = cli.getHomeserverUrl(); + const isUrl = cli.getIdentityServerUrl(); const loginType = "m.login.password"; const loginParams = { identifier: { type: "m.id.user", - user: MatrixClientPeg.get().getUserId(), + user: cli.getUserId(), }, password: this.state.password, - device_id: MatrixClientPeg.get().getDeviceId() ?? undefined, + device_id: cli.getDeviceId() ?? undefined, }; let credentials: IMatrixClientCreds; @@ -196,11 +197,11 @@ export default class SoftLogout extends React.Component { return; } - const isUrl = localStorage.getItem(SSO_ID_SERVER_URL_KEY) || MatrixClientPeg.get().getIdentityServerUrl(); + const isUrl = localStorage.getItem(SSO_ID_SERVER_URL_KEY) || MatrixClientPeg.safeGet().getIdentityServerUrl(); const loginType = "m.login.token"; const loginParams = { token: this.props.realQueryParams["loginToken"], - device_id: MatrixClientPeg.get().getDeviceId() ?? undefined, + device_id: MatrixClientPeg.safeGet().getDeviceId() ?? undefined, }; let credentials: IMatrixClientCreds; @@ -262,7 +263,7 @@ export default class SoftLogout extends React.Component {
{introText ?

{introText}

: null} void] => { const [rooms, setRooms] = useState(() => { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); const recents = SettingsStore.getValue("SpotlightSearch.recentSearches", null); return filterBoolean(recents.map((r) => cli.getRoom(r))); }); diff --git a/src/hooks/usePermalinkEvent.ts b/src/hooks/usePermalinkEvent.ts index 1cb2b05e3b..e72592a6e5 100644 --- a/src/hooks/usePermalinkEvent.ts +++ b/src/hooks/usePermalinkEvent.ts @@ -74,7 +74,7 @@ export const usePermalinkEvent = ( const fetchRoomEvent = async (): Promise => { try { - const eventData = await MatrixClientPeg.get().fetchRoomEvent( + const eventData = await MatrixClientPeg.safeGet().fetchRoomEvent( parseResult.roomIdOrAlias!, parseResult.eventId!, ); diff --git a/src/hooks/usePermalinkTargetRoom.ts b/src/hooks/usePermalinkTargetRoom.ts index 826f995bbe..d6d1dd0959 100644 --- a/src/hooks/usePermalinkTargetRoom.ts +++ b/src/hooks/usePermalinkTargetRoom.ts @@ -59,7 +59,7 @@ const determineInitialRoom = ( * @returns Room if found, else null. */ const findRoom = (roomIdOrAlias: string): Room | null => { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); return roomIdOrAlias[0] === "#" ? client.getRooms().find((r) => { diff --git a/src/hooks/useProfileInfo.ts b/src/hooks/useProfileInfo.ts index 6110c6732c..d85012b87e 100644 --- a/src/hooks/useProfileInfo.ts +++ b/src/hooks/useProfileInfo.ts @@ -51,7 +51,7 @@ export const useProfileInfo = (): { setLoading(true); try { - const result = await MatrixClientPeg.get().getProfileInfo(term); + const result = await MatrixClientPeg.safeGet().getProfileInfo(term); updateResult(term, { user_id: term, avatar_url: result.avatar_url, diff --git a/src/hooks/usePublicRoomDirectory.ts b/src/hooks/usePublicRoomDirectory.ts index 9572862d00..d3c6b00c0b 100644 --- a/src/hooks/usePublicRoomDirectory.ts +++ b/src/hooks/usePublicRoomDirectory.ts @@ -72,7 +72,7 @@ export const usePublicRoomDirectory = (): { } else if (thirdParty) { setProtocols(thirdParty); } else { - const response = await MatrixClientPeg.get().getThirdpartyProtocols(); + const response = await MatrixClientPeg.safeGet().getThirdpartyProtocols(); thirdParty = response; setProtocols(response); } @@ -105,7 +105,7 @@ export const usePublicRoomDirectory = (): { generic_search_term: query, room_types: roomTypes && - (await MatrixClientPeg.get().doesServerSupportUnstableFeature("org.matrix.msc3827.stable")) + (await MatrixClientPeg.safeGet().doesServerSupportUnstableFeature("org.matrix.msc3827.stable")) ? Array.from(roomTypes) : undefined, }; @@ -114,7 +114,7 @@ export const usePublicRoomDirectory = (): { updateQuery(opts); try { setLoading(true); - const { chunk } = await MatrixClientPeg.get().publicRooms(opts); + const { chunk } = await MatrixClientPeg.safeGet().publicRooms(opts); updateResult(opts, showNsfwPublicRooms ? chunk : chunk.filter(cheapNsfwFilter)); return true; } catch (e) { diff --git a/src/hooks/useSlidingSyncRoomSearch.ts b/src/hooks/useSlidingSyncRoomSearch.ts index c4dfbbf409..5cf1f6bea8 100644 --- a/src/hooks/useSlidingSyncRoomSearch.ts +++ b/src/hooks/useSlidingSyncRoomSearch.ts @@ -62,7 +62,7 @@ export const useSlidingSyncRoomSearch = (): { let i = 0; while (roomIndexToRoomId[i]) { const roomId = roomIndexToRoomId[i]; - const room = MatrixClientPeg.get().getRoom(roomId); + const room = MatrixClientPeg.safeGet().getRoom(roomId); if (room) { rooms.push(room); } diff --git a/src/hooks/useSpaceResults.ts b/src/hooks/useSpaceResults.ts index 35a4627b05..ebeed76239 100644 --- a/src/hooks/useSpaceResults.ts +++ b/src/hooks/useSpaceResults.ts @@ -54,7 +54,7 @@ export const useSpaceResults = (space: Room | undefined, query: string): [IHiera const lcQuery = trimmedQuery.toLowerCase(); const normalizedQuery = normalize(trimmedQuery); - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); return rooms?.filter((r) => { return ( r.room_type !== RoomType.Space && diff --git a/src/hooks/useUserDirectory.ts b/src/hooks/useUserDirectory.ts index d775994e3a..9dfcbc05ad 100644 --- a/src/hooks/useUserDirectory.ts +++ b/src/hooks/useUserDirectory.ts @@ -49,7 +49,7 @@ export const useUserDirectory = (): { try { setLoading(true); - const { results } = await MatrixClientPeg.get().searchUserDirectory(opts); + const { results } = await MatrixClientPeg.safeGet().searchUserDirectory(opts); updateResult( opts, results.map((user) => new DirectoryMember(user)), diff --git a/src/stores/ActiveWidgetStore.ts b/src/stores/ActiveWidgetStore.ts index 90e349e668..edc4632486 100644 --- a/src/stores/ActiveWidgetStore.ts +++ b/src/stores/ActiveWidgetStore.ts @@ -51,7 +51,7 @@ export default class ActiveWidgetStore extends EventEmitter { } public start(): void { - MatrixClientPeg.get().on(RoomStateEvent.Events, this.onRoomStateEvents); + MatrixClientPeg.safeGet().on(RoomStateEvent.Events, this.onRoomStateEvents); } public stop(): void { diff --git a/src/stores/OwnProfileStore.ts b/src/stores/OwnProfileStore.ts index db8960307b..bae9534846 100644 --- a/src/stores/OwnProfileStore.ts +++ b/src/stores/OwnProfileStore.ts @@ -159,7 +159,7 @@ export class OwnProfileStore extends AsyncStoreWithClient { ); private onStateEvents = async (ev: MatrixEvent): Promise => { - const myUserId = MatrixClientPeg.get().getUserId(); + const myUserId = MatrixClientPeg.safeGet().getUserId(); if (ev.getType() === EventType.RoomMember && ev.getSender() === myUserId && ev.getStateKey() === myUserId) { await this.onProfileUpdate(); } diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index 2f8c80023f..1fa116094d 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -306,7 +306,7 @@ export class RoomViewStore extends EventEmitter { this.setState({ shouldPeek: false }); } - awaitRoomDownSync(MatrixClientPeg.get(), payload.roomId).then((room) => { + awaitRoomDownSync(MatrixClientPeg.safeGet(), payload.roomId).then((room) => { const numMembers = room.getJoinedMemberCount(); const roomSize = numMembers > 1000 @@ -361,7 +361,7 @@ export class RoomViewStore extends EventEmitter { private async viewRoom(payload: ViewRoomPayload): Promise { if (payload.room_id) { - const room = MatrixClientPeg.get().getRoom(payload.room_id); + const room = MatrixClientPeg.safeGet().getRoom(payload.room_id); if (payload.metricsTrigger !== null && payload.room_id !== this.state.roomId) { let activeSpace: ViewRoomEvent["activeSpace"]; @@ -488,7 +488,7 @@ export class RoomViewStore extends EventEmitter { viewingCall: payload.view_call ?? false, }); try { - const result = await MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias); + const result = await MatrixClientPeg.safeGet().getRoomIdForAlias(payload.room_alias); storeRoomAliasInCache(payload.room_alias, result.room_id); roomId = result.room_id; } catch (err) { @@ -531,12 +531,12 @@ export class RoomViewStore extends EventEmitter { joining: true, }); - const cli = MatrixClientPeg.get(); // take a copy of roomAlias & roomId as they may change by the time the join is complete const { roomAlias, roomId = payload.roomId } = this.state; const address = roomAlias || roomId!; const viaServers = this.state.viaServers || []; try { + const cli = MatrixClientPeg.safeGet(); await retry( () => cli.joinRoom(address, { @@ -568,7 +568,7 @@ export class RoomViewStore extends EventEmitter { } private getInvitingUserId(roomId: string): string | undefined { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); const room = cli.getRoom(roomId); if (room?.getMyMembership() === "invite") { const myMember = room.getMember(cli.getSafeUserId()); @@ -596,7 +596,7 @@ export class RoomViewStore extends EventEmitter { // provide a better error message for invites if (invitingUserId) { // if the inviting user is on the same HS, there can only be one cause: they left. - if (invitingUserId.endsWith(`:${MatrixClientPeg.get().getDomain()}`)) { + if (invitingUserId.endsWith(`:${MatrixClientPeg.safeGet().getDomain()}`)) { description = _t("The person who invited you has already left."); } else { description = _t("The person who invited you has already left, or their server is offline."); diff --git a/src/stores/SetupEncryptionStore.ts b/src/stores/SetupEncryptionStore.ts index 31910e46be..3c47d6b266 100644 --- a/src/stores/SetupEncryptionStore.ts +++ b/src/stores/SetupEncryptionStore.ts @@ -62,7 +62,7 @@ export class SetupEncryptionStore extends EventEmitter { this.started = true; this.phase = Phase.Loading; - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); cli.on(CryptoEvent.VerificationRequest, this.onVerificationRequest); cli.on(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); @@ -83,15 +83,17 @@ export class SetupEncryptionStore extends EventEmitter { } this.started = false; this.verificationRequest?.off(VerificationRequestEvent.Change, this.onVerificationRequestChange); - if (MatrixClientPeg.get()) { - MatrixClientPeg.get().removeListener(CryptoEvent.VerificationRequest, this.onVerificationRequest); - MatrixClientPeg.get().removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); + + const cli = MatrixClientPeg.get(); + if (!!cli) { + cli.removeListener(CryptoEvent.VerificationRequest, this.onVerificationRequest); + cli.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserTrustStatusChanged); } } public async fetchKeyInfo(): Promise { if (!this.started) return; // bail if we were stopped - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); const keys = await cli.isSecretStored("m.cross_signing.master"); if (keys === null || Object.keys(keys).length === 0) { this.keyId = null; @@ -120,8 +122,8 @@ export class SetupEncryptionStore extends EventEmitter { public async usePassPhrase(): Promise { this.phase = Phase.Busy; this.emit("update"); - const cli = MatrixClientPeg.get(); try { + const cli = MatrixClientPeg.safeGet(); const backupInfo = await cli.getKeyBackupVersion(); this.backupInfo = backupInfo; this.emit("update"); @@ -161,8 +163,8 @@ export class SetupEncryptionStore extends EventEmitter { } private onUserTrustStatusChanged = async (userId: string): Promise => { - if (userId !== MatrixClientPeg.get().getUserId()) return; - const publicKeysTrusted = await MatrixClientPeg.get().getCrypto()?.getCrossSigningKeyId(); + if (userId !== MatrixClientPeg.safeGet().getSafeUserId()) return; + const publicKeysTrusted = await MatrixClientPeg.safeGet().getCrypto()?.getCrossSigningKeyId(); if (publicKeysTrusted) { this.phase = Phase.Done; this.emit("update"); @@ -184,7 +186,7 @@ export class SetupEncryptionStore extends EventEmitter { // At this point, the verification has finished, we just need to wait for // cross signing to be ready to use, so wait for the user trust status to // change (or change to DONE if it's already ready). - const publicKeysTrusted = await MatrixClientPeg.get().getCrypto()?.getCrossSigningKeyId(); + const publicKeysTrusted = await MatrixClientPeg.safeGet().getCrypto()?.getCrossSigningKeyId(); this.phase = publicKeysTrusted ? Phase.Done : Phase.Busy; this.emit("update"); } @@ -217,7 +219,7 @@ export class SetupEncryptionStore extends EventEmitter { // secret storage and setting up a new recovery key, then // create new cross-signing keys once that succeeds. await accessSecretStorage(async (): Promise => { - const cli = MatrixClientPeg.get(); + const cli = MatrixClientPeg.safeGet(); await cli.bootstrapCrossSigning({ authUploadDeviceSigningKeys: async (makeRequest): Promise => { const cachedPassword = SdkContextClass.instance.accountPasswordStore.getPassword(); @@ -227,9 +229,9 @@ export class SetupEncryptionStore extends EventEmitter { type: "m.login.password", identifier: { type: "m.id.user", - user: cli.getUserId(), + user: cli.getSafeUserId(), }, - user: cli.getUserId(), + user: cli.getSafeUserId(), password: cachedPassword, }); return; @@ -265,12 +267,12 @@ export class SetupEncryptionStore extends EventEmitter { this.phase = Phase.Finished; this.emit("update"); // async - ask other clients for keys, if necessary - MatrixClientPeg.get().crypto?.cancelAndResendAllOutgoingKeyRequests(); + MatrixClientPeg.safeGet().crypto?.cancelAndResendAllOutgoingKeyRequests(); } private async setActiveVerificationRequest(request: VerificationRequest): Promise { if (!this.started) return; // bail if we were stopped - if (request.otherUserId !== MatrixClientPeg.get().getUserId()) return; + if (request.otherUserId !== MatrixClientPeg.safeGet().getUserId()) return; if (this.verificationRequest) { this.verificationRequest.off(VerificationRequestEvent.Change, this.onVerificationRequestChange); diff --git a/src/stores/notifications/RoomNotificationState.ts b/src/stores/notifications/RoomNotificationState.ts index 3c0447a143..d647f5cd1b 100644 --- a/src/stores/notifications/RoomNotificationState.ts +++ b/src/stores/notifications/RoomNotificationState.ts @@ -59,7 +59,7 @@ export class RoomNotificationState extends NotificationState implements IDestroy }; private handleReadReceipt = (event: MatrixEvent, room: Room): void => { - if (!readReceiptChangeIsFor(event, MatrixClientPeg.get())) return; // not our own - ignore + if (!readReceiptChangeIsFor(event, MatrixClientPeg.safeGet())) return; // not our own - ignore if (room.roomId !== this.room.roomId) return; // not for us - ignore this.updateNotificationState(); }; diff --git a/src/stores/right-panel/RightPanelStore.ts b/src/stores/right-panel/RightPanelStore.ts index 942645b15f..6d827aa171 100644 --- a/src/stores/right-panel/RightPanelStore.ts +++ b/src/stores/right-panel/RightPanelStore.ts @@ -310,7 +310,7 @@ export default class RightPanelStore extends ReadyWatchingStore { // RightPanelPhases.RoomMemberInfo -> needs to be changed to RightPanelPhases.EncryptionPanel if there is a pending verification request const { member } = card.state; const pendingRequest = member - ? pendingVerificationRequestForUser(MatrixClientPeg.get(), member) + ? pendingVerificationRequestForUser(MatrixClientPeg.safeGet(), member) : undefined; if (pendingRequest) { return { @@ -344,7 +344,7 @@ export default class RightPanelStore extends ReadyWatchingStore { if (!this.currentCard?.state) return; const { member } = this.currentCard.state; if (!member) return; - const pendingRequest = pendingVerificationRequestForUser(MatrixClientPeg.get(), member); + const pendingRequest = pendingVerificationRequestForUser(MatrixClientPeg.safeGet(), member); if (pendingRequest) { this.currentCard.state.verificationRequest = pendingRequest; this.emitAndUpdateSettings(); diff --git a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts index e0b7d4bd20..15c579312a 100644 --- a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts +++ b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts @@ -56,7 +56,7 @@ export const sortRooms = (rooms: Room[]): Room[] => { // See https://github.com/vector-im/element-web/issues/14458 let myUserId = ""; if (MatrixClientPeg.get()) { - myUserId = MatrixClientPeg.get().getUserId()!; + myUserId = MatrixClientPeg.get()!.getSafeUserId(); } const tsCache: { [roomId: string]: number } = {}; diff --git a/src/stores/room-list/previews/utils.ts b/src/stores/room-list/previews/utils.ts index ec8ddb28e3..07a561a219 100644 --- a/src/stores/room-list/previews/utils.ts +++ b/src/stores/room-list/previews/utils.ts @@ -20,7 +20,7 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { DefaultTagID, TagID } from "../models"; export function isSelf(event: MatrixEvent): boolean { - const selfUserId = MatrixClientPeg.get().getSafeUserId(); + const selfUserId = MatrixClientPeg.safeGet().getSafeUserId(); if (event.getType() === "m.room.member") { return event.getStateKey() === selfUserId; } @@ -31,7 +31,7 @@ export function shouldPrefixMessagesIn(roomId: string, tagId?: TagID): boolean { if (tagId !== DefaultTagID.DM) return true; // We don't prefix anything in 1:1s - const room = MatrixClientPeg.get().getRoom(roomId); + const room = MatrixClientPeg.safeGet().getRoom(roomId); if (!room) return true; return room.currentState.getJoinedMemberCount() !== 2; } diff --git a/src/stores/widgets/StopGapWidget.ts b/src/stores/widgets/StopGapWidget.ts index 2fc176e6dc..2781612a0c 100644 --- a/src/stores/widgets/StopGapWidget.ts +++ b/src/stores/widgets/StopGapWidget.ts @@ -167,7 +167,7 @@ export class StopGapWidget extends EventEmitter { public constructor(private appTileProps: IAppTileProps) { super(); - this.client = MatrixClientPeg.get(); + this.client = MatrixClientPeg.safeGet(); let app = appTileProps.app; // Backwards compatibility: not all old widgets have a creatorUserId diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts index 9e24126b15..b0fe61deb7 100644 --- a/src/stores/widgets/StopGapWidgetDriver.ts +++ b/src/stores/widgets/StopGapWidgetDriver.ts @@ -138,7 +138,7 @@ export class StopGapWidgetDriver extends WidgetDriver { WidgetEventCapability.forStateEvent( EventDirection.Send, "org.matrix.msc3401.call.member", - MatrixClientPeg.get().getUserId()!, + MatrixClientPeg.safeGet().getSafeUserId(), ).raw, ); this.allowedCapabilities.add( @@ -266,7 +266,7 @@ export class StopGapWidgetDriver extends WidgetDriver { encrypted: boolean, contentMap: { [userId: string]: { [deviceId: string]: object } }, ): Promise { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); if (encrypted) { const deviceInfoMap = await client.crypto!.deviceList.downloadKeys(Object.keys(contentMap), false); @@ -382,7 +382,7 @@ export class StopGapWidgetDriver extends WidgetDriver { if (opts.approved) { return observer.update({ state: OpenIDRequestState.Allowed, - token: await MatrixClientPeg.get().getOpenIdToken(), + token: await MatrixClientPeg.safeGet().getOpenIdToken(), }); } @@ -393,7 +393,7 @@ export class StopGapWidgetDriver extends WidgetDriver { ); const getToken = (): Promise => { - return MatrixClientPeg.get().getOpenIdToken(); + return MatrixClientPeg.safeGet().getOpenIdToken(); }; if (oidcState === OIDCState.Denied) { @@ -425,7 +425,7 @@ export class StopGapWidgetDriver extends WidgetDriver { } public async *getTurnServers(): AsyncGenerator { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); if (!client.pollingTurnServers || !client.getTurnServers().length) return; let setTurnServer: (server: ITurnServer) => void; @@ -468,7 +468,7 @@ export class StopGapWidgetDriver extends WidgetDriver { limit?: number, direction?: "f" | "b", ): Promise { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); const dir = direction as Direction; roomId = roomId ?? SdkContextClass.instance.roomViewStore.getRoomId() ?? undefined; @@ -492,7 +492,7 @@ export class StopGapWidgetDriver extends WidgetDriver { } public async searchUserDirectory(searchTerm: string, limit?: number): Promise { - const client = MatrixClientPeg.get(); + const client = MatrixClientPeg.safeGet(); const { limited, results } = await client.searchUserDirectory({ term: searchTerm, limit }); diff --git a/src/utils/PasswordScorer.ts b/src/utils/PasswordScorer.ts index fa2ef92058..187962e8f3 100644 --- a/src/utils/PasswordScorer.ts +++ b/src/utils/PasswordScorer.ts @@ -61,7 +61,7 @@ _td("Short keyboard patterns are easy to guess"); * @param matrixClient the client of the logged in user, if any * @returns {object} Score result with `score` and `feedback` properties */ -export function scorePassword(matrixClient: MatrixClient | undefined, password: string): zxcvbn.ZXCVBNResult | null { +export function scorePassword(matrixClient: MatrixClient | null, password: string): zxcvbn.ZXCVBNResult | null { if (password.length === 0) return null; const userInputs = ZXCVBN_USER_INPUTS.slice(); diff --git a/test/stores/room-list/previews/PollStartEventPreview-test.ts b/test/stores/room-list/previews/PollStartEventPreview-test.ts index dc9bcabfe3..fdb02ff186 100644 --- a/test/stores/room-list/previews/PollStartEventPreview-test.ts +++ b/test/stores/room-list/previews/PollStartEventPreview-test.ts @@ -24,6 +24,10 @@ jest.spyOn(MatrixClientPeg, "get").mockReturnValue({ getUserId: () => "@me:example.com", getSafeUserId: () => "@me:example.com", } as unknown as MatrixClient); +jest.spyOn(MatrixClientPeg, "safeGet").mockReturnValue({ + getUserId: () => "@me:example.com", + getSafeUserId: () => "@me:example.com", +} as unknown as MatrixClient); describe("PollStartEventPreview", () => { it("shows the question for a poll I created", async () => { diff --git a/test/stores/widgets/StopGapWidgetDriver-test.ts b/test/stores/widgets/StopGapWidgetDriver-test.ts index b5bea5b692..b3d11f4b9b 100644 --- a/test/stores/widgets/StopGapWidgetDriver-test.ts +++ b/test/stores/widgets/StopGapWidgetDriver-test.ts @@ -63,6 +63,7 @@ describe("StopGapWidgetDriver", () => { stubClient(); client = mocked(MatrixClientPeg.safeGet()); client.getUserId.mockReturnValue("@alice:example.org"); + client.getSafeUserId.mockReturnValue("@alice:example.org"); }); it("auto-approves capabilities of virtual Element Call widgets", async () => {