diff --git a/package.json b/package.json index 0318f4ac24..01c0db98ed 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "0.0.1", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", - "matrix-widget-api": "^1.1.1", + "matrix-widget-api": "^1.2.0", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", "pako": "^2.0.3", diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index d389345af8..c14e081a80 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -259,7 +259,7 @@ class LoggedInView extends React.Component { isItemCollapsed: (domNode) => { return domNode.classList.contains("mx_LeftPanel_minimized"); }, - handler: this.resizeHandler.current, + handler: this.resizeHandler.current ?? undefined, }; const resizer = new Resizer(this._resizeContainer.current, CollapseDistributor, collapseConfig); resizer.setClassNames({ diff --git a/src/components/structures/RightPanel.tsx b/src/components/structures/RightPanel.tsx index 9793289416..f6ad289318 100644 --- a/src/components/structures/RightPanel.tsx +++ b/src/components/structures/RightPanel.tsx @@ -90,7 +90,7 @@ export default class RightPanel extends React.Component { } public static getDerivedStateFromProps(props: IProps): Partial { - let currentCard: IRightPanelCard; + let currentCard: IRightPanelCard | undefined; if (props.room) { currentCard = RightPanelStore.instance.currentCardForRoom(props.room.roomId); } @@ -111,7 +111,7 @@ export default class RightPanel extends React.Component { this.delayedUpdate(); } else if ( this.state.phase === RightPanelPhases.RoomMemberInfo && - member.userId === this.state.cardState.member.userId + member.userId === this.state.cardState.member?.userId ) { // refresh the member info (e.g. new power level) this.delayedUpdate(); @@ -136,7 +136,7 @@ export default class RightPanel extends React.Component { }); } else if ( this.state.phase === RightPanelPhases.EncryptionPanel && - this.state.cardState.verificationRequest?.pending + this.state.cardState?.verificationRequest?.pending ) { // When the user clicks close on the encryption panel cancel the pending request first if any this.state.cardState.verificationRequest.cancel(); @@ -171,8 +171,8 @@ export default class RightPanel extends React.Component { case RightPanelPhases.SpaceMemberList: card = ( { case RightPanelPhases.RoomMemberInfo: case RightPanelPhases.SpaceMemberInfo: case RightPanelPhases.EncryptionPanel: { - const roomMember = cardState.member instanceof RoomMember ? cardState.member : undefined; + const roomMember = cardState?.member instanceof RoomMember ? cardState.member : undefined; card = ( ); break; } case RightPanelPhases.Room3pidMemberInfo: case RightPanelPhases.Space3pidMemberInfo: - card = ; + card = ; break; case RightPanelPhases.NotificationPanel: @@ -240,10 +240,10 @@ export default class RightPanel extends React.Component { room={this.props.room} resizeNotifier={this.props.resizeNotifier} onClose={this.onClose} - mxEvent={cardState.threadHeadEvent} - initialEvent={cardState.initialEvent} - isInitialEventHighlighted={cardState.isInitialEventHighlighted} - initialEventScrollIntoView={cardState.initialEventScrollIntoView} + mxEvent={cardState?.threadHeadEvent} + initialEvent={cardState?.initialEvent} + isInitialEventHighlighted={cardState?.isInitialEventHighlighted} + initialEventScrollIntoView={cardState?.initialEventScrollIntoView} permalinkCreator={this.props.permalinkCreator} e2eStatus={this.props.e2eStatus} /> @@ -273,7 +273,7 @@ export default class RightPanel extends React.Component { break; case RightPanelPhases.Widget: - card = ; + card = ; break; } diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 68f64aa622..ccb22253af 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -132,7 +132,7 @@ if (DEBUG) { } interface IRoomProps { - threepidInvite: IThreepidInvite; + threepidInvite?: IThreepidInvite; oobData?: IOOBData; resizeNotifier: ResizeNotifier; @@ -606,11 +606,11 @@ export class RoomView extends React.Component { return; } - const roomId = this.context.roomViewStore.getRoomId(); - const room = this.context.client.getRoom(roomId); + const roomId = this.context.roomViewStore.getRoomId() ?? null; + const room = this.context.client?.getRoom(roomId ?? undefined) ?? undefined; const newState: Partial = { - roomId, + roomId: roomId ?? undefined, roomAlias: this.context.roomViewStore.getRoomAlias(), roomLoading: this.context.roomViewStore.isRoomLoading(), roomLoadError: this.context.roomViewStore.getRoomLoadError(), @@ -624,8 +624,8 @@ export class RoomView extends React.Component { showAvatarChanges: SettingsStore.getValue("showAvatarChanges", roomId), showDisplaynameChanges: SettingsStore.getValue("showDisplaynameChanges", roomId), wasContextSwitch: this.context.roomViewStore.getWasContextSwitch(), - mainSplitContentType: room === null ? undefined : this.getMainSplitContentType(room), - initialEventId: null, // default to clearing this, will get set later in the method if needed + mainSplitContentType: room ? this.getMainSplitContentType(room) : undefined, + initialEventId: undefined, // default to clearing this, will get set later in the method if needed showRightPanel: this.context.rightPanelStore.isOpenForRoom(roomId), activeCall: CallStore.instance.getActiveCall(roomId), }; @@ -655,12 +655,11 @@ export class RoomView extends React.Component { // The rest will be lost for now, until the aggregation API on the server // becomes available to fetch a whole thread if (!initialEvent) { - initialEvent = await fetchInitialEvent(this.context.client, roomId, initialEventId); + initialEvent = (await fetchInitialEvent(this.context.client, roomId, initialEventId)) ?? undefined; } - // If we have an initial event, we want to reset the event pixel offset to ensure it ends up - // visible - newState.initialEventPixelOffset = null; + // If we have an initial event, we want to reset the event pixel offset to ensure it ends up visible + newState.initialEventPixelOffset = undefined; const thread = initialEvent?.getThread(); if (thread && !initialEvent?.isThreadRoot) { @@ -709,7 +708,7 @@ export class RoomView extends React.Component { if (!initial && this.state.shouldPeek && !newState.shouldPeek) { // Stop peeking because we have joined this room now - this.context.client.stopPeeking(); + this.context.client?.stopPeeking(); } // Temporary logging to diagnose https://github.com/vector-im/element-web/issues/4307 @@ -825,7 +824,7 @@ export class RoomView extends React.Component { } } - private setupRoom(room: Room, roomId: string, joining: boolean, shouldPeek: boolean): void { + private setupRoom(room: Room | undefined, roomId: string | undefined, joining: boolean, shouldPeek: boolean): void { // if this is an unknown room then we're in one of three states: // - This is a room we can peek into (search engine) (we can /peek) // - This is a room we can publicly join or were invited to. (we can /join) @@ -1504,7 +1503,7 @@ export class RoomView extends React.Component { private updateDMState(): void { const room = this.state.room; - if (room.getMyMembership() != "join") { + if (room?.getMyMembership() !== "join") { return; } const dmInviter = room.getDMInviter(); @@ -1564,7 +1563,7 @@ export class RoomView extends React.Component { ); private onMessageListScroll = (): void => { - if (this.messagePanel.isAtEndOfLiveTimeline()) { + if (this.messagePanel?.isAtEndOfLiveTimeline()) { this.setState({ numUnreadMessages: 0, atEndOfLiveTimeline: true, @@ -1740,7 +1739,7 @@ export class RoomView extends React.Component { this.setState( { timelineRenderingType: TimelineRenderingType.Room, - search: null, + search: undefined, }, resolve, ); @@ -1760,20 +1759,20 @@ export class RoomView extends React.Component { }); } else { // Otherwise we have to jump manually - this.messagePanel.jumpToLiveTimeline(); + this.messagePanel?.jumpToLiveTimeline(); dis.fire(Action.FocusSendMessageComposer); } }; // jump up to wherever our read marker is private jumpToReadMarker = (): void => { - this.messagePanel.jumpToReadMarker(); + this.messagePanel?.jumpToReadMarker(); }; // update the read marker to match the read-receipt private forgetReadMarker = (ev: ButtonEvent): void => { ev.stopPropagation(); - this.messagePanel.forgetReadMarker(); + this.messagePanel?.forgetReadMarker(); }; // decide whether or not the top 'unread messages' bar should be shown @@ -1791,7 +1790,7 @@ export class RoomView extends React.Component { // get the current scroll position of the room, so that it can be // restored when we switch back to it. // - private getScrollState(): ScrollState { + private getScrollState(): ScrollState | null { const messagePanel = this.messagePanel; if (!messagePanel) return null; @@ -1845,7 +1844,7 @@ export class RoomView extends React.Component { * We pass it down to the scroll panel. */ public handleScrollKey = (ev: React.KeyboardEvent | KeyboardEvent): void => { - let panel: ScrollPanel | TimelinePanel; + let panel: ScrollPanel | TimelinePanel | undefined; if (this.searchResultsPanel.current) { panel = this.searchResultsPanel.current; } else if (this.messagePanel) { @@ -1858,7 +1857,7 @@ export class RoomView extends React.Component { /** * get any current call for this room */ - private getCallForRoom(): MatrixCall { + private getCallForRoom(): MatrixCall | null { if (!this.state.room) { return null; } @@ -1920,7 +1919,7 @@ export class RoomView extends React.Component { } private renderLocalRoomCreateLoader(localRoom: LocalRoom): ReactElement { - const names = this.state.room.getDefaultRoomName(this.context.client.getUserId()); + const names = this.state.room.getDefaultRoomName(this.context.client.getSafeUserId()); return ( @@ -1992,7 +1991,7 @@ export class RoomView extends React.Component { ); } else { - let inviterName = undefined; + let inviterName: string | undefined; if (this.props.oobData) { inviterName = this.props.oobData.inviterName; } @@ -2058,12 +2057,12 @@ export class RoomView extends React.Component { ); } else { - const myUserId = this.context.client.credentials.userId; + const myUserId = this.context.client.getSafeUserId(); const myMember = this.state.room.getMember(myUserId); const inviteEvent = myMember ? myMember.events.member : null; let inviterName = _t("Unknown"); if (inviteEvent) { - inviterName = inviteEvent.sender ? inviteEvent.sender.name : inviteEvent.getSender(); + inviterName = inviteEvent.sender?.name ?? inviteEvent.getSender(); } // We deliberately don't try to peek into invites, even if we have permission to peek @@ -2140,7 +2139,7 @@ export class RoomView extends React.Component { const showRoomUpgradeBar = roomVersionRecommendation && roomVersionRecommendation.needsUpgrade && - this.state.room.userMayUpgradeRoom(this.context.client.credentials.userId); + this.state.room.userMayUpgradeRoom(this.context.client.getSafeUserId()); const hiddenHighlightCount = this.getHiddenHighlightCount(); @@ -2160,7 +2159,7 @@ export class RoomView extends React.Component { } else if (myMembership !== "join") { // We do have a room object for this room, but we're not currently in it. // We may have a 3rd party invite to it. - let inviterName = undefined; + let inviterName: string | undefined; if (this.props.oobData) { inviterName = this.props.oobData.inviterName; } @@ -2207,6 +2206,7 @@ export class RoomView extends React.Component { space={this.state.room} justCreatedOpts={this.props.justCreatedOpts} resizeNotifier={this.props.resizeNotifier} + permalinkCreator={this.permalinkCreator} onJoinButtonClicked={this.onJoinButtonClicked} onRejectButtonClicked={ this.props.threepidInvite @@ -2220,7 +2220,7 @@ export class RoomView extends React.Component { const auxPanel = ( @@ -2330,7 +2330,7 @@ export class RoomView extends React.Component { permalinkCreator={this.permalinkCreator} e2eStatus={this.state.e2eStatus} /> - ) : null; + ) : undefined; const timelineClasses = classNames("mx_RoomView_timeline", { mx_RoomView_timeline_rr_enabled: this.state.showReadReceipts, @@ -2344,14 +2344,16 @@ export class RoomView extends React.Component { const showChatEffects = SettingsStore.getValue("showChatEffects"); let mainSplitBody: JSX.Element | undefined; - let mainSplitContentClassName: string; + let mainSplitContentClassName: string | undefined; // Decide what to show in the main split switch (this.state.mainSplitContentType) { case MainSplitContentType.Timeline: mainSplitContentClassName = "mx_MainSplit_timeline"; mainSplitBody = ( <> - + {this.roomViewBody.current && ( + + )} {auxPanel}
@@ -2372,7 +2374,7 @@ export class RoomView extends React.Component { <> @@ -2426,7 +2428,7 @@ export class RoomView extends React.Component { onAppsClick = null; onForgetClick = null; onSearchClick = null; - if (this.state.room.canInvite(this.context.client.credentials.userId)) { + if (this.state.room.canInvite(this.context.client.getSafeUserId())) { onInviteClick = this.onInviteClick; } viewingCall = true; diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 10a603e598..37fe63fc03 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -18,7 +18,7 @@ import { EventType, RoomType } from "matrix-js-sdk/src/@types/event"; import { JoinRule, Preset } from "matrix-js-sdk/src/@types/partials"; import { logger } from "matrix-js-sdk/src/logger"; import { Room, RoomEvent } from "matrix-js-sdk/src/models/room"; -import React, { RefObject, useCallback, useContext, useRef, useState } from "react"; +import React, { MutableRefObject, useCallback, useContext, useRef, useState } from "react"; import MatrixClientContext from "../../contexts/MatrixClientContext"; import createRoom, { IOpts } from "../../createRoom"; @@ -77,11 +77,13 @@ import { ChevronFace, ContextMenuButton, useContextMenu } from "./ContextMenu"; import MainSplit from "./MainSplit"; import RightPanel from "./RightPanel"; import SpaceHierarchy, { showRoom } from "./SpaceHierarchy"; +import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks"; interface IProps { space: Room; justCreatedOpts?: IOpts; resizeNotifier: ResizeNotifier; + permalinkCreator: RoomPermalinkCreator; onJoinButtonClicked(): void; onRejectButtonClicked(): void; } @@ -112,7 +114,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => { let contextMenu: JSX.Element | null = null; if (menuDisplayed) { - const rect = handle.current.getBoundingClientRect(); + const rect = handle.current!.getBoundingClientRect(); contextMenu = ( = ({ space }) => { const SpaceLanding: React.FC<{ space: Room }> = ({ space }) => { const cli = useContext(MatrixClientContext); const myMembership = useMyRoomMembership(space); - const userId = cli.getUserId(); + const userId = cli.getSafeUserId(); const storeIsShowingSpaceMembers = useCallback( () => @@ -458,7 +460,7 @@ const SpaceSetupPublicShare: React.FC = ({ const SpaceSetupPrivateScope: React.FC<{ space: Room; - justCreatedOpts: IOpts; + justCreatedOpts?: IOpts; onFinished(createRooms: boolean): void; }> = ({ space, justCreatedOpts, onFinished }) => { return ( @@ -509,7 +511,7 @@ const SpaceSetupPrivateInvite: React.FC<{ const [busy, setBusy] = useState(false); const [error, setError] = useState(""); const numFields = 3; - const fieldRefs: RefObject[] = [useRef(), useRef(), useRef()]; + const fieldRefs: MutableRefObject[] = [useRef(), useRef(), useRef()]; const [emailAddresses, setEmailAddress] = useStateArray(numFields, ""); const fields = new Array(numFields).fill(0).map((x, i) => { const name = "emailAddress" + i; @@ -647,7 +649,7 @@ export default class SpaceRoomView extends React.PureComponent { if (showSetup) { phase = - this.props.justCreatedOpts.createOpts.preset === Preset.PublicChat + this.props.justCreatedOpts!.createOpts?.preset === Preset.PublicChat ? Phase.PublicCreateRooms : Phase.PrivateScope; } @@ -817,8 +819,12 @@ export default class SpaceRoomView extends React.PureComponent { public render(): React.ReactNode { const rightPanel = this.state.showRightPanel && this.state.phase === Phase.Landing ? ( - - ) : null; + + ) : undefined; return (
diff --git a/src/hooks/usePublicRoomDirectory.ts b/src/hooks/usePublicRoomDirectory.ts index c75cffd825..d58b799d93 100644 --- a/src/hooks/usePublicRoomDirectory.ts +++ b/src/hooks/usePublicRoomDirectory.ts @@ -103,11 +103,11 @@ export const usePublicRoomDirectory = (): { if (query || roomTypes) { opts.filter = { generic_search_term: query, - room_types: (await MatrixClientPeg.get().doesServerSupportUnstableFeature( - "org.matrix.msc3827.stable", - )) - ? Array.from(roomTypes) - : undefined, + room_types: + roomTypes && + (await MatrixClientPeg.get().doesServerSupportUnstableFeature("org.matrix.msc3827.stable")) + ? Array.from(roomTypes) + : undefined, }; } diff --git a/src/utils/DMRoomMap.ts b/src/utils/DMRoomMap.ts index 245c2e77be..97c4b6b11c 100644 --- a/src/utils/DMRoomMap.ts +++ b/src/utils/DMRoomMap.ts @@ -189,8 +189,11 @@ export default class DMRoomMap { if (!this.roomToUser) return {}; // No rooms means no map. return Object.keys(this.roomToUser) .map((r) => ({ userId: this.getUserIdForRoomId(r), room: this.matrixClient.getRoom(r) })) - .filter((r) => r.userId && r.room && r.room.getInvitedAndJoinedMemberCount() === 2) - .reduce((obj, r) => (obj[r.userId] = r.room) && obj, {} as Record); + .filter((r) => r.userId && r.room?.getInvitedAndJoinedMemberCount() === 2) + .reduce((obj, r) => { + obj[r.userId] = r.room; + return obj; + }, {} as Record); } /** diff --git a/src/utils/MultiInviter.ts b/src/utils/MultiInviter.ts index 2ea1a73bd7..45de0e2ca0 100644 --- a/src/utils/MultiInviter.ts +++ b/src/utils/MultiInviter.ts @@ -141,8 +141,8 @@ export default class MultiInviter { return this.completionStates[addr]; } - public getErrorText(addr: string): string { - return this.errors[addr] ? this.errors[addr].errorText : null; + public getErrorText(addr: string): string | null { + return this.errors[addr]?.errorText ?? null; } private async inviteToRoom(roomId: string, addr: string, ignoreProfile = false): Promise<{}> { diff --git a/src/utils/UrlUtils.ts b/src/utils/UrlUtils.ts index 9c4b81ad3e..d3e1a9929c 100644 --- a/src/utils/UrlUtils.ts +++ b/src/utils/UrlUtils.ts @@ -37,7 +37,7 @@ export function abbreviateUrl(u: string): string { return u; } -export function unabbreviateUrl(u: string): string { +export function unabbreviateUrl(u?: string): string { if (!u) return ""; let longUrl = u; diff --git a/src/utils/WidgetUtils.ts b/src/utils/WidgetUtils.ts index c47086235a..986d050b0c 100644 --- a/src/utils/WidgetUtils.ts +++ b/src/utils/WidgetUtils.ts @@ -450,7 +450,7 @@ export default class WidgetUtils { oobRoomName?: string, ): Promise { const domain = Jitsi.getInstance().preferredDomain; - const auth = await Jitsi.getInstance().getJitsiAuth(); + const auth = (await Jitsi.getInstance().getJitsiAuth()) ?? undefined; const widgetId = randomString(24); // Must be globally unique let confId; diff --git a/src/utils/dm/findDMRoom.ts b/src/utils/dm/findDMRoom.ts index 7196b42fee..09e7a63417 100644 --- a/src/utils/dm/findDMRoom.ts +++ b/src/utils/dm/findDMRoom.ts @@ -29,14 +29,11 @@ import { findDMForUser } from "./findDMForUser"; */ export function findDMRoom(client: MatrixClient, targets: Member[]): Room | null { const targetIds = targets.map((t) => t.userId); - let existingRoom: Room | undefined; + let existingRoom: Room | null; if (targetIds.length === 1) { - existingRoom = findDMForUser(client, targetIds[0]); + existingRoom = findDMForUser(client, targetIds[0]) ?? null; } else { existingRoom = DMRoomMap.shared().getDMRoomForIdentifiers(targetIds); } - if (existingRoom) { - return existingRoom; - } - return null; + return existingRoom; } diff --git a/src/utils/exportUtils/Exporter.ts b/src/utils/exportUtils/Exporter.ts index c01f5ac3ee..74e1e80f64 100644 --- a/src/utils/exportUtils/Exporter.ts +++ b/src/utils/exportUtils/Exporter.ts @@ -135,7 +135,7 @@ export default abstract class Exporter { let limit: number; switch (this.exportType) { case ExportType.LastNMessages: - limit = this.exportOptions.numberOfMessages; + limit = this.exportOptions.numberOfMessages!; break; case ExportType.Timeline: limit = 40; @@ -221,11 +221,11 @@ export default abstract class Exporter { return events; } - protected async getMediaBlob(event: MatrixEvent): Promise { - let blob: Blob; + protected async getMediaBlob(event: MatrixEvent): Promise { + let blob: Blob | undefined; try { const isEncrypted = event.isEncrypted(); - const content: IMediaEventContent = event.getContent(); + const content = event.getContent(); const shouldDecrypt = isEncrypted && content.hasOwnProperty("file") && event.getType() !== "m.sticker"; if (shouldDecrypt) { blob = await decryptFile(content.file); diff --git a/src/utils/exportUtils/JSONExport.ts b/src/utils/exportUtils/JSONExport.ts index e1b41b6f82..2f629d5a2c 100644 --- a/src/utils/exportUtils/JSONExport.ts +++ b/src/utils/exportUtils/JSONExport.ts @@ -45,7 +45,7 @@ export default class JSONExporter extends Exporter { protected createJSONString(): string { const exportDate = formatFullDateNoDayNoTime(new Date()); const creator = this.room.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender(); - const creatorName = this.room?.getMember(creator)?.rawDisplayName || creator; + const creatorName = (creator && this.room?.getMember(creator)?.rawDisplayName) || creator; const topic = this.room.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent()?.topic || ""; const exporter = this.client.getUserId()!; const exporterName = this.room?.getMember(exporter)?.rawDisplayName || exporter; diff --git a/src/utils/leave-behaviour.ts b/src/utils/leave-behaviour.ts index b6b1958e37..68e7e49cbc 100644 --- a/src/utils/leave-behaviour.ts +++ b/src/utils/leave-behaviour.ts @@ -19,6 +19,7 @@ import React, { ReactNode } from "react"; import { EventStatus } from "matrix-js-sdk/src/models/event-status"; import { MatrixEventEvent } from "matrix-js-sdk/src/models/event"; import { Room } from "matrix-js-sdk/src/models/room"; +import { MatrixError } from "matrix-js-sdk/src/matrix"; import Modal, { IHandle } from "../Modal"; import Spinner from "../components/views/elements/Spinner"; @@ -87,7 +88,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = ), ); - let results: { [roomId: string]: Error & { errcode?: string; message: string; data?: Record } } = {}; + let results: { [roomId: string]: Error | MatrixError | null } = {}; if (!leavingAllVersions) { try { await cli.leave(roomId); @@ -104,7 +105,9 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = } if (retry) { - const limitExceededError = Object.values(results).find((e) => e?.errcode === "M_LIMIT_EXCEEDED"); + const limitExceededError = Object.values(results).find( + (e) => (e as MatrixError)?.errcode === "M_LIMIT_EXCEEDED", + ) as MatrixError; if (limitExceededError) { await sleep(limitExceededError.data.retry_after_ms ?? 100); return leaveRoomBehaviour(roomId, false, false); @@ -117,9 +120,9 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = if (errors.length > 0) { const messages: ReactNode[] = []; for (const roomErr of errors) { - const err = roomErr[1]; // [0] is the roomId + const err = roomErr[1] as MatrixError; // [0] is the roomId let message = _t("Unexpected server error trying to leave the room"); - if (err.errcode && err.message) { + if (err?.errcode && err.message) { if (err.errcode === "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM") { Modal.createDialog(ErrorDialog, { title: _t("Can't leave Server Notices room"), @@ -130,7 +133,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = }); return; } - message = results[roomId].message; + message = results[roomId]!.message; } messages.push(message, React.createElement("BR")); // createElement to avoid using a tsx file in utils } diff --git a/src/utils/location/map.ts b/src/utils/location/map.ts index b0434d76cd..8fe698b5eb 100644 --- a/src/utils/location/map.ts +++ b/src/utils/location/map.ts @@ -79,7 +79,7 @@ export const makeMapSiteLink = (coords: GeolocationCoordinates): string => { ); }; -export const createMapSiteLinkFromEvent = (event: MatrixEvent): string => { +export const createMapSiteLinkFromEvent = (event: MatrixEvent): string | null => { const content = event.getContent(); const mLocation = content[M_LOCATION.name]; if (mLocation !== undefined) { diff --git a/src/utils/permalinks/Permalinks.ts b/src/utils/permalinks/Permalinks.ts index b9ee13334c..d2981905e3 100644 --- a/src/utils/permalinks/Permalinks.ts +++ b/src/utils/permalinks/Permalinks.ts @@ -192,7 +192,7 @@ export class RoomPermalinkCreator { isHostInRegex(domain, this.allowedHostsRegexps) ); }); - const maxEntry = allowedEntries.reduce( + const maxEntry = allowedEntries.reduce<[string | null, number]>( (max, entry) => { return entry[1] > max[1] ? entry : max; }, @@ -329,7 +329,7 @@ export function tryTransformEntityToPermalink(entity: string): string | null { if (permalinkParts.roomIdOrAlias) { const eventIdPart = permalinkParts.eventId ? `/${permalinkParts.eventId}` : ""; let pl = matrixtoBaseUrl + `/#/${permalinkParts.roomIdOrAlias}${eventIdPart}`; - if (permalinkParts.viaServers.length > 0) { + if (permalinkParts.viaServers?.length) { pl += new MatrixToPermalinkConstructor().encodeServerCandidates(permalinkParts.viaServers); } return pl; @@ -376,7 +376,7 @@ export function tryTransformPermalinkToLocalHref(permalink: string): string { if (permalinkParts.roomIdOrAlias) { const eventIdPart = permalinkParts.eventId ? `/${permalinkParts.eventId}` : ""; permalink = `#/room/${permalinkParts.roomIdOrAlias}${eventIdPart}`; - if (permalinkParts.viaServers.length > 0) { + if (permalinkParts.viaServers?.length) { permalink += new MatrixToPermalinkConstructor().encodeServerCandidates(permalinkParts.viaServers); } } else if (permalinkParts.userId) { @@ -475,7 +475,7 @@ function isHostnameIpAddress(hostname: string): boolean { return isIp(hostname); } -export const calculateRoomVia = (room: Room): string[] => { +export const calculateRoomVia = (room: Room): string[] | undefined => { const permalinkCreator = new RoomPermalinkCreator(room); permalinkCreator.load(); return permalinkCreator.serverCandidates; diff --git a/src/utils/space.tsx b/src/utils/space.tsx index 2c076436d4..fa480f6209 100644 --- a/src/utils/space.tsx +++ b/src/utils/space.tsx @@ -84,7 +84,7 @@ export const showCreateNewRoom = async (space: Room, type?: RoomType): Promise diff --git a/yarn.lock b/yarn.lock index 50dadd073b..9f987d886c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6493,7 +6493,7 @@ matrix-web-i18n@^1.3.0: "@babel/traverse" "^7.18.5" walk "^2.3.15" -matrix-widget-api@^1.0.0, matrix-widget-api@^1.1.1: +matrix-widget-api@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.1.1.tgz#d3fec45033d0cbc14387a38ba92dac4dbb1be962" integrity sha512-gNSgmgSwvOsOcWK9k2+tOhEMYBiIMwX95vMZu0JqY7apkM02xrOzUBuPRProzN8CnbIALH7e3GAhatF6QCNvtA== @@ -6501,6 +6501,14 @@ matrix-widget-api@^1.0.0, matrix-widget-api@^1.1.1: "@types/events" "^3.0.0" events "^3.2.0" +matrix-widget-api@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.2.0.tgz#ad98796f9879c1db1ef04301f6680ba01b15a6b5" + integrity sha512-BkBTREtXjCUM3Kx4UBgDmKoz39w7AXfIjBIC/jISBdcJkg8upFUhpIy+zUrSCIrmfO2Ke8LOsSoFoQkOyhqGxQ== + dependencies: + "@types/events" "^3.0.0" + events "^3.2.0" + md5@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"