Conform more of the codebase to strictNullChecks (#11134)

pull/28788/head^2
Michael Telatynski 2023-06-27 17:39:56 +01:00 committed by GitHub
parent 3d886de5b0
commit e1cad41bc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 44 additions and 36 deletions

View File

@ -71,7 +71,7 @@ export interface IMatrixClientPeg {
* *
* @returns {string} The homeserver name, if present. * @returns {string} The homeserver name, if present.
*/ */
getHomeserverName(): string | null; getHomeserverName(): string;
get(): MatrixClient | null; get(): MatrixClient | null;
safeGet(): MatrixClient; safeGet(): MatrixClient;
@ -358,10 +358,8 @@ class MatrixClientPegClass implements IMatrixClientPeg {
}; };
} }
public getHomeserverName(): string | null { public getHomeserverName(): string {
if (!this.matrixClient) return null; const matches = /^@[^:]+:(.+)$/.exec(this.safeGet().getSafeUserId());
const matches = /^@[^:]+:(.+)$/.exec(this.matrixClient.getSafeUserId());
if (matches === null || matches.length < 1) { if (matches === null || matches.length < 1) {
throw new Error("Failed to derive homeserver name from user ID!"); throw new Error("Failed to derive homeserver name from user ID!");
} }

View File

@ -234,9 +234,11 @@ async function localPagination(
): Promise<ISeshatSearchResults> { ): Promise<ISeshatSearchResults> {
const eventIndex = EventIndexPeg.get(); const eventIndex = EventIndexPeg.get();
const searchArgs = searchResult.seshatQuery; if (!searchResult.seshatQuery) {
throw new Error("localSearchProcess must be called first");
}
const localResult = await eventIndex!.search(searchArgs); const localResult = await eventIndex!.search(searchResult.seshatQuery);
if (!localResult) { if (!localResult) {
throw new Error("Local search pagination failed"); throw new Error("Local search pagination failed");
} }
@ -408,7 +410,7 @@ function combineEvents(
): IResultRoomEvents { ): IResultRoomEvents {
const response = {} as IResultRoomEvents; const response = {} as IResultRoomEvents;
const cachedEvents = previousSearchResult.cachedEvents; const cachedEvents = previousSearchResult.cachedEvents ?? [];
let oldestEventFrom = previousSearchResult.oldestEventFrom; let oldestEventFrom = previousSearchResult.oldestEventFrom;
response.highlights = previousSearchResult.highlights; response.highlights = previousSearchResult.highlights;
@ -564,7 +566,7 @@ async function combinedPagination(
// Fetch events from the server if we have a token for it and if it's the // Fetch events from the server if we have a token for it and if it's the
// local indexes turn or the local index has exhausted its results. // local indexes turn or the local index has exhausted its results.
if (searchResult.serverSideNextBatch && (oldestEventFrom === "local" || !searchArgs.next_batch)) { if (searchResult.serverSideNextBatch && (oldestEventFrom === "local" || !searchArgs.next_batch)) {
const body = { body: searchResult._query, next_batch: searchResult.serverSideNextBatch }; const body = { body: searchResult._query!, next_batch: searchResult.serverSideNextBatch };
serverSideResult = await client.search(body); serverSideResult = await client.search(body);
} }

View File

@ -1704,7 +1704,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
} catch (error) { } catch (error) {
logger.error(`Failed to reject invite: ${error}`); logger.error(`Failed to reject invite: ${error}`);
const msg = error.message ? error.message : JSON.stringify(error); const msg = error instanceof Error ? error.message : JSON.stringify(error);
Modal.createDialog(ErrorDialog, { Modal.createDialog(ErrorDialog, {
title: _t("Failed to reject invite"), title: _t("Failed to reject invite"),
description: msg, description: msg,

View File

@ -700,7 +700,7 @@ export default class ScrollPanel extends React.Component<IProps> {
const trackedNode = this.getTrackedNode(); const trackedNode = this.getTrackedNode();
if (trackedNode) { if (trackedNode) {
const newBottomOffset = this.topFromBottom(trackedNode); const newBottomOffset = this.topFromBottom(trackedNode);
const bottomDiff = newBottomOffset - scrollState.bottomOffset; const bottomDiff = newBottomOffset - (scrollState.bottomOffset ?? 0);
this.bottomGrowth += bottomDiff; this.bottomGrowth += bottomDiff;
scrollState.bottomOffset = newBottomOffset; scrollState.bottomOffset = newBottomOffset;
const newHeight = `${this.getListHeight()}px`; const newHeight = `${this.getListHeight()}px`;

View File

@ -599,7 +599,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
if (!this.timelineWindow?.canPaginate(dir)) { if (!this.timelineWindow?.canPaginate(dir)) {
debuglog("can't", dir, "paginate any further"); debuglog("can't", dir, "paginate any further");
this.setState<null>({ [canPaginateKey]: false }); this.setState({ [canPaginateKey]: false } as Pick<IState, typeof canPaginateKey>);
return Promise.resolve(false); return Promise.resolve(false);
} }
@ -609,7 +609,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
} }
debuglog("Initiating paginate; backwards:" + backwards); debuglog("Initiating paginate; backwards:" + backwards);
this.setState<null>({ [paginatingKey]: true }); this.setState({ [paginatingKey]: true } as Pick<IState, typeof paginatingKey>);
return this.onPaginationRequest(this.timelineWindow, dir, PAGINATE_SIZE).then(async (r) => { return this.onPaginationRequest(this.timelineWindow, dir, PAGINATE_SIZE).then(async (r) => {
if (this.unmounted) { if (this.unmounted) {
@ -2012,7 +2012,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
return receiptStore?.getEventReadUpTo(myUserId, ignoreSynthesized) ?? null; return receiptStore?.getEventReadUpTo(myUserId, ignoreSynthesized) ?? null;
} }
private setReadMarker(eventId: string | null, eventTs: number, inhibitSetState = false): void { private setReadMarker(eventId: string | null, eventTs?: number, inhibitSetState = false): void {
const roomId = this.props.timelineSet.room?.roomId; const roomId = this.props.timelineSet.room?.roomId;
// don't update the state (and cause a re-render) if there is // don't update the state (and cause a re-render) if there is
@ -2023,7 +2023,11 @@ class TimelinePanel extends React.Component<IProps, IState> {
// in order to later figure out if the read marker is // in order to later figure out if the read marker is
// above or below the visible timeline, we stash the timestamp. // above or below the visible timeline, we stash the timestamp.
if (eventTs !== undefined) {
TimelinePanel.roomReadMarkerTsMap[roomId ?? ""] = eventTs; TimelinePanel.roomReadMarkerTsMap[roomId ?? ""] = eventTs;
} else {
delete TimelinePanel.roomReadMarkerTsMap[roomId ?? ""];
}
if (inhibitSetState) { if (inhibitSetState) {
return; return;

View File

@ -18,7 +18,7 @@ import React from "react";
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton"; import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
interface IProps { interface IProps {
mxEvent: MatrixEvent; mxEvent: MatrixEvent;
@ -26,7 +26,7 @@ interface IProps {
} }
export default class MjolnirBody extends React.Component<IProps> { export default class MjolnirBody extends React.Component<IProps> {
private onAllowClick = (e: React.MouseEvent): void => { private onAllowClick = (e: ButtonEvent): void => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();

View File

@ -171,7 +171,7 @@ const RoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
contextMenu = ( contextMenu = (
<ContextMenuComponent <ContextMenuComponent
{...contextMenuBelow(mainMenuHandle.current.getBoundingClientRect())} {...contextMenuBelow(mainMenuHandle.current.getBoundingClientRect())}
space={activeSpace} space={activeSpace!}
onFinished={closeMainMenu} onFinished={closeMainMenu}
hideHeader={true} hideHeader={true}
/> />

View File

@ -155,7 +155,7 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
); );
this.setState({ invitedEmailMxid: result.mxid }); this.setState({ invitedEmailMxid: result.mxid });
} catch (err) { } catch (err) {
this.setState({ threePidFetchError: err }); this.setState({ threePidFetchError: err as MatrixError });
} }
this.setState({ busy: false }); this.setState({ busy: false });
} }

View File

@ -70,11 +70,7 @@ export class ModalWidgetStore extends AsyncStoreWithClient<IState> {
widgetRoomId, widgetRoomId,
sourceWidgetId: sourceWidget.id, sourceWidgetId: sourceWidget.id,
onFinished: (success, data) => { onFinished: (success, data) => {
if (!success) { this.closeModalWidget(sourceWidget, widgetRoomId, success && data ? data : { "m.exited": true });
this.closeModalWidget(sourceWidget, widgetRoomId, { "m.exited": true });
} else {
this.closeModalWidget(sourceWidget, widgetRoomId, data);
}
this.openSourceWidgetId = null; this.openSourceWidgetId = null;
this.openSourceWidgetRoomId = null; this.openSourceWidgetRoomId = null;

View File

@ -363,7 +363,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
const panel = this.byRoom[this.viewedRoomId]; const panel = this.byRoom[this.viewedRoomId];
if (panel?.history) { if (panel?.history) {
panel.history = panel.history.filter( panel.history = panel.history.filter(
(card) => (card: IRightPanelCard) =>
card.phase != RightPanelPhases.RoomMemberInfo && card.phase != RightPanelPhases.RoomMemberInfo &&
card.phase != RightPanelPhases.Room3pidMemberInfo, card.phase != RightPanelPhases.Room3pidMemberInfo,
); );
@ -371,7 +371,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
} }
// when we're switching to a room, clear out thread permalinks to not get you stuck in the middle of the thread // when we're switching to a room, clear out thread permalinks to not get you stuck in the middle of the thread
// in order to fix https://github.com/matrix-org/matrix-react-sdk/pull/11011 // in order to fix https://github.com/matrix-org/matrix-react-sdk/pull/11011
if (this.currentCard?.phase === RightPanelPhases.ThreadView) { if (this.currentCard?.phase === RightPanelPhases.ThreadView && this.currentCard.state) {
this.currentCard.state.initialEvent = undefined; this.currentCard.state.initialEvent = undefined;
this.currentCard.state.isInitialEventHighlighted = undefined; this.currentCard.state.isInitialEventHighlighted = undefined;
this.currentCard.state.initialEventScrollIntoView = undefined; this.currentCard.state.initialEventScrollIntoView = undefined;

View File

@ -261,7 +261,15 @@ export default class AutoDiscoveryUtils {
throw new UserFriendlyError("Unexpected error resolving homeserver configuration"); throw new UserFriendlyError("Unexpected error resolving homeserver configuration");
} }
let delegatedAuthentication = undefined; let delegatedAuthentication:
| {
authorizationEndpoint: string;
registrationEndpoint?: string;
tokenEndpoint: string;
account?: string;
issuer: string;
}
| undefined;
if (discoveryResult[M_AUTHENTICATION.stable!]?.state === AutoDiscovery.SUCCESS) { if (discoveryResult[M_AUTHENTICATION.stable!]?.state === AutoDiscovery.SUCCESS) {
const { authorizationEndpoint, registrationEndpoint, tokenEndpoint, account, issuer } = discoveryResult[ const { authorizationEndpoint, registrationEndpoint, tokenEndpoint, account, issuer } = discoveryResult[
M_AUTHENTICATION.stable! M_AUTHENTICATION.stable!

View File

@ -60,7 +60,7 @@ export async function decryptFile(file?: IEncryptedFile, info?: IMediaEventInfo)
} }
responseData = await response.arrayBuffer(); responseData = await response.arrayBuffer();
} catch (e) { } catch (e) {
throw new DownloadError(e); throw new DownloadError(e as Error);
} }
try { try {
@ -77,6 +77,6 @@ export async function decryptFile(file?: IEncryptedFile, info?: IMediaEventInfo)
return new Blob([dataArray], { type: mimetype }); return new Blob([dataArray], { type: mimetype });
} catch (e) { } catch (e) {
throw new DecryptError(e); throw new DecryptError(e as Error);
} }
} }

View File

@ -36,7 +36,7 @@ function log(msg: string): void {
logger.log(`StorageManager: ${msg}`); logger.log(`StorageManager: ${msg}`);
} }
function error(msg: string, ...args: string[]): void { function error(msg: string, ...args: any[]): void {
logger.error(`StorageManager: ${msg}`, ...args); logger.error(`StorageManager: ${msg}`, ...args);
} }

View File

@ -33,14 +33,14 @@ export async function retry<T, E extends Error>(
num: number, num: number,
predicate?: (e: E) => boolean, predicate?: (e: E) => boolean,
): Promise<T> { ): Promise<T> {
let lastErr!: E; let lastErr!: any;
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
try { try {
const v = await fn(); const v = await fn();
// If `await fn()` throws then we won't reach here // If `await fn()` throws then we won't reach here
return v; return v;
} catch (err) { } catch (err) {
if (predicate && !predicate(err)) { if (predicate && !predicate(err as E)) {
throw err; throw err;
} }
lastErr = err; lastErr = err;

View File

@ -41,7 +41,7 @@ describe("requestMediaPermissions", () => {
describe("when an audio and video device is available", () => { describe("when an audio and video device is available", () => {
beforeEach(() => { beforeEach(() => {
mocked(navigator.mediaDevices.getUserMedia).mockImplementation( mocked(navigator.mediaDevices.getUserMedia).mockImplementation(
async ({ audio, video }): Promise<MediaStream> => { async ({ audio, video }: MediaStreamConstraints): Promise<MediaStream> => {
if (audio && video) return audioVideoStream; if (audio && video) return audioVideoStream;
return audioStream; return audioStream;
}, },
@ -56,7 +56,7 @@ describe("requestMediaPermissions", () => {
describe("when calling with video = false and an audio device is available", () => { describe("when calling with video = false and an audio device is available", () => {
beforeEach(() => { beforeEach(() => {
mocked(navigator.mediaDevices.getUserMedia).mockImplementation( mocked(navigator.mediaDevices.getUserMedia).mockImplementation(
async ({ audio, video }): Promise<MediaStream> => { async ({ audio, video }: MediaStreamConstraints): Promise<MediaStream> => {
if (audio && !video) return audioStream; if (audio && !video) return audioStream;
return audioVideoStream; return audioVideoStream;
}, },
@ -72,7 +72,7 @@ describe("requestMediaPermissions", () => {
beforeEach(() => { beforeEach(() => {
error.name = "NotFoundError"; error.name = "NotFoundError";
mocked(navigator.mediaDevices.getUserMedia).mockImplementation( mocked(navigator.mediaDevices.getUserMedia).mockImplementation(
async ({ audio, video }): Promise<MediaStream> => { async ({ audio, video }: MediaStreamConstraints): Promise<MediaStream> => {
if (audio && video) throw error; if (audio && video) throw error;
if (audio) return audioStream; if (audio) return audioStream;
return audioVideoStream; return audioVideoStream;
@ -103,7 +103,7 @@ describe("requestMediaPermissions", () => {
describe("when an Error is raised", () => { describe("when an Error is raised", () => {
beforeEach(async () => { beforeEach(async () => {
mocked(navigator.mediaDevices.getUserMedia).mockImplementation( mocked(navigator.mediaDevices.getUserMedia).mockImplementation(
async ({ audio, video }): Promise<MediaStream> => { async ({ audio, video }: MediaStreamConstraints): Promise<MediaStream> => {
if (audio && video) throw error; if (audio && video) throw error;
return audioVideoStream; return audioVideoStream;
}, },