diff --git a/src/KeyBindingsManager.ts b/src/KeyBindingsManager.ts index 7720c05166..fad4cf208c 100644 --- a/src/KeyBindingsManager.ts +++ b/src/KeyBindingsManager.ts @@ -25,7 +25,7 @@ import { IS_MAC } from "./Keyboard"; * The combo is evaluated strictly, i.e. the KeyboardEvent must match exactly what is specified in the KeyCombo. */ export type KeyCombo = { - key?: string; + key: string; /** On PC: ctrl is pressed; on Mac: meta is pressed */ ctrlOrCmdKey?: boolean; diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts index 13c75f0ba3..51d493030e 100644 --- a/src/MatrixClientPeg.ts +++ b/src/MatrixClientPeg.ts @@ -306,7 +306,7 @@ class MatrixClientPegClass implements IMatrixClientPeg { homeserverUrl: this.matrixClient.baseUrl, identityServerUrl: this.matrixClient.idBaseUrl, userId: this.matrixClient.credentials.userId, - deviceId: this.matrixClient.getDeviceId(), + deviceId: this.matrixClient.getDeviceId() ?? undefined, accessToken: this.matrixClient.getAccessToken(), guest: this.matrixClient.isGuest(), }; diff --git a/src/Searching.ts b/src/Searching.ts index 90798f480e..85efeea8c8 100644 --- a/src/Searching.ts +++ b/src/Searching.ts @@ -576,7 +576,7 @@ async function combinedPagination(searchResult: ISeshatSearchResults): Promise { // We want to recalculate zoom whenever the window's size changes window.addEventListener("resize", this.recalculateZoom); // After the image loads for the first time we want to calculate the zoom - this.image.current.addEventListener("load", this.imageLoaded); + this.image.current?.addEventListener("load", this.imageLoaded); } public componentWillUnmount(): void { this.focusLock.current.removeEventListener("wheel", this.onWheel); window.removeEventListener("resize", this.recalculateZoom); - this.image.current.removeEventListener("load", this.imageLoaded); + this.image.current?.removeEventListener("load", this.imageLoaded); } private imageLoaded = (): void => { @@ -171,6 +171,7 @@ export default class ImageView extends React.Component { private setZoomAndRotation = (inputRotation?: number): void => { const image = this.image.current; const imageWrapper = this.imageWrapper.current; + if (!image || !imageWrapper) return; const rotation = inputRotation ?? this.state.rotation; @@ -236,8 +237,8 @@ export default class ImageView extends React.Component { // Zoom relative to the given point on the image. // First we need to figure out the offset of the anchor point // relative to the center of the image, accounting for rotation. - let offsetX; - let offsetY; + let offsetX: number | undefined; + let offsetY: number | undefined; // The modulo operator can return negative values for some // rotations, so we have to do some extra work to normalize it switch (((this.state.rotation % 360) + 360) % 360) { @@ -310,7 +311,7 @@ export default class ImageView extends React.Component { private onDownloadClick = (): void => { const a = document.createElement("a"); a.href = this.props.src; - a.download = this.props.name; + if (this.props.name) a.download = this.props.name; a.target = "_blank"; a.rel = "noreferrer noopener"; a.click(); @@ -334,9 +335,9 @@ export default class ImageView extends React.Component { ev.preventDefault(); dis.dispatch({ action: Action.ViewRoom, - event_id: this.props.mxEvent.getId(), + event_id: this.props.mxEvent?.getId(), highlighted: true, - room_id: this.props.mxEvent.getRoomId(), + room_id: this.props.mxEvent?.getRoomId(), metricsTrigger: undefined, // room doesn't change }); this.props.onFinished(); @@ -440,11 +441,11 @@ export default class ImageView extends React.Component { let info: JSX.Element | undefined; if (showEventMeta) { - const mxEvent = this.props.mxEvent; + const mxEvent = this.props.mxEvent!; const showTwelveHour = SettingsStore.getValue("showTwelveHourTimestamps"); let permalink = "#"; if (this.props.permalinkCreator) { - permalink = this.props.permalinkCreator.forEvent(this.props.mxEvent.getId()); + permalink = this.props.permalinkCreator.forEvent(mxEvent.getId()); } const senderName = mxEvent.sender?.name ?? mxEvent.getSender(); @@ -453,7 +454,7 @@ export default class ImageView extends React.Component { { // should typically be less than `overflowItems` unless applying // margins in the parent component when using multiple LazyRenderList in one viewport. // use 0 to only rerender when items will come into view. - overflowMargin?: number; + overflowMargin: number; // the amount of items to add at the top and bottom to render, // so not every scroll of causes a rerender. - overflowItems?: number; + overflowItems: number; element?: string; className?: string; } interface IState { - renderRange: ItemRange | null; + renderRange: ItemRange; } export default class LazyRenderList extends React.Component, IState> { @@ -88,9 +88,7 @@ export default class LazyRenderList extends React.Component, public constructor(props: IProps) { super(props); - this.state = { - renderRange: null, - }; + this.state = LazyRenderList.getDerivedStateFromProps(props, {} as IState) as IState; } public static getDerivedStateFromProps(props: IProps, state: IState): Partial | null { diff --git a/src/components/views/messages/EncryptionEvent.tsx b/src/components/views/messages/EncryptionEvent.tsx index 28809579d5..fbc1da18d3 100644 --- a/src/components/views/messages/EncryptionEvent.tsx +++ b/src/components/views/messages/EncryptionEvent.tsx @@ -35,7 +35,7 @@ const ALGORITHM = "m.megolm.v1.aes-sha2"; const EncryptionEvent = forwardRef(({ mxEvent, timestamp }, ref) => { const cli = useContext(MatrixClientContext); - const roomId = mxEvent.getRoomId(); + const roomId = mxEvent.getRoomId()!; const isRoomEncrypted = MatrixClientPeg.get().isRoomEncrypted(roomId); const prevContent = mxEvent.getPrevContent() as IRoomEncryption; @@ -51,13 +51,13 @@ const EncryptionEvent = forwardRef(({ mxEvent, timestamp if (prevContent.algorithm === ALGORITHM) { subtitle = _t("Some encryption parameters have been changed."); } else if (dmPartner) { - const displayName = room.getMember(dmPartner)?.rawDisplayName || dmPartner; + const displayName = room?.getMember(dmPartner)?.rawDisplayName || dmPartner; subtitle = _t( "Messages here are end-to-end encrypted. " + "Verify %(displayName)s in their profile - tap on their avatar.", { displayName }, ); - } else if (isLocalRoom(room)) { + } else if (room && isLocalRoom(room)) { subtitle = _t("Messages in this chat will be end-to-end encrypted."); } else { subtitle = _t( diff --git a/src/components/views/messages/MBeaconBody.tsx b/src/components/views/messages/MBeaconBody.tsx index 3fa0b60696..a3d680cb07 100644 --- a/src/components/views/messages/MBeaconBody.tsx +++ b/src/components/views/messages/MBeaconBody.tsx @@ -183,7 +183,7 @@ const MBeaconBody: React.FC = React.forwardRef(({ mxEvent, getRelati diff --git a/src/components/views/right_panel/TimelineCard.tsx b/src/components/views/right_panel/TimelineCard.tsx index 56b3b580a0..3ccf60d5da 100644 --- a/src/components/views/right_panel/TimelineCard.tsx +++ b/src/components/views/right_panel/TimelineCard.tsx @@ -47,10 +47,10 @@ interface IProps { room: Room; onClose: () => void; resizeNotifier: ResizeNotifier; - permalinkCreator?: RoomPermalinkCreator; + permalinkCreator: RoomPermalinkCreator; e2eStatus?: E2EStatus; classNames?: string; - timelineSet?: EventTimelineSet; + timelineSet: EventTimelineSet; timelineRenderingType?: TimelineRenderingType; showComposer?: boolean; composerRelation?: IEventRelation; @@ -77,7 +77,7 @@ export default class TimelineCard extends React.Component { private layoutWatcherRef: string; private timelinePanel = React.createRef(); private card = React.createRef(); - private readReceiptsSettingWatcher: string; + private readReceiptsSettingWatcher: string | undefined; public constructor(props: IProps) { super(props); @@ -87,7 +87,6 @@ export default class TimelineCard extends React.Component { atEndOfLiveTimeline: true, narrow: false, }; - this.readReceiptsSettingWatcher = null; } public componentDidMount(): void { @@ -129,7 +128,7 @@ export default class TimelineCard extends React.Component { case Action.EditEvent: this.setState( { - editState: payload.event ? new EditorStateTransfer(payload.event) : null, + editState: payload.event ? new EditorStateTransfer(payload.event) : undefined, }, () => { if (payload.event) { @@ -199,7 +198,7 @@ export default class TimelineCard extends React.Component { }; public render(): React.ReactNode { - const highlightedEventId = this.state.isInitialEventHighlighted ? this.state.initialEventId : null; + const highlightedEventId = this.state.isInitialEventHighlighted ? this.state.initialEventId : undefined; let jumpToBottom; if (!this.state.atEndOfLiveTimeline) { @@ -232,7 +231,7 @@ export default class TimelineCard extends React.Component { header={this.renderTimelineCardHeader()} ref={this.card} > - + {this.card.current && }
{jumpToBottom} {_t( "The device you are trying to verify doesn't support scanning a " + @@ -79,12 +80,13 @@ export default class VerificationPanel extends React.PureComponent - ) : null; + ); + } if (this.props.layout === "dialog") { // HACK: This is a terrible idea. - let qrBlockDialog: JSX.Element; - let sasBlockDialog: JSX.Element; + let qrBlockDialog: JSX.Element | undefined; + let sasBlockDialog: JSX.Element | undefined; if (showQR) { qrBlockDialog = (
@@ -132,7 +134,7 @@ export default class VerificationPanel extends React.PureComponent @@ -150,7 +152,7 @@ export default class VerificationPanel extends React.PureComponent { + if (!this.state.reciprocateQREvent) return; this.setState({ reciprocateButtonClicked: true }); this.state.reciprocateQREvent.confirm(); }; private onReciprocateNoClick = (): void => { + if (!this.state.reciprocateQREvent) return; this.setState({ reciprocateButtonClicked: true }); this.state.reciprocateQREvent.cancel(); }; - private getDevice(): DeviceInfo { - const deviceId = this.props.request && this.props.request.channel.deviceId; - return MatrixClientPeg.get().getStoredDevice(MatrixClientPeg.get().getUserId(), deviceId); + private getDevice(): DeviceInfo | null { + const cli = MatrixClientPeg.get(); + return cli.getStoredDevice(cli.getSafeUserId(), this.props.request?.channel.deviceId); } private renderQRReciprocatePhase(): JSX.Element { @@ -253,7 +257,7 @@ export default class VerificationPanel extends React.PureComponent { - this.state.sasEvent.confirm(); + this.state.sasEvent?.confirm(); }; private onSasMismatchesClick = (): void => { - this.state.sasEvent.mismatch(); + this.state.sasEvent?.mismatch(); }; private updateVerifierState = (): void => { diff --git a/src/components/views/right_panel/WidgetCard.tsx b/src/components/views/right_panel/WidgetCard.tsx index 0e26ebcb6c..3fb4ab6cfd 100644 --- a/src/components/views/right_panel/WidgetCard.tsx +++ b/src/components/views/right_panel/WidgetCard.tsx @@ -55,9 +55,9 @@ const WidgetCard: React.FC = ({ room, widgetId, onClose }) => { // Don't render anything as we are about to transition if (!app || !isRight) return null; - let contextMenu; + let contextMenu: JSX.Element | undefined; if (menuDisplayed) { - const rect = handle.current.getBoundingClientRect(); + const rect = handle.current!.getBoundingClientRect(); contextMenu = ( = ({ room, widgetId, onClose }) => { fullWidth showMenubar={false} room={room} - userId={cli.getUserId()} + userId={cli.getSafeUserId()} creatorUserId={app.creatorUserId} widgetPageTitle={WidgetUtils.getWidgetDataTitle(app)} waitForIframeLoad={app.waitForIframeLoad} diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index d251285816..d6cfb3038a 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -252,10 +252,10 @@ export default class BasicMessageEditor extends React.Component } } if (isEmpty) { - this.formatBarRef.current.hide(); + this.formatBarRef.current?.hide(); } this.setState({ - autoComplete: this.props.model.autoComplete, + autoComplete: this.props.model.autoComplete ?? undefined, // if a change is happening then clear the showVisualBell showVisualBell: diff ? false : this.state.showVisualBell, }); @@ -266,12 +266,16 @@ export default class BasicMessageEditor extends React.Component // If the user is entering a command, only consider them typing if it is one which sends a message into the room if (isTyping && this.props.model.parts[0].type === "command") { const { cmd } = parseCommandString(this.props.model.parts[0].text); - const command = CommandMap.get(cmd); - if (!command || !command.isEnabled() || command.category !== CommandCategories.messages) { + const command = CommandMap.get(cmd!); + if (!command?.isEnabled() || command.category !== CommandCategories.messages) { isTyping = false; } } - SdkContextClass.instance.typingStore.setSelfTyping(this.props.room.roomId, this.props.threadId, isTyping); + SdkContextClass.instance.typingStore.setSelfTyping( + this.props.room.roomId, + this.props.threadId ?? null, + isTyping, + ); if (this.props.onChange) { this.props.onChange(); @@ -280,14 +284,14 @@ export default class BasicMessageEditor extends React.Component private showPlaceholder(): void { // escape single quotes - const placeholder = this.props.placeholder.replace(/'/g, "\\'"); - this.editorRef.current.style.setProperty("--placeholder", `'${placeholder}'`); - this.editorRef.current.classList.add("mx_BasicMessageComposer_inputEmpty"); + const placeholder = this.props.placeholder?.replace(/'/g, "\\'"); + this.editorRef.current?.style.setProperty("--placeholder", `'${placeholder}'`); + this.editorRef.current?.classList.add("mx_BasicMessageComposer_inputEmpty"); } private hidePlaceholder(): void { - this.editorRef.current.classList.remove("mx_BasicMessageComposer_inputEmpty"); - this.editorRef.current.style.removeProperty("--placeholder"); + this.editorRef.current?.classList.remove("mx_BasicMessageComposer_inputEmpty"); + this.editorRef.current?.style.removeProperty("--placeholder"); } private onCompositionStart = (): void => { @@ -327,9 +331,9 @@ export default class BasicMessageEditor extends React.Component } private onCutCopy = (event: ClipboardEvent, type: string): void => { - const selection = document.getSelection(); + const selection = document.getSelection()!; const text = selection.toString(); - if (text) { + if (text && this.editorRef.current) { const { model } = this.props; const range = getRangeForSelection(this.editorRef.current, model, selection); const selectedParts = range.parts.map((p) => p.serialize()); @@ -412,7 +416,7 @@ export default class BasicMessageEditor extends React.Component const { model } = this.props; this._isCaretAtEnd = position.isAtEnd(model); this.lastCaret = position.asOffset(model); - this.lastSelection = cloneSelection(document.getSelection()); + this.lastSelection = cloneSelection(document.getSelection()!); } private refreshLastCaretIfNeeded(): DocumentOffset | undefined { @@ -422,7 +426,7 @@ export default class BasicMessageEditor extends React.Component if (!this.editorRef.current) { return; } - const selection = document.getSelection(); + const selection = document.getSelection()!; if (!this.lastSelection || !selectionEquals(this.lastSelection, selection)) { this.lastSelection = cloneSelection(selection); const { caret, text } = getCaretOffsetAndText(this.editorRef.current, selection); @@ -467,7 +471,7 @@ export default class BasicMessageEditor extends React.Component const { isEmpty } = this.props.model; this.refreshLastCaretIfNeeded(); - const selection = document.getSelection(); + const selection = document.getSelection()!; if (this.hasTextSelected && selection.isCollapsed) { this.hasTextSelected = false; this.formatBarRef.current?.hide(); @@ -485,7 +489,7 @@ export default class BasicMessageEditor extends React.Component const model = this.props.model; let handled = false; - if (this.state.surroundWith && document.getSelection().type !== "Caret") { + if (this.state.surroundWith && document.getSelection()!.type !== "Caret") { // This surrounds the selected text with a character. This is // intentionally left out of the keybinding manager as the keybinds // here shouldn't be changeable @@ -538,7 +542,7 @@ export default class BasicMessageEditor extends React.Component this.tabCompleteName(); handled = true; } else if ([KeyBindingAction.Delete, KeyBindingAction.Backspace].includes(accessibilityAction!)) { - this.formatBarRef.current.hide(); + this.formatBarRef.current?.hide(); } if (handled) { @@ -654,7 +658,7 @@ export default class BasicMessageEditor extends React.Component private onAutoCompleteConfirm = (completion: ICompletion): void => { this.modifiedFlag = true; - this.props.model.autoComplete.onComponentConfirm(completion); + this.props.model.autoComplete?.onComponentConfirm(completion); }; private onAutoCompleteSelectionChange = (completionIndex: number): void => { @@ -691,9 +695,9 @@ export default class BasicMessageEditor extends React.Component public componentWillUnmount(): void { document.removeEventListener("selectionchange", this.onSelectionChange); - this.editorRef.current.removeEventListener("input", this.onInput, true); - this.editorRef.current.removeEventListener("compositionstart", this.onCompositionStart, true); - this.editorRef.current.removeEventListener("compositionend", this.onCompositionEnd, true); + this.editorRef.current?.removeEventListener("input", this.onInput, true); + this.editorRef.current?.removeEventListener("compositionstart", this.onCompositionStart, true); + this.editorRef.current?.removeEventListener("compositionend", this.onCompositionEnd, true); SettingsStore.unwatchSetting(this.useMarkdownHandle); SettingsStore.unwatchSetting(this.emoticonSettingHandle); SettingsStore.unwatchSetting(this.shouldShowPillAvatarSettingHandle); @@ -716,10 +720,10 @@ export default class BasicMessageEditor extends React.Component this.updateEditorState(this.getInitialCaretPosition()); // attach input listener by hand so React doesn't proxy the events, // as the proxied event doesn't support inputType, which we need. - this.editorRef.current.addEventListener("input", this.onInput, true); - this.editorRef.current.addEventListener("compositionstart", this.onCompositionStart, true); - this.editorRef.current.addEventListener("compositionend", this.onCompositionEnd, true); - this.editorRef.current.focus(); + this.editorRef.current?.addEventListener("input", this.onInput, true); + this.editorRef.current?.addEventListener("compositionstart", this.onCompositionStart, true); + this.editorRef.current?.addEventListener("compositionend", this.onCompositionEnd, true); + this.editorRef.current?.focus(); } private getInitialCaretPosition(): DocumentPosition { @@ -826,7 +830,7 @@ export default class BasicMessageEditor extends React.Component } public focus(): void { - this.editorRef.current.focus(); + this.editorRef.current?.focus(); } public insertMention(userId: string): void { diff --git a/src/components/views/rooms/EditMessageComposer.tsx b/src/components/views/rooms/EditMessageComposer.tsx index 9d21284c27..3698a7fb11 100644 --- a/src/components/views/rooms/EditMessageComposer.tsx +++ b/src/components/views/rooms/EditMessageComposer.tsx @@ -149,7 +149,7 @@ class EditMessageComposer extends React.Component { @@ -304,10 +304,10 @@ class EditMessageComposer extends React.Component if (thread.id === this.props.mxEvent.getId()) { this.updateThread(thread); const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); - room.off(ThreadEvent.New, this.onNewThread); + room?.off(ThreadEvent.New, this.onNewThread); } }; private get thread(): Thread | null { - let thread = this.props.mxEvent.getThread(); + let thread: Thread | undefined = this.props.mxEvent.getThread(); /** * Accessing the threads value through the room due to a race condition * that will be solved when there are proper backend support for threads @@ -452,7 +452,7 @@ export class UnwrappedEventTile extends React.Component */ if (!thread) { const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); - thread = room?.findThreadForEvent(this.props.mxEvent); + thread = room?.findThreadForEvent(this.props.mxEvent) ?? undefined; } return thread ?? null; } @@ -471,7 +471,7 @@ export class UnwrappedEventTile extends React.Component } private renderThreadInfo(): React.ReactNode { - if (this.state.thread?.id === this.props.mxEvent.getId()) { + if (this.state.thread && this.state.thread.id === this.props.mxEvent.getId()) { return ( ); @@ -506,7 +506,7 @@ export class UnwrappedEventTile extends React.Component evt.preventDefault(); evt.stopPropagation(); const { permalinkCreator, mxEvent } = this.props; - const matrixToUrl = permalinkCreator.forEvent(mxEvent.getId()); + const matrixToUrl = permalinkCreator.forEvent(mxEvent.getId()!); await copyPlaintext(matrixToUrl); }; @@ -1104,7 +1104,7 @@ export class UnwrappedEventTile extends React.Component const useIRCLayout = this.props.layout === Layout.IRC; const groupTimestamp = !useIRCLayout ? linkedTimestamp : null; const ircTimestamp = useIRCLayout ? linkedTimestamp : null; - const bubbleTimestamp = this.props.layout === Layout.Bubble ? messageTimestamp : null; + const bubbleTimestamp = this.props.layout === Layout.Bubble ? messageTimestamp : undefined; const groupPadlock = !useIRCLayout && !isBubbleMessage && this.renderE2EPadlock(); const ircPadlock = useIRCLayout && !isBubbleMessage && this.renderE2EPadlock(); @@ -1493,7 +1493,7 @@ class E2ePadlock extends React.Component { } interface ISentReceiptProps { - messageState: string; // TODO: Types for message sending state + messageState: EventStatus | null; } function SentReceipt({ messageState }: ISentReceiptProps): JSX.Element { diff --git a/src/components/views/rooms/NewRoomIntro.tsx b/src/components/views/rooms/NewRoomIntro.tsx index 7f2aa3ce3f..ecff7aa946 100644 --- a/src/components/views/rooms/NewRoomIntro.tsx +++ b/src/components/views/rooms/NewRoomIntro.tsx @@ -164,7 +164,7 @@ const NewRoomIntro: React.FC = () => { } const creator = room.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender(); - const creatorName = room?.getMember(creator)?.rawDisplayName || creator; + const creatorName = (creator && room?.getMember(creator)?.rawDisplayName) || creator; let createdText: string; if (creator === cli.getUserId()) { @@ -178,7 +178,7 @@ const NewRoomIntro: React.FC = () => { let parentSpace: Room | undefined; if ( SpaceStore.instance.activeSpaceRoom?.canInvite(cli.getSafeUserId()) && - SpaceStore.instance.isRoomInSpace(SpaceStore.instance.activeSpace, room.roomId) + SpaceStore.instance.isRoomInSpace(SpaceStore.instance.activeSpace!, room.roomId) ) { parentSpace = SpaceStore.instance.activeSpaceRoom; } diff --git a/src/components/views/rooms/RoomListHeader.tsx b/src/components/views/rooms/RoomListHeader.tsx index ce56dabd77..1feb201e8a 100644 --- a/src/components/views/rooms/RoomListHeader.tsx +++ b/src/components/views/rooms/RoomListHeader.tsx @@ -231,7 +231,7 @@ const RoomListHeader: React.FC = ({ onVisibilityChange }) => { contextMenu = ( @@ -357,7 +357,7 @@ const RoomListHeader: React.FC = ({ onVisibilityChange }) => { contextMenu = ( diff --git a/src/components/views/rooms/SendMessageComposer.tsx b/src/components/views/rooms/SendMessageComposer.tsx index a99d2c1c68..d3d7e3847d 100644 --- a/src/components/views/rooms/SendMessageComposer.tsx +++ b/src/components/views/rooms/SendMessageComposer.tsx @@ -227,12 +227,14 @@ export class SendMessageComposer extends React.Component(); + messageReactions.getAnnotationsBySender()?.[userId] || new Set(); const myReactionKeys = [...myReactionEvents] .filter((event) => !event.isRedacted()) - .map((event) => event.getRelation().key); + .map((event) => event.getRelation()?.key); shouldReact = !myReactionKeys.includes(reaction); } if (shouldReact) { diff --git a/src/components/views/settings/KeyboardShortcut.tsx b/src/components/views/settings/KeyboardShortcut.tsx index 4aad22995e..ea907655ea 100644 --- a/src/components/views/settings/KeyboardShortcut.tsx +++ b/src/components/views/settings/KeyboardShortcut.tsx @@ -46,7 +46,7 @@ interface IKeyboardShortcutProps { export const KeyboardShortcut: React.FC = ({ value, className = "mx_KeyboardShortcut" }) => { if (!value) return null; - const modifiersElement = []; + const modifiersElement: JSX.Element[] = []; if (value.ctrlOrCmdKey) { modifiersElement.push(); } else if (value.ctrlKey) { diff --git a/src/components/views/settings/Notifications.tsx b/src/components/views/settings/Notifications.tsx index 6aa7dca132..6d517fb635 100644 --- a/src/components/views/settings/Notifications.tsx +++ b/src/components/views/settings/Notifications.tsx @@ -41,7 +41,7 @@ import SdkConfig from "../../../SdkConfig"; import AccessibleButton from "../elements/AccessibleButton"; import TagComposer from "../elements/TagComposer"; import { objectClone } from "../../../utils/objects"; -import { arrayDiff } from "../../../utils/arrays"; +import { arrayDiff, filterBoolean } from "../../../utils/arrays"; import { clearAllNotifications, getLocalNotificationAccountDataEventType } from "../../../utils/notifications"; import { updateExistingPushRulesWithActions, @@ -167,7 +167,7 @@ const maximumVectorState = ( if (!definition.syncedRuleIds?.length) { return undefined; } - const vectorState = definition.syncedRuleIds.reduce((maxVectorState, ruleId) => { + const vectorState = definition.syncedRuleIds.reduce((maxVectorState, ruleId) => { // already set to maximum if (maxVectorState === VectorState.Loud) { return maxVectorState; @@ -345,7 +345,7 @@ export default class Notifications extends React.PureComponent { for (const rule of defaultRules[category]) { const definition: VectorPushRuleDefinition = VectorPushRulesDefinitions[rule.rule_id]; const vectorState = definition.ruleToVectorState(rule); - preparedNewState.vectorPushRules[category].push({ + preparedNewState.vectorPushRules[category]!.push({ ruleId: rule.rule_id, rule, vectorState, @@ -355,7 +355,7 @@ export default class Notifications extends React.PureComponent { } // Quickly sort the rules for display purposes - preparedNewState.vectorPushRules[category].sort((a, b) => { + preparedNewState.vectorPushRules[category]!.sort((a, b) => { let idxA = RULE_DISPLAY_ORDER.indexOf(a.ruleId); let idxB = RULE_DISPLAY_ORDER.indexOf(b.ruleId); @@ -367,7 +367,7 @@ export default class Notifications extends React.PureComponent { }); if (category === KEYWORD_RULE_CATEGORY) { - preparedNewState.vectorPushRules[category].push({ + preparedNewState.vectorPushRules[category]!.push({ ruleId: KEYWORD_RULE_ID, description: _t("Messages containing keywords"), vectorState: preparedNewState.vectorKeywordRuleInfo.vectorState, @@ -540,8 +540,8 @@ export default class Notifications extends React.PureComponent { private async setKeywords(keywords: string[], originalRules: IAnnotatedPushRule[]): Promise { try { // De-duplicate and remove empties - keywords = Array.from(new Set(keywords)).filter((k) => !!k); - const oldKeywords = Array.from(new Set(originalRules.map((r) => r.pattern))).filter((k) => !!k); + keywords = filterBoolean(Array.from(new Set(keywords))); + const oldKeywords = filterBoolean(Array.from(new Set(originalRules.map((r) => r.pattern)))); // Note: Technically because of the UI interaction (at the time of writing), the diff // will only ever be +/-1 so we don't really have to worry about efficiently handling @@ -555,13 +555,13 @@ export default class Notifications extends React.PureComponent { } } - let ruleVectorState = this.state.vectorKeywordRuleInfo.vectorState; + let ruleVectorState = this.state.vectorKeywordRuleInfo?.vectorState; if (ruleVectorState === VectorState.Off) { // When the current global keywords rule is OFF, we need to look at // the flavor of existing rules to apply the same actions // when creating the new rule. if (originalRules.length) { - ruleVectorState = PushRuleVectorState.contentRuleVectorStateKind(originalRules[0]); + ruleVectorState = PushRuleVectorState.contentRuleVectorStateKind(originalRules[0]) ?? undefined; } else { ruleVectorState = VectorState.On; // default } @@ -776,7 +776,7 @@ export default class Notifications extends React.PureComponent { /> ); - const fieldsetRows = this.state.vectorPushRules[category]?.map((r) => ( + const fieldsetRows = this.state.vectorPushRules?.[category]?.map((r) => (
{ )); - if (!rows.length) return null; // no targets to show + if (!rows?.length) return null; // no targets to show return (
diff --git a/src/components/views/settings/SetIdServer.tsx b/src/components/views/settings/SetIdServer.tsx index 50c1c6c452..f6f166d2d6 100644 --- a/src/components/views/settings/SetIdServer.tsx +++ b/src/components/views/settings/SetIdServer.tsx @@ -72,7 +72,7 @@ interface IProps { interface IState { defaultIdServer?: string; - currentClientIdServer: string; + currentClientIdServer?: string; idServer?: string; error?: string; busy: boolean; diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx index 6e455e5131..743cceff75 100644 --- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx @@ -402,14 +402,14 @@ export default class RolesRoomSettingsTab extends React.Component { {banned.map((member) => { const banEvent = member.events.member?.getContent(); const sender = room?.getMember(member.events.member.getSender()); - let bannedBy = member.events.member.getSender(); // start by falling back to mxid + let bannedBy = member.events.member?.getSender(); // start by falling back to mxid if (sender) bannedBy = sender.name; return ( ); diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx index a1c6e6075f..dc3bf9f408 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx @@ -61,7 +61,7 @@ interface IProps { interface IState { language: string; - spellCheckEnabled: boolean; + spellCheckEnabled?: boolean; spellCheckLanguages: string[]; haveIdServer: boolean; serverSupportsSeparateAddAndBind?: boolean; @@ -406,7 +406,7 @@ export default class GeneralUserSettingsTab extends React.Component {_t("Spell check")} - + {this.state.spellCheckEnabled && !IS_MAC && ( }); const [confirmed] = await finished; - return confirmed; + return !!confirmed; }; const useSignOut = ( diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx index 49067d4ec1..71d33171df 100644 --- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx @@ -61,7 +61,7 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> { private refreshMediaDevices = async (stream?: MediaStream): Promise => { this.setState({ - mediaDevices: await MediaDeviceHandler.getDevices(), + mediaDevices: (await MediaDeviceHandler.getDevices()) ?? null, [MediaDeviceKindEnum.AudioOutput]: MediaDeviceHandler.getAudioOutput(), [MediaDeviceKindEnum.AudioInput]: MediaDeviceHandler.getAudioInput(), [MediaDeviceKindEnum.VideoInput]: MediaDeviceHandler.getVideoInput(), @@ -105,8 +105,8 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> { } private renderDropdown(kind: MediaDeviceKindEnum, label: string): ReactNode { - const devices = this.state.mediaDevices[kind].slice(0); - if (devices.length === 0) return null; + const devices = this.state.mediaDevices?.[kind].slice(0); + if (!devices?.length) return null; const defaultDevice = MediaDeviceHandler.getDefaultDevice(devices); return ( diff --git a/src/components/views/toasts/VerificationRequestToast.tsx b/src/components/views/toasts/VerificationRequestToast.tsx index b62303076e..70c85ab674 100644 --- a/src/components/views/toasts/VerificationRequestToast.tsx +++ b/src/components/views/toasts/VerificationRequestToast.tsx @@ -77,7 +77,7 @@ export default class VerificationRequestToast extends React.PureComponent = ({ room, joinCallButtonDisabledTooltip, con // non-blank labels for the devices. let stream: MediaStream | null = null; try { - if (devices.audioinput.length > 0) { + if (devices!.audioinput.length > 0) { // Holding just an audio stream will be enough to get us all device labels, so // if video is muted, don't bother requesting video. stream = await navigator.mediaDevices.getUserMedia({ audio: true, - video: !videoMuted && devices.videoinput.length > 0 && { deviceId: videoInputId }, + video: !videoMuted && devices!.videoinput.length > 0 && { deviceId: videoInputId }, }); - } else if (devices.videoinput.length > 0) { + } else if (devices!.videoinput.length > 0) { // We have to resort to a video stream, even if video is supposed to be muted. stream = await navigator.mediaDevices.getUserMedia({ video: { deviceId: videoInputId } }); } @@ -182,7 +182,7 @@ export const Lobby: FC = ({ room, joinCallButtonDisabledTooltip, con stream = null; } - return [stream, devices.audioinput, devices.videoinput]; + return [stream, devices?.audioinput ?? [], devices?.videoinput ?? []]; }, [videoInputId, videoMuted], [null, [], []], diff --git a/src/dispatcher/payloads/ViewRoomErrorPayload.ts b/src/dispatcher/payloads/ViewRoomErrorPayload.ts index d30aa8893a..e7fbda0975 100644 --- a/src/dispatcher/payloads/ViewRoomErrorPayload.ts +++ b/src/dispatcher/payloads/ViewRoomErrorPayload.ts @@ -22,7 +22,7 @@ import { Action } from "../actions"; export interface ViewRoomErrorPayload extends Pick { action: Action.ViewRoomError; // eslint-disable-next-line camelcase - room_id: Room["roomId"]; + room_id: Room["roomId"] | null; // eslint-disable-next-line camelcase room_alias?: string; err?: MatrixError; diff --git a/src/editor/history.ts b/src/editor/history.ts index ec0b84ef18..351d9709ec 100644 --- a/src/editor/history.ts +++ b/src/editor/history.ts @@ -47,7 +47,7 @@ export default class HistoryManager { this.removedSinceLastPush = false; } - private shouldPush(inputType: string, diff: IDiff): boolean { + private shouldPush(inputType?: string, diff?: IDiff): boolean { // right now we can only push a step after // the input has been applied to the model, // so we can't push the state before something happened. @@ -102,7 +102,7 @@ export default class HistoryManager { } // needs to persist parts and caret position - public tryPush(model: EditorModel, caret: Caret, inputType: string, diff: IDiff): boolean { + public tryPush(model: EditorModel, caret: Caret, inputType?: string, diff?: IDiff): boolean { // ignore state restoration echos. // these respect the inputType values of the input event, // but are actually passed in from MessageEditor calling model.reset() diff --git a/src/editor/model.ts b/src/editor/model.ts index 695e544c22..2e30442e02 100644 --- a/src/editor/model.ts +++ b/src/editor/model.ts @@ -171,7 +171,7 @@ export default class EditorModel { this._autoComplete = null; this.autoCompletePartIdx = null; } - this.updateCallback(caret, inputType); + this.updateCallback?.(caret, inputType); } /** diff --git a/src/stores/AutoRageshakeStore.ts b/src/stores/AutoRageshakeStore.ts index f5e7bfe92c..e2e14b3a7e 100644 --- a/src/stores/AutoRageshakeStore.ts +++ b/src/stores/AutoRageshakeStore.ts @@ -119,7 +119,7 @@ export default class AutoRageshakeStore extends AsyncStoreWithClient { room_id: ev.getRoomId(), session_id: sessionId, device_id: wireContent.device_id, - user_id: ev.getSender(), + user_id: ev.getSender()!, sender_key: wireContent.sender_key, }; diff --git a/src/stores/ModalWidgetStore.ts b/src/stores/ModalWidgetStore.ts index 479ca4fe3f..1126df1f0e 100644 --- a/src/stores/ModalWidgetStore.ts +++ b/src/stores/ModalWidgetStore.ts @@ -62,14 +62,14 @@ export class ModalWidgetStore extends AsyncStoreWithClient { ): void => { if (this.modalInstance) return; this.openSourceWidgetId = sourceWidget.id; - this.openSourceWidgetRoomId = widgetRoomId; + this.openSourceWidgetRoomId = widgetRoomId ?? null; this.modalInstance = Modal.createDialog( ModalWidgetDialog, { widgetDefinition: { ...requestData }, widgetRoomId, sourceWidgetId: sourceWidget.id, - onFinished: (success: boolean, data?: IModalWidgetReturnData) => { + onFinished: (success, data) => { if (!success) { this.closeModalWidget(sourceWidget, widgetRoomId, { "m.exited": true }); } else { @@ -81,13 +81,17 @@ export class ModalWidgetStore extends AsyncStoreWithClient { this.modalInstance = null; }, }, - null, + undefined, /* priority = */ false, /* static = */ true, ); }; - public closeModalWidget = (sourceWidget: Widget, widgetRoomId?: string, data?: IModalWidgetReturnData): void => { + public closeModalWidget = ( + sourceWidget: Widget, + widgetRoomId: string | undefined, + data: IModalWidgetReturnData, + ): void => { if (!this.modalInstance) return; if (this.openSourceWidgetId === sourceWidget.id && this.openSourceWidgetRoomId === widgetRoomId) { this.openSourceWidgetId = null; diff --git a/src/stores/RoomScrollStateStore.ts b/src/stores/RoomScrollStateStore.ts index 61e89ed8de..8a7281e066 100644 --- a/src/stores/RoomScrollStateStore.ts +++ b/src/stores/RoomScrollStateStore.ts @@ -50,4 +50,4 @@ export class RoomScrollStateStore { if (window.mxRoomScrollStateStore === undefined) { window.mxRoomScrollStateStore = new RoomScrollStateStore(); } -export default window.mxRoomScrollStateStore; +export default window.mxRoomScrollStateStore!; diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index 47bc9b959b..dd87a97a57 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -395,7 +395,6 @@ export class RoomViewStore extends EventEmitter { roomId: payload.room_id, initialEventId: null, initialEventPixelOffset: null, - isInitialEventHighlighted: null, initialEventScrollIntoView: true, roomAlias: null, roomLoading: true, @@ -567,13 +566,13 @@ export class RoomViewStore extends EventEmitter { } } - private getInvitingUserId(roomId: string): string { + private getInvitingUserId(roomId: string): string | undefined { const cli = MatrixClientPeg.get(); const room = cli.getRoom(roomId); if (room?.getMyMembership() === "invite") { - const myMember = room.getMember(cli.getUserId()); + const myMember = room.getMember(cli.getSafeUserId()); const inviteEvent = myMember ? myMember.events.member : null; - return inviteEvent && inviteEvent.getSender(); + return inviteEvent?.getSender(); } } diff --git a/src/stores/right-panel/RightPanelStore.ts b/src/stores/right-panel/RightPanelStore.ts index 8e8155c4bc..caf85f28c8 100644 --- a/src/stores/right-panel/RightPanelStore.ts +++ b/src/stores/right-panel/RightPanelStore.ts @@ -278,28 +278,28 @@ export default class RightPanelStore extends ReadyWatchingStore { // (A nicer fix could be to indicate, that the right panel is loading if there is missing state data and re-emit if the data is available) switch (card.phase) { case RightPanelPhases.ThreadView: - if (!card.state.threadHeadEvent) { + if (!card.state?.threadHeadEvent) { logger.warn("removed card from right panel because of missing threadHeadEvent in card state"); } - return !!card.state.threadHeadEvent; + return !!card.state?.threadHeadEvent; case RightPanelPhases.RoomMemberInfo: case RightPanelPhases.SpaceMemberInfo: case RightPanelPhases.EncryptionPanel: - if (!card.state.member) { + if (!card.state?.member) { logger.warn("removed card from right panel because of missing member in card state"); } - return !!card.state.member; + return !!card.state?.member; case RightPanelPhases.Room3pidMemberInfo: case RightPanelPhases.Space3pidMemberInfo: - if (!card.state.memberInfoEvent) { + if (!card.state?.memberInfoEvent) { logger.warn("removed card from right panel because of missing memberInfoEvent in card state"); } - return !!card.state.memberInfoEvent; + return !!card.state?.memberInfoEvent; case RightPanelPhases.Widget: - if (!card.state.widgetId) { + if (!card.state?.widgetId) { logger.warn("removed card from right panel because of missing widgetId in card state"); } - return !!card.state.widgetId; + return !!card.state?.widgetId; } return true; } diff --git a/src/stores/spaces/SpaceStore.ts b/src/stores/spaces/SpaceStore.ts index 0723e30374..e516110a9c 100644 --- a/src/stores/spaces/SpaceStore.ts +++ b/src/stores/spaces/SpaceStore.ts @@ -168,7 +168,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { return this.rootSpaces; } - public get activeSpace(): SpaceKey | undefined { + public get activeSpace(): SpaceKey { return this._activeSpace; } @@ -1018,7 +1018,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { private onRoomStateMembers = (ev: MatrixEvent): void => { const room = this.matrixClient.getRoom(ev.getRoomId()); - const userId = ev.getStateKey(); + const userId = ev.getStateKey()!; if ( room?.isSpaceRoom() && // only consider space rooms DMRoomMap.shared().getDMRoomsForUserId(userId).length > 0 && // only consider members we have a DM with @@ -1049,9 +1049,9 @@ export class SpaceStoreClass extends AsyncStoreWithClient { private onRoomFavouriteChange(room: Room): void { if (this.enabledMetaSpaces.includes(MetaSpace.Favourites)) { if (room.tags[DefaultTagID.Favourite]) { - this.roomIdsBySpace.get(MetaSpace.Favourites).add(room.roomId); + this.roomIdsBySpace.get(MetaSpace.Favourites)?.add(room.roomId); } else { - this.roomIdsBySpace.get(MetaSpace.Favourites).delete(room.roomId); + this.roomIdsBySpace.get(MetaSpace.Favourites)?.delete(room.roomId); } this.emit(MetaSpace.Favourites); } @@ -1064,7 +1064,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { const homeRooms = this.roomIdsBySpace.get(MetaSpace.Home); if (this.showInHomeSpace(room)) { homeRooms?.add(room.roomId); - } else if (!this.roomIdsBySpace.get(MetaSpace.Orphans).has(room.roomId)) { + } else if (!this.roomIdsBySpace.get(MetaSpace.Orphans)?.has(room.roomId)) { this.roomIdsBySpace.get(MetaSpace.Home)?.delete(room.roomId); } @@ -1076,7 +1076,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } if (enabledMetaSpaces.has(MetaSpace.Orphans) || enabledMetaSpaces.has(MetaSpace.Home)) { - if (isDm && this.roomIdsBySpace.get(MetaSpace.Orphans).delete(room.roomId)) { + if (isDm && this.roomIdsBySpace.get(MetaSpace.Orphans)?.delete(room.roomId)) { this.emit(MetaSpace.Orphans); this.emit(MetaSpace.Home); } diff --git a/src/voice-broadcast/components/molecules/ConfirmListeBroadcastStopCurrent.tsx b/src/voice-broadcast/components/molecules/ConfirmListenBroadcastStopCurrent.tsx similarity index 88% rename from src/voice-broadcast/components/molecules/ConfirmListeBroadcastStopCurrent.tsx rename to src/voice-broadcast/components/molecules/ConfirmListenBroadcastStopCurrent.tsx index 39ab4339b4..0affa3beba 100644 --- a/src/voice-broadcast/components/molecules/ConfirmListeBroadcastStopCurrent.tsx +++ b/src/voice-broadcast/components/molecules/ConfirmListenBroadcastStopCurrent.tsx @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { defer } from "matrix-js-sdk/src/utils"; import React from "react"; import BaseDialog from "../../../components/views/dialogs/BaseDialog"; @@ -46,11 +45,7 @@ export const ConfirmListenBroadcastStopCurrentDialog: React.FC = ({ onFin }; export const showConfirmListenBroadcastStopCurrentDialog = async (): Promise => { - const { promise, resolve } = defer(); - - Modal.createDialog(ConfirmListenBroadcastStopCurrentDialog, { - onFinished: resolve, - }); - - return promise; + const { finished } = Modal.createDialog(ConfirmListenBroadcastStopCurrentDialog); + const [confirmed] = await finished; + return !!confirmed; }; diff --git a/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts b/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts index 660bf31865..1e4c02fe00 100644 --- a/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts +++ b/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts @@ -35,7 +35,7 @@ export const useVoiceBroadcastPlayback = ( position: number; timeLeft: number; }; - sender: RoomMember; + sender: RoomMember | null; liveness: VoiceBroadcastLiveness; playbackState: VoiceBroadcastPlaybackState; toggle(): void; diff --git a/src/voice-broadcast/hooks/useVoiceBroadcastRecording.tsx b/src/voice-broadcast/hooks/useVoiceBroadcastRecording.tsx index e4e0f9955c..f9df59ae41 100644 --- a/src/voice-broadcast/hooks/useVoiceBroadcastRecording.tsx +++ b/src/voice-broadcast/hooks/useVoiceBroadcastRecording.tsx @@ -44,7 +44,7 @@ const showStopBroadcastingDialog = async (): Promise => { button: _t("Yes, stop broadcast"), }); const [confirmed] = await finished; - return confirmed; + return !!confirmed; }; export const useVoiceBroadcastRecording = ( @@ -54,7 +54,7 @@ export const useVoiceBroadcastRecording = ( timeLeft: number; recordingState: VoiceBroadcastRecordingState; room: Room; - sender: RoomMember; + sender: RoomMember | null; stopRecording(): void; toggleRecording(): void; } => { diff --git a/src/voice-broadcast/index.ts b/src/voice-broadcast/index.ts index e397c342b5..3baabc35d3 100644 --- a/src/voice-broadcast/index.ts +++ b/src/voice-broadcast/index.ts @@ -32,7 +32,7 @@ export * from "./components/atoms/VoiceBroadcastHeader"; export * from "./components/atoms/VoiceBroadcastPlaybackControl"; export * from "./components/atoms/VoiceBroadcastRecordingConnectionError"; export * from "./components/atoms/VoiceBroadcastRoomSubtitle"; -export * from "./components/molecules/ConfirmListeBroadcastStopCurrent"; +export * from "./components/molecules/ConfirmListenBroadcastStopCurrent"; export * from "./components/molecules/VoiceBroadcastPlaybackBody"; export * from "./components/molecules/VoiceBroadcastSmallPlaybackBody"; export * from "./components/molecules/VoiceBroadcastPreRecordingPip"; diff --git a/test/components/structures/MessagePanel-test.tsx b/test/components/structures/MessagePanel-test.tsx index 7159c18e4d..f9b4597699 100644 --- a/test/components/structures/MessagePanel-test.tsx +++ b/test/components/structures/MessagePanel-test.tsx @@ -674,7 +674,7 @@ describe("MessagePanel", function () { // Increase the length of the loop here to test performance issues with // rendering - const events = []; + const events: MatrixEvent[] = []; for (let i = 0; i < 100; i++) { events.push( TestUtilsMatrix.mkEvent({ diff --git a/test/components/structures/RightPanel-test.tsx b/test/components/structures/RightPanel-test.tsx index 40ba8ac4ae..03b0a1cc08 100644 --- a/test/components/structures/RightPanel-test.tsx +++ b/test/components/structures/RightPanel-test.tsx @@ -35,6 +35,7 @@ import RightPanelStore from "../../../src/stores/right-panel/RightPanelStore"; import { UPDATE_EVENT } from "../../../src/stores/AsyncStore"; import { WidgetLayoutStore } from "../../../src/stores/widgets/WidgetLayoutStore"; import { SdkContextClass } from "../../../src/contexts/SDKContext"; +import { RoomPermalinkCreator } from "../../../src/utils/permalinks/Permalinks"; const RightPanelBase = wrapInMatrixClientContext(_RightPanel); @@ -110,7 +111,13 @@ describe("RightPanel", () => { }); await viewedRoom; - const { container } = render(); + const { container } = render( + , + ); expect(container.getElementsByClassName("mx_RoomSummaryCard")).toHaveLength(1); const switchedPhases = waitForRpsUpdate(); @@ -152,7 +159,13 @@ describe("RightPanel", () => { await spinUpStores(); // Run initial render with room 1, and also running lifecycle methods - const { container, rerender } = render(); + const { container, rerender } = render( + , + ); // Wait for RPS room 1 updates to fire const rpsUpdated = waitForRpsUpdate(); dis.dispatch({ @@ -172,7 +185,13 @@ describe("RightPanel", () => { room_id: "r2", }); await _rpsUpdated; - rerender(); + rerender( + , + ); // After all that setup, now to the interesting part... // We want to verify that as we change to room 2, we should always have diff --git a/test/components/views/elements/AppTile-test.tsx b/test/components/views/elements/AppTile-test.tsx index 99843d76e6..27ff5a1503 100644 --- a/test/components/views/elements/AppTile-test.tsx +++ b/test/components/views/elements/AppTile-test.tsx @@ -50,6 +50,7 @@ import { ElementWidgetCapabilities } from "../../../../src/stores/widgets/Elemen import { ElementWidget } from "../../../../src/stores/widgets/StopGapWidget"; import { WidgetMessagingStore } from "../../../../src/stores/widgets/WidgetMessagingStore"; import { ModuleRunner } from "../../../../src/modules/ModuleRunner"; +import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks"; describe("AppTile", () => { let cli: MatrixClient; @@ -153,7 +154,11 @@ describe("AppTile", () => { // Run initial render with room 1, and also running lifecycle methods const renderResult = render( - + , ); // Wait for RPS room 1 updates to fire @@ -178,7 +183,11 @@ describe("AppTile", () => { renderResult.rerender( - + , ); @@ -214,7 +223,11 @@ describe("AppTile", () => { // Run initial render with room 1, and also running lifecycle methods const renderResult = render( - + , ); // Wait for RPS room 1 updates to fire @@ -256,7 +269,11 @@ describe("AppTile", () => { }); renderResult.rerender( - + , ); await rpsUpdated2; diff --git a/test/components/views/settings/tabs/user/PreferencesUserSettingsTab-test.tsx b/test/components/views/settings/tabs/user/PreferencesUserSettingsTab-test.tsx index 379b1db8af..634164338d 100644 --- a/test/components/views/settings/tabs/user/PreferencesUserSettingsTab-test.tsx +++ b/test/components/views/settings/tabs/user/PreferencesUserSettingsTab-test.tsx @@ -68,7 +68,7 @@ describe("PreferencesUserSettingsTab", () => { const expectSetValueToHaveBeenCalled = ( name: string, - roomId: string | undefined, + roomId: string | null, level: SettingLevel, value: boolean, ) => expect(SettingsStore.setValue).toHaveBeenCalledWith(name, roomId, level, value);