From e5a314617ab9a18fbf773768933c4e52b845b2fd Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 Apr 2023 09:02:40 +0100 Subject: [PATCH] Conform more of the codebase to strictNullChecks (#10505 * Conform more of the codebase to `strictNullChecks` * Iterate * Conform more of the codebase to `strictNullChecks` * Iterate * Iterate * Iterate * Iterate --- src/MatrixClientPeg.ts | 4 +-- src/components/structures/SpaceHierarchy.tsx | 2 +- src/components/structures/TimelinePanel.tsx | 34 +++++++++---------- .../context_menus/RoomGeneralContextMenu.tsx | 1 + .../dialogs/ConfirmAndWaitRedactDialog.tsx | 2 +- .../views/dialogs/ConfirmRedactDialog.tsx | 5 +-- .../KeySignatureUploadFailedDialog.tsx | 2 +- .../dialogs/MessageEditHistoryDialog.tsx | 26 +++++++------- .../views/dialogs/ServerOfflineDialog.tsx | 4 +-- .../dialogs/SlidingSyncOptionsDialog.tsx | 2 +- .../views/dialogs/TextInputDialog.tsx | 3 +- .../dialogs/spotlight/SpotlightDialog.tsx | 29 ++++++++-------- .../views/directory/NetworkDropdown.tsx | 2 +- src/components/views/messages/MPollBody.tsx | 6 ++-- .../views/messages/MessageActionBar.tsx | 2 +- src/components/views/right_panel/UserInfo.tsx | 15 ++------ .../views/rooms/MessageComposer.tsx | 2 +- .../views/rooms/MessageComposerButtons.tsx | 4 +-- .../wysiwyg_composer/EditWysiwygComposer.tsx | 2 +- .../views/settings/Notifications.tsx | 8 +++-- .../settings/tabs/user/SessionManagerTab.tsx | 4 +-- 21 files changed, 76 insertions(+), 83 deletions(-) diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts index 5d1351f1fa..1194b5daa9 100644 --- a/src/MatrixClientPeg.ts +++ b/src/MatrixClientPeg.ts @@ -332,7 +332,7 @@ class MatrixClientPegClass implements IMatrixClientPeg { homeserverUrl: this.matrixClient.baseUrl, identityServerUrl: this.matrixClient.idBaseUrl, - userId: this.matrixClient.credentials.userId, + userId: this.matrixClient.getSafeUserId(), deviceId: this.matrixClient.getDeviceId() ?? undefined, accessToken: this.matrixClient.getAccessToken(), guest: this.matrixClient.isGuest(), @@ -340,7 +340,7 @@ class MatrixClientPegClass implements IMatrixClientPeg { } public getHomeserverName(): string { - const matches = /^@[^:]+:(.+)$/.exec(this.matrixClient.credentials.userId); + const matches = /^@[^:]+:(.+)$/.exec(this.matrixClient.getSafeUserId()); if (matches === null || matches.length < 1) { throw new Error("Failed to derive homeserver name from user ID!"); } diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx index 5e17723ab1..fe246f6b35 100644 --- a/src/components/structures/SpaceHierarchy.tsx +++ b/src/components/structures/SpaceHierarchy.tsx @@ -102,7 +102,7 @@ const Tile: React.FC = ({ }) => { const cli = useContext(MatrixClientContext); const [joinedRoom, setJoinedRoom] = useState(() => { - const cliRoom = cli.getRoom(room.room_id); + const cliRoom = cli?.getRoom(room.room_id); return cliRoom?.getMyMembership() === "join" ? cliRoom : undefined; }); const joinedRoomName = useTypedEventEmitterState(joinedRoom, RoomEvent.Name, (room) => room?.name); diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index b496454c7e..3a28a2a4cd 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -30,7 +30,6 @@ import { ClientEvent } from "matrix-js-sdk/src/client"; import { Thread, ThreadEvent } from "matrix-js-sdk/src/models/thread"; import { ReceiptType } from "matrix-js-sdk/src/@types/read_receipts"; import { MatrixError } from "matrix-js-sdk/src/http-api"; -import { ReadReceipt } from "matrix-js-sdk/src/models/read-receipt"; import { Relations } from "matrix-js-sdk/src/models/relations"; import SettingsStore from "../../settings/SettingsStore"; @@ -515,23 +514,22 @@ class TimelinePanel extends React.Component { if (count > 0) { debuglog("Unpaginating", count, "in direction", dir); - this.timelineWindow.unpaginate(count, backwards); + this.timelineWindow?.unpaginate(count, backwards); const { events, liveEvents, firstVisibleEventIndex } = this.getEvents(); this.buildLegacyCallEventGroupers(events); - const newState: Partial = { + this.setState({ events, liveEvents, firstVisibleEventIndex, - }; + }); // We can now paginate in the unpaginated direction if (backwards) { - newState.canBackPaginate = true; + this.setState({ canBackPaginate: true }); } else { - newState.canForwardPaginate = true; + this.setState({ canForwardPaginate: true }); } - this.setState(newState); } }; @@ -636,6 +634,7 @@ class TimelinePanel extends React.Component { private doManageReadMarkers = debounce( () => { const rmPosition = this.getReadMarkerPosition(); + if (rmPosition === null) return; // we hide the read marker when it first comes onto the screen, but if // it goes back off the top of the screen (presumably because the user // clicks on the 'jump to bottom' button), we need to re-enable it. @@ -1125,7 +1124,7 @@ class TimelinePanel extends React.Component { return; } const lastDisplayedEvent = this.state.events[lastDisplayedIndex]; - this.setReadMarker(lastDisplayedEvent.getId(), lastDisplayedEvent.getTs()); + this.setReadMarker(lastDisplayedEvent.getId()!, lastDisplayedEvent.getTs()); // the read-marker should become invisible, so that if the user scrolls // down, they don't see it. @@ -1141,7 +1140,7 @@ class TimelinePanel extends React.Component { // advance the read marker past any events we sent ourselves. private advanceReadMarkerPastMyEvents(): void { - if (!this.props.manageReadMarkers) return; + if (!this.props.manageReadMarkers || !this.timelineWindow) return; // we call `timelineWindow.getEvents()` rather than using // `this.state.liveEvents`, because React batches the update to the @@ -1171,7 +1170,7 @@ class TimelinePanel extends React.Component { i--; const ev = events[i]; - this.setReadMarker(ev.getId(), ev.getTs()); + this.setReadMarker(ev.getId()!, ev.getTs()); } /* jump down to the bottom of this room, where new events are arriving @@ -1280,6 +1279,7 @@ class TimelinePanel extends React.Component { public getReadMarkerPosition = (): number | null => { if (!this.props.manageReadMarkers) return null; if (!this.messagePanel.current) return null; + if (!this.props.timelineSet.room) return null; const ret = this.messagePanel.current.getReadMarkerPosition(); if (ret !== null) { @@ -1629,7 +1629,7 @@ class TimelinePanel extends React.Component { return 0; } - const userId = cli.credentials.userId; + const userId = cli.getSafeUserId(); // get the user's membership at the last event by getting the timeline // that the event belongs to, and traversing the timeline looking for @@ -1648,7 +1648,7 @@ class TimelinePanel extends React.Component { continue; } - userMembership = timeline.getState(EventTimeline.FORWARDS).getMember(userId)?.membership ?? "leave"; + userMembership = timeline.getState(EventTimeline.FORWARDS)?.getMember(userId)?.membership ?? "leave"; const timelineEvents = timeline.getEvents(); for (let j = timelineEvents.length - 1; j >= 0; j--) { const event = timelineEvents[j]; @@ -1769,7 +1769,7 @@ class TimelinePanel extends React.Component { for (let i = this.state.liveEvents.length - 1; i >= 0; --i) { const ev = this.state.liveEvents[i]; - const node = messagePanel.getNodeForEventId(ev.getId()); + const node = messagePanel.getNodeForEventId(ev.getId()!); const isInView = isNodeInView(node); // when we've reached the first visible event, and the previous @@ -1829,8 +1829,8 @@ class TimelinePanel extends React.Component { } const myUserId = client.getSafeUserId(); - const receiptStore: ReadReceipt = this.props.timelineSet.thread ?? this.props.timelineSet.room; - return receiptStore?.getEventReadUpTo(myUserId, ignoreSynthesized); + const receiptStore = this.props.timelineSet.thread ?? this.props.timelineSet.room; + return receiptStore?.getEventReadUpTo(myUserId, ignoreSynthesized) ?? null; } private setReadMarker(eventId: string | null, eventTs: number, inhibitSetState = false): void { @@ -1924,7 +1924,7 @@ class TimelinePanel extends React.Component { // If the state is PREPARED or CATCHUP, we're still waiting for the js-sdk to sync with // the HS and fetch the latest events, so we are effectively forward paginating. const forwardPaginating = - this.state.forwardPaginating || ["PREPARED", "CATCHUP"].includes(this.state.clientSyncState); + this.state.forwardPaginating || ["PREPARED", "CATCHUP"].includes(this.state.clientSyncState!); const events = this.state.firstVisibleEventIndex ? this.state.events.slice(this.state.firstVisibleEventIndex) : this.state.events; @@ -1985,7 +1985,7 @@ function serializeEventIdsFromTimelineSets(timelineSets: EventTimelineSet[]): { // Add a special label when it is the live timeline so we can tell // it apart from the others const isLiveTimeline = timeline === liveTimeline; - timelineMap[isLiveTimeline ? "liveTimeline" : `${index}`] = timeline.getEvents().map((ev) => ev.getId()); + timelineMap[isLiveTimeline ? "liveTimeline" : `${index}`] = timeline.getEvents().map((ev) => ev.getId()!); }); return timelineMap; diff --git a/src/components/views/context_menus/RoomGeneralContextMenu.tsx b/src/components/views/context_menus/RoomGeneralContextMenu.tsx index 9cac6f4615..711b5fb910 100644 --- a/src/components/views/context_menus/RoomGeneralContextMenu.tsx +++ b/src/components/views/context_menus/RoomGeneralContextMenu.tsx @@ -89,6 +89,7 @@ export const RoomGeneralContextMenu: React.FC = ({ }; const onTagRoom = (ev: ButtonEvent, tagId: TagID): void => { + if (!cli) return; if (tagId === DefaultTagID.Favourite || tagId === DefaultTagID.LowPriority) { const inverseTag = tagId === DefaultTagID.Favourite ? DefaultTagID.LowPriority : DefaultTagID.Favourite; const isApplied = RoomListStore.instance.getTagsForRoom(room).includes(tagId); diff --git a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx index a7329d6fde..a792ccbd63 100644 --- a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx +++ b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx @@ -53,7 +53,7 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent => { + public onParentFinished = async (proceed?: boolean): Promise => { if (proceed) { this.setState({ isRedacting: true }); try { diff --git a/src/components/views/dialogs/ConfirmRedactDialog.tsx b/src/components/views/dialogs/ConfirmRedactDialog.tsx index 6f4d27781d..cd6ca8119e 100644 --- a/src/components/views/dialogs/ConfirmRedactDialog.tsx +++ b/src/components/views/dialogs/ConfirmRedactDialog.tsx @@ -26,7 +26,8 @@ import ErrorDialog from "./ErrorDialog"; import TextInputDialog from "./TextInputDialog"; interface IProps { - onFinished: (success: boolean) => void; + onFinished(success?: false, reason?: void): void; + onFinished(success: true, reason?: string): void; } /* @@ -67,7 +68,7 @@ export function createRedactEventDialog({ Modal.createDialog( ConfirmRedactDialog, { - onFinished: async (proceed: boolean, reason?: string): Promise => { + onFinished: async (proceed, reason): Promise => { if (!proceed) return; const cli = MatrixClientPeg.get(); diff --git a/src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx b/src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx index 25b367bf1d..efb87dbf07 100644 --- a/src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx +++ b/src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx @@ -72,7 +72,7 @@ const KeySignatureUploadFailedDialog: React.FC = ({ failures, source, co }, [continuation, onFinished]); let body; - if (!success && !cancelled && continuation && retry > 0) { + if (!success && !cancelled && retry > 0) { const reason = causes.get(source) || defaultCause; const brand = SdkConfig.get().brand; diff --git a/src/components/views/dialogs/MessageEditHistoryDialog.tsx b/src/components/views/dialogs/MessageEditHistoryDialog.tsx index d558774bfd..197709b8b7 100644 --- a/src/components/views/dialogs/MessageEditHistoryDialog.tsx +++ b/src/components/views/dialogs/MessageEditHistoryDialog.tsx @@ -20,6 +20,7 @@ import { EventType, RelationType } from "matrix-js-sdk/src/@types/event"; import { defer } from "matrix-js-sdk/src/utils"; import { logger } from "matrix-js-sdk/src/logger"; import { MatrixClient } from "matrix-js-sdk/src/client"; +import { MatrixError } from "matrix-js-sdk/src/http-api"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { _t } from "../../../languageHandler"; @@ -37,12 +38,10 @@ interface IProps { } interface IState { - originalEvent: MatrixEvent; - error: { - errcode: string; - }; + originalEvent: MatrixEvent | null; + error: MatrixError | null; events: MatrixEvent[]; - nextBatch: string; + nextBatch: string | null; isLoading: boolean; isTwelveHour: boolean; } @@ -65,9 +64,9 @@ export default class MessageEditHistoryDialog extends React.PureComponent(); @@ -80,7 +79,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent reject(error)); + this.setState({ error: error as MatrixError }, () => reject(error)); return promise; } @@ -88,9 +87,9 @@ export default class MessageEditHistoryDialog extends React.PureComponent { @@ -105,6 +104,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent { @@ -133,7 +133,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent - + , ); } @@ -141,7 +141,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent { this.forceUpdate(); // no state to worry about }; - private renderTimeline(): React.ReactElement[] { + private renderTimeline(): ReactNode[] { return EchoStore.instance.contexts.map((c, i) => { if (!c.firstFailedTime) return null; // not useful if (!(c instanceof RoomEchoContext)) diff --git a/src/components/views/dialogs/SlidingSyncOptionsDialog.tsx b/src/components/views/dialogs/SlidingSyncOptionsDialog.tsx index 50daed6847..cf1bf354ce 100644 --- a/src/components/views/dialogs/SlidingSyncOptionsDialog.tsx +++ b/src/components/views/dialogs/SlidingSyncOptionsDialog.tsx @@ -124,7 +124,7 @@ export const SlidingSyncOptionsDialog: React.FC<{ onFinished(enabled: boolean): value={currentProxy} button={_t("Enable")} validator={validProxy} - onFinished={(enable: boolean, proxyUrl: string) => { + onFinished={(enable, proxyUrl) => { if (enable) { SettingsStore.setValue("feature_sliding_sync_proxy_url", null, SettingLevel.DEVICE, proxyUrl); onFinished(true); diff --git a/src/components/views/dialogs/TextInputDialog.tsx b/src/components/views/dialogs/TextInputDialog.tsx index ed9f377508..89b5e91640 100644 --- a/src/components/views/dialogs/TextInputDialog.tsx +++ b/src/components/views/dialogs/TextInputDialog.tsx @@ -33,7 +33,8 @@ interface IProps { hasCancel: boolean; validator?: (fieldState: IFieldState) => Promise; // result of withValidation fixedWidth?: boolean; - onFinished(ok?: boolean, text?: string): void; + onFinished(ok?: false, text?: void): void; + onFinished(ok: true, text: string): void; } interface IState { diff --git a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx index ba1e0098f6..7c5aed0273 100644 --- a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx +++ b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx @@ -35,7 +35,6 @@ import React, { import sanitizeHtml from "sanitize-html"; import { KeyBindingAction } from "../../../../accessibility/KeyboardShortcuts"; -import { Ref } from "../../../../accessibility/roving/types"; import { findSiblingElement, RovingTabIndexContext, @@ -104,8 +103,8 @@ interface IProps { onFinished(): void; } -function refIsForRecentlyViewed(ref: RefObject): boolean { - return ref.current?.id?.startsWith("mx_SpotlightDialog_button_recentlyViewed_") === true; +function refIsForRecentlyViewed(ref?: RefObject): boolean { + return ref?.current?.id?.startsWith("mx_SpotlightDialog_button_recentlyViewed_") === true; } function getRoomTypes(showRooms: boolean, showSpaces: boolean): Set { @@ -366,7 +365,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n return [ ...SpaceStore.instance.enabledMetaSpaces.map((spaceKey) => ({ section: Section.Spaces, - filter: [], + filter: [] as Filter[], avatar: (
= ({ initialText = "", initialFilter = n return memberComparator(a.member, b.member); } + return 0; }); } @@ -474,17 +474,16 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n }; useEffect(() => { setImmediate(() => { - let ref: Ref | undefined; - if (rovingContext.state.refs) { - ref = rovingContext.state.refs[0]; + const ref = rovingContext.state.refs[0]; + if (ref) { + rovingContext.dispatch({ + type: Type.SetFocus, + payload: { ref }, + }); + ref.current?.scrollIntoView?.({ + block: "nearest", + }); } - rovingContext.dispatch({ - type: Type.SetFocus, - payload: { ref }, - }); - ref?.current?.scrollIntoView?.({ - block: "nearest", - }); }); // we intentionally ignore changes to the rovingContext for the purpose of this hook // we only want to reset the focus whenever the results or filters change @@ -635,7 +634,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n roomId: publicRoom.room_id, autoJoin: !result.publicRoom.world_readable && !cli.isGuest(), shouldPeek: result.publicRoom.world_readable || cli.isGuest(), - viaServers: [config.roomServer], + viaServers: config ? [config.roomServer] : undefined, }, true, ev.type !== "click", diff --git a/src/components/views/directory/NetworkDropdown.tsx b/src/components/views/directory/NetworkDropdown.tsx index c84bb4a2f1..b90d22574b 100644 --- a/src/components/views/directory/NetworkDropdown.tsx +++ b/src/components/views/directory/NetworkDropdown.tsx @@ -148,7 +148,7 @@ export const NetworkDropdown: React.FC = ({ protocols, config, setConfig const { allServers, homeServer, userDefinedServers, setUserDefinedServers } = useServers(); const options: GenericDropdownMenuItem[] = allServers.map((roomServer) => ({ - key: { roomServer, instanceId: null }, + key: { roomServer, instanceId: undefined }, label: roomServer, description: roomServer === homeServer ? _t("Your server") : null, options: [ diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index c701cb4d01..1029f7370d 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -154,7 +154,7 @@ export default class MPollBody extends React.Component { } public componentDidMount(): void { - const room = this.context.getRoom(this.props.mxEvent.getRoomId()); + const room = this.context?.getRoom(this.props.mxEvent.getRoomId()); const poll = room?.polls.get(this.props.mxEvent.getId()!); if (poll) { this.setPollInstance(poll); @@ -291,8 +291,8 @@ export default class MPollBody extends React.Component { const votes = countVotes(userVotes, pollEvent); const totalVotes = this.totalVotes(votes); const winCount = Math.max(...votes.values()); - const userId = this.context.getUserId(); - const myVote = userVotes?.get(userId!)?.answers[0]; + const userId = this.context.getSafeUserId(); + const myVote = userVotes?.get(userId)?.answers[0]; const disclosed = M_POLL_KIND_DISCLOSED.matches(pollEvent.kind.name); // Disclosed: votes are hidden until I vote or the poll ends diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index 6ac1e74586..3a85406c4f 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -259,7 +259,7 @@ interface IFavouriteButtonProp { const FavouriteButton: React.FC = ({ mxEvent }) => { const { isFavourite, toggleFavourite } = useFavouriteMessages(); - const eventId = mxEvent.getId(); + const eventId = mxEvent.getId()!; const classes = classNames("mx_MessageActionBar_iconButton mx_MessageActionBar_favouriteButton", { mx_MessageActionBar_favouriteButton_fillstar: isFavourite(eventId), }); diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index b389dd4dcd..c0fb6dd443 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -995,19 +995,8 @@ export const RoomAdminToolsContainer: React.FC = ({ return
; }; -const useIsSynapseAdmin = (cli: MatrixClient): boolean => { - const [isAdmin, setIsAdmin] = useState(false); - useEffect(() => { - cli.isSynapseAdministrator().then( - (isAdmin) => { - setIsAdmin(isAdmin); - }, - () => { - setIsAdmin(false); - }, - ); - }, [cli]); - return isAdmin; +const useIsSynapseAdmin = (cli?: MatrixClient): boolean => { + return useAsyncMemo(async () => (cli ? cli.isSynapseAdministrator().catch(() => false) : false), [cli], false); }; const useHomeserverSupportsCrossSigning = (cli: MatrixClient): boolean => { diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index 2e4be003c4..a5569de36a 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -250,7 +250,7 @@ export class MessageComposer extends React.Component { // The members should already be loading, and loadMembersIfNeeded // will return the promise for the existing operation this.props.room.loadMembersIfNeeded().then(() => { - const me = this.props.room.getMember(MatrixClientPeg.get().getUserId()!); + const me = this.props.room.getMember(MatrixClientPeg.get().getSafeUserId()) ?? undefined; this.setState({ me }); }); } diff --git a/src/components/views/rooms/MessageComposerButtons.tsx b/src/components/views/rooms/MessageComposerButtons.tsx index abcb82ee63..1b8e15b498 100644 --- a/src/components/views/rooms/MessageComposerButtons.tsx +++ b/src/components/views/rooms/MessageComposerButtons.tsx @@ -64,7 +64,7 @@ type OverflowMenuCloser = () => void; export const OverflowMenuContext = createContext(null); const MessageComposerButtons: React.FC = (props: IProps) => { - const matrixClient: MatrixClient = useContext(MatrixClientContext); + const matrixClient = useContext(MatrixClientContext); const { room, roomId, narrow } = useContext(RoomContext); const isWysiwygLabEnabled = useSettingValue("feature_wysiwyg_composer"); @@ -183,7 +183,7 @@ const UploadButtonContextProvider: React.FC = ({ roomId, rel const uploadInput = useRef(); const onUploadClick = (): void => { - if (cli.isGuest()) { + if (cli?.isGuest()) { dis.dispatch({ action: "require_registration" }); return; } diff --git a/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx b/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx index c0915469e2..69bc8b618f 100644 --- a/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx +++ b/src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx @@ -59,7 +59,7 @@ export default function EditWysiwygComposer({ const { editMessage, endEditing, onChange, isSaveDisabled } = useEditing(editorStateTransfer, initialContent); if (!isReady) { - return null; + return <>; } return ( diff --git a/src/components/views/settings/Notifications.tsx b/src/components/views/settings/Notifications.tsx index 6d517fb635..3e833b315f 100644 --- a/src/components/views/settings/Notifications.tsx +++ b/src/components/views/settings/Notifications.tsx @@ -439,9 +439,11 @@ export default class Notifications extends React.PureComponent { append: true, }); } else { - const pusher = this.state.pushers.find((p) => p.kind === "email" && p.pushkey === email); - pusher.kind = null; // flag for delete - await MatrixClientPeg.get().setPusher(pusher); + const pusher = this.state.pushers?.find((p) => p.kind === "email" && p.pushkey === email); + if (pusher) { + pusher.kind = null; // flag for delete + await MatrixClientPeg.get().setPusher(pusher); + } } await this.refreshFromServer(); diff --git a/src/components/views/settings/tabs/user/SessionManagerTab.tsx b/src/components/views/settings/tabs/user/SessionManagerTab.tsx index 4e66da4ea2..0dbda9477a 100644 --- a/src/components/views/settings/tabs/user/SessionManagerTab.tsx +++ b/src/components/views/settings/tabs/user/SessionManagerTab.tsx @@ -129,8 +129,8 @@ const SessionManagerTab: React.FC = () => { const scrollIntoViewTimeoutRef = useRef(); const matrixClient = useContext(MatrixClientContext); - const userId = matrixClient.getUserId(); - const currentUserMember = (userId && matrixClient.getUser(userId)) || undefined; + const userId = matrixClient?.getUserId(); + const currentUserMember = (userId && matrixClient?.getUser(userId)) || undefined; const clientVersions = useAsyncMemo(() => matrixClient.getVersions(), [matrixClient]); const onDeviceExpandToggle = (deviceId: ExtendedDevice["device_id"]): void => {