Conform more of the codebase to strictNullChecks (#11134)
parent
3d886de5b0
commit
e1cad41bc3
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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`;
|
||||||
|
|
|
@ -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.
|
||||||
TimelinePanel.roomReadMarkerTsMap[roomId ?? ""] = eventTs;
|
if (eventTs !== undefined) {
|
||||||
|
TimelinePanel.roomReadMarkerTsMap[roomId ?? ""] = eventTs;
|
||||||
|
} else {
|
||||||
|
delete TimelinePanel.roomReadMarkerTsMap[roomId ?? ""];
|
||||||
|
}
|
||||||
|
|
||||||
if (inhibitSetState) {
|
if (inhibitSetState) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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 });
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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!
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue