diff --git a/src/ContentMessages.ts b/src/ContentMessages.ts
index 85ca90067d..e05858bb16 100644
--- a/src/ContentMessages.ts
+++ b/src/ContentMessages.ts
@@ -89,7 +89,7 @@ async function loadImageElement(imageFile: File): Promise<{
// check for hi-dpi PNGs and fudge display resolution as needed.
// this is mainly needed for macOS screencaps
- let parsePromise: Promise;
+ let parsePromise = Promise.resolve(false);
if (imageFile.type === "image/png") {
// in practice macOS happens to order the chunks so they fall in
// the first 0x1000 bytes (thanks to a massive ICC header).
@@ -101,7 +101,7 @@ async function loadImageElement(imageFile: File): Promise<{
const chunks = extractPngChunks(buffer);
for (const chunk of chunks) {
if (chunk.name === "pHYs") {
- if (chunk.data.byteLength !== PHYS_HIDPI.length) return;
+ if (chunk.data.byteLength !== PHYS_HIDPI.length) return false;
return chunk.data.every((val, i) => val === PHYS_HIDPI[i]);
}
}
@@ -199,10 +199,10 @@ function loadVideoElement(videoFile: File): Promise {
reject(e);
};
- let dataUrl = ev.target.result as string;
+ let dataUrl = ev.target?.result as string;
// Chrome chokes on quicktime but likes mp4, and `file.type` is
// read only, so do this horrible hack to unbreak quicktime
- if (dataUrl.startsWith("data:video/quicktime;")) {
+ if (dataUrl?.startsWith("data:video/quicktime;")) {
dataUrl = dataUrl.replace("data:video/quicktime;", "data:video/mp4;");
}
@@ -258,7 +258,7 @@ function readFileAsArrayBuffer(file: File | Blob): Promise {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = function (e): void {
- resolve(e.target.result as ArrayBuffer);
+ resolve(e.target?.result as ArrayBuffer);
};
reader.onerror = function (e): void {
reject(e);
@@ -329,7 +329,7 @@ export async function uploadFile(
export default class ContentMessages {
private inprogress: RoomUpload[] = [];
- private mediaConfig: IMediaConfig = null;
+ private mediaConfig: IMediaConfig | null = null;
public sendStickerContentToRoom(
url: string,
@@ -377,8 +377,8 @@ export default class ContentMessages {
modal.close();
}
- const tooBigFiles = [];
- const okFiles = [];
+ const tooBigFiles: File[] = [];
+ const okFiles: File[] = [];
for (const file of files) {
if (this.isFileSizeAcceptable(file)) {
@@ -420,7 +420,14 @@ export default class ContentMessages {
}
promBefore = doMaybeLocalRoomAction(roomId, (actualRoomId) =>
- this.sendContentToRoom(file, actualRoomId, relation, matrixClient, replyToEvent, loopPromiseBefore),
+ this.sendContentToRoom(
+ file,
+ actualRoomId,
+ relation,
+ matrixClient,
+ replyToEvent ?? undefined,
+ loopPromiseBefore,
+ ),
);
}
@@ -584,7 +591,7 @@ export default class ContentMessages {
}
private ensureMediaConfigFetched(matrixClient: MatrixClient): Promise {
- if (this.mediaConfig !== null) return;
+ if (this.mediaConfig !== null) return Promise.resolve();
logger.log("[Media Config] Fetching");
return matrixClient
diff --git a/src/DecryptionFailureTracker.ts b/src/DecryptionFailureTracker.ts
index 7329c665bc..256fe245ee 100644
--- a/src/DecryptionFailureTracker.ts
+++ b/src/DecryptionFailureTracker.ts
@@ -138,7 +138,7 @@ export class DecryptionFailureTracker {
return;
}
if (err) {
- this.addDecryptionFailure(new DecryptionFailure(e.getId(), err.code));
+ this.addDecryptionFailure(new DecryptionFailure(e.getId()!, err.code));
} else {
// Could be an event in the failures, remove it
this.removeDecryptionFailuresForEvent(e);
@@ -146,7 +146,7 @@ export class DecryptionFailureTracker {
}
public addVisibleEvent(e: MatrixEvent): void {
- const eventId = e.getId();
+ const eventId = e.getId()!;
if (this.trackedEvents.has(eventId)) {
return;
@@ -154,7 +154,7 @@ export class DecryptionFailureTracker {
this.visibleEvents.add(eventId);
if (this.failures.has(eventId) && !this.visibleFailures.has(eventId)) {
- this.visibleFailures.set(eventId, this.failures.get(eventId));
+ this.visibleFailures.set(eventId, this.failures.get(eventId)!);
}
}
@@ -172,7 +172,7 @@ export class DecryptionFailureTracker {
}
public removeDecryptionFailuresForEvent(e: MatrixEvent): void {
- const eventId = e.getId();
+ const eventId = e.getId()!;
this.failures.delete(eventId);
this.visibleFailures.delete(eventId);
}
@@ -193,8 +193,8 @@ export class DecryptionFailureTracker {
* Clear state and stop checking for and tracking failures.
*/
public stop(): void {
- clearInterval(this.checkInterval);
- clearInterval(this.trackInterval);
+ if (this.checkInterval) clearInterval(this.checkInterval);
+ if (this.trackInterval) clearInterval(this.trackInterval);
this.failures = new Map();
this.visibleEvents = new Set();
diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts
index eccfc1c0e3..039adc27cd 100644
--- a/src/DeviceListener.ts
+++ b/src/DeviceListener.ts
@@ -51,7 +51,7 @@ import { isBulkUnverifiedDeviceReminderSnoozed } from "./utils/device/snoozeBulk
const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000;
export default class DeviceListener {
- private dispatcherRef: string;
+ private dispatcherRef: string | null;
// device IDs for which the user has dismissed the verify toast ('Later')
private dismissed = new Set();
// has the user dismissed any of the various nag toasts to setup encryption on this device?
@@ -152,7 +152,7 @@ export default class DeviceListener {
private ensureDeviceIdsAtStartPopulated(): void {
if (this.ourDeviceIdsAtStart === null) {
const cli = MatrixClientPeg.get();
- this.ourDeviceIdsAtStart = new Set(cli.getStoredDevicesForUser(cli.getUserId()).map((d) => d.deviceId));
+ this.ourDeviceIdsAtStart = new Set(cli.getStoredDevicesForUser(cli.getUserId()!).map((d) => d.deviceId));
}
}
@@ -162,7 +162,7 @@ export default class DeviceListener {
// devicesAtStart list to the devices that we see after the fetch.
if (initialFetch) return;
- const myUserId = MatrixClientPeg.get().getUserId();
+ const myUserId = MatrixClientPeg.get().getUserId()!;
if (users.includes(myUserId)) this.ensureDeviceIdsAtStartPopulated();
// No need to do a recheck here: we just need to get a snapshot of our devices
@@ -170,7 +170,7 @@ export default class DeviceListener {
};
private onDevicesUpdated = (users: string[]): void => {
- if (!users.includes(MatrixClientPeg.get().getUserId())) return;
+ if (!users.includes(MatrixClientPeg.get().getUserId()!)) return;
this.recheck();
};
@@ -225,7 +225,7 @@ export default class DeviceListener {
// The server doesn't tell us when key backup is set up, so we poll
// & cache the result
- private async getKeyBackupInfo(): Promise {
+ private async getKeyBackupInfo(): Promise {
const now = new Date().getTime();
if (!this.keyBackupInfo || this.keyBackupFetchedAt < now - KEY_BACKUP_POLL_INTERVAL) {
this.keyBackupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
@@ -265,10 +265,10 @@ export default class DeviceListener {
this.checkKeyBackupStatus();
} else if (this.shouldShowSetupEncryptionToast()) {
// make sure our keys are finished downloading
- await cli.downloadKeys([cli.getUserId()]);
+ await cli.downloadKeys([cli.getUserId()!]);
// cross signing isn't enabled - nag to enable it
// There are 3 different toasts for:
- if (!cli.getCrossSigningId() && cli.getStoredCrossSigningForUser(cli.getUserId())) {
+ if (!cli.getCrossSigningId() && cli.getStoredCrossSigningForUser(cli.getUserId()!)) {
// Cross-signing on account but this device doesn't trust the master key (verify this session)
showSetupEncryptionToast(SetupKind.VERIFY_THIS_SESSION);
this.checkKeyBackupStatus();
@@ -310,13 +310,13 @@ export default class DeviceListener {
// as long as cross-signing isn't ready,
// you can't see or dismiss any device toasts
if (crossSigningReady) {
- const devices = cli.getStoredDevicesForUser(cli.getUserId());
+ const devices = cli.getStoredDevicesForUser(cli.getUserId()!);
for (const device of devices) {
if (device.deviceId === cli.deviceId) continue;
const deviceTrust = await cli.checkDeviceTrust(cli.getUserId()!, device.deviceId!);
if (!deviceTrust.isCrossSigningVerified() && !this.dismissed.has(device.deviceId)) {
- if (this.ourDeviceIdsAtStart.has(device.deviceId)) {
+ if (this.ourDeviceIdsAtStart?.has(device.deviceId)) {
oldUnverifiedDeviceIds.add(device.deviceId);
} else {
newUnverifiedDeviceIds.add(device.deviceId);
diff --git a/src/IdentityAuthClient.tsx b/src/IdentityAuthClient.tsx
index 293a3c19a6..12f42a3add 100644
--- a/src/IdentityAuthClient.tsx
+++ b/src/IdentityAuthClient.tsx
@@ -67,7 +67,7 @@ export default class IdentityAuthClient {
window.localStorage.setItem("mx_is_access_token", this.accessToken);
}
- private readToken(): string {
+ private readToken(): string | null {
if (this.tempClient) return null; // temporary client: ignore
return window.localStorage.getItem("mx_is_access_token");
}
@@ -77,13 +77,13 @@ export default class IdentityAuthClient {
}
// Returns a promise that resolves to the access_token string from the IS
- public async getAccessToken({ check = true } = {}): Promise {
+ public async getAccessToken({ check = true } = {}): Promise {
if (!this.authEnabled) {
// The current IS doesn't support authentication
return null;
}
- let token = this.accessToken;
+ let token: string | null = this.accessToken;
if (!token) {
token = this.readToken();
}
diff --git a/src/LegacyCallHandler.tsx b/src/LegacyCallHandler.tsx
index c3ca256646..34fffffc50 100644
--- a/src/LegacyCallHandler.tsx
+++ b/src/LegacyCallHandler.tsx
@@ -181,7 +181,7 @@ export default class LegacyCallHandler extends EventEmitter {
* Gets the user-facing room associated with a call (call.roomId may be the call "virtual room"
* if a voip_mxid_translate_pattern is set in the config)
*/
- public roomIdForCall(call: MatrixCall): string {
+ public roomIdForCall(call?: MatrixCall): string | null {
if (!call) return null;
// check asserted identity: if we're not obeying asserted identity,
@@ -194,7 +194,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
}
- return VoipUserMapper.sharedInstance().nativeRoomForVirtualRoom(call.roomId) || call.roomId;
+ return VoipUserMapper.sharedInstance().nativeRoomForVirtualRoom(call.roomId) ?? call.roomId ?? null;
}
public start(): void {
@@ -282,7 +282,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
public unSilenceCall(callId: string): void {
- if (this.isForcedSilent) return;
+ if (this.isForcedSilent()) return;
this.silencedCalls.delete(callId);
this.emit(LegacyCallHandlerEvent.SilencedCallsChanged, this.silencedCalls);
this.play(AudioID.Ring);
@@ -341,14 +341,14 @@ export default class LegacyCallHandler extends EventEmitter {
}
private shouldObeyAssertedfIdentity(): boolean {
- return SdkConfig.getObject("voip")?.get("obey_asserted_identity");
+ return !!SdkConfig.getObject("voip")?.get("obey_asserted_identity");
}
- public getSupportsPstnProtocol(): boolean {
+ public getSupportsPstnProtocol(): boolean | null {
return this.supportsPstnProtocol;
}
- public getSupportsVirtualRooms(): boolean {
+ public getSupportsVirtualRooms(): boolean | null {
return this.supportsSipNativeVirtual;
}
@@ -414,7 +414,7 @@ export default class LegacyCallHandler extends EventEmitter {
cli.prepareToEncrypt(cli.getRoom(call.roomId));
};
- public getCallById(callId: string): MatrixCall {
+ public getCallById(callId: string): MatrixCall | null {
for (const call of this.calls.values()) {
if (call.callId === callId) return call;
}
@@ -435,7 +435,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
public getAllActiveCalls(): MatrixCall[] {
- const activeCalls = [];
+ const activeCalls: MatrixCall[] = [];
for (const call of this.calls.values()) {
if (call.state !== CallState.Ended && call.state !== CallState.Ringing) {
@@ -446,7 +446,7 @@ export default class LegacyCallHandler extends EventEmitter {
}
public getAllActiveCallsNotInRoom(notInThisRoomId: string): MatrixCall[] {
- const callsNotInThatRoom = [];
+ const callsNotInThatRoom: MatrixCall[] = [];
for (const [roomId, call] of this.calls.entries()) {
if (roomId !== notInThisRoomId && call.state !== CallState.Ended) {
@@ -547,7 +547,7 @@ export default class LegacyCallHandler extends EventEmitter {
const mappedRoomId = this.roomIdForCall(call);
const callForThisRoom = this.getCallForRoom(mappedRoomId);
- return callForThisRoom && call.callId === callForThisRoom.callId;
+ return !!callForThisRoom && call.callId === callForThisRoom.callId;
}
private setCallListeners(call: MatrixCall): void {
@@ -610,7 +610,7 @@ export default class LegacyCallHandler extends EventEmitter {
return;
}
- const newAssertedIdentity = call.getRemoteAssertedIdentity().id;
+ const newAssertedIdentity = call.getRemoteAssertedIdentity()?.id;
let newNativeAssertedIdentity = newAssertedIdentity;
if (newAssertedIdentity) {
const response = await this.sipNativeLookup(newAssertedIdentity);
@@ -642,7 +642,7 @@ export default class LegacyCallHandler extends EventEmitter {
});
}
- private onCallStateChanged = (newState: CallState, oldState: CallState, call: MatrixCall): void => {
+ private onCallStateChanged = (newState: CallState, oldState: CallState | null, call: MatrixCall): void => {
if (!this.matchesCallForThisRoom(call)) return;
const mappedRoomId = this.roomIdForCall(call);
@@ -830,7 +830,7 @@ export default class LegacyCallHandler extends EventEmitter {
"turn.matrix.org
, but this will not be as reliable, and " +
"it will share your IP address with that server. You can also manage " +
"this in Settings.",
- null,
+ undefined,
{ code },
)}
@@ -843,7 +843,7 @@ export default class LegacyCallHandler extends EventEmitter {
cli.setFallbackICEServerAllowed(allow);
},
},
- null,
+ undefined,
true,
);
}
@@ -882,7 +882,7 @@ export default class LegacyCallHandler extends EventEmitter {
title,
description,
},
- null,
+ undefined,
true,
);
}
diff --git a/src/Login.ts b/src/Login.ts
index dbcdfe954e..73e6366956 100644
--- a/src/Login.ts
+++ b/src/Login.ts
@@ -29,20 +29,17 @@ interface ILoginOptions {
}
export default class Login {
- private hsUrl: string;
- private isUrl: string;
- private fallbackHsUrl: string;
- private flows: Array;
- private defaultDeviceDisplayName: string;
- private tempClient: MatrixClient;
+ private flows: Array = [];
+ private readonly defaultDeviceDisplayName?: string;
+ private tempClient: MatrixClient | null = null; // memoize
- public constructor(hsUrl: string, isUrl: string, fallbackHsUrl?: string, opts?: ILoginOptions) {
- this.hsUrl = hsUrl;
- this.isUrl = isUrl;
- this.fallbackHsUrl = fallbackHsUrl;
- this.flows = [];
+ public constructor(
+ private hsUrl: string,
+ private isUrl: string,
+ private fallbackHsUrl: string | null,
+ opts: ILoginOptions,
+ ) {
this.defaultDeviceDisplayName = opts.defaultDeviceDisplayName;
- this.tempClient = null; // memoize
}
public getHomeserverUrl(): string {
@@ -96,7 +93,7 @@ export default class Login {
phoneNumber: string | undefined,
password: string,
): Promise {
- const isEmail = username?.indexOf("@") > 0;
+ const isEmail = !!username && username.indexOf("@") > 0;
let identifier;
if (phoneCountry && phoneNumber) {
@@ -127,7 +124,7 @@ export default class Login {
};
const tryFallbackHs = (originalError: Error): Promise => {
- return sendLoginRequest(this.fallbackHsUrl, this.isUrl, "m.login.password", loginParams).catch(
+ return sendLoginRequest(this.fallbackHsUrl!, this.isUrl, "m.login.password", loginParams).catch(
(fallbackError) => {
logger.log("fallback HS login failed", fallbackError);
// throw the original error
@@ -136,13 +133,13 @@ export default class Login {
);
};
- let originalLoginError = null;
+ let originalLoginError: Error | null = null;
return sendLoginRequest(this.hsUrl, this.isUrl, "m.login.password", loginParams)
.catch((error) => {
originalLoginError = error;
if (error.httpStatus === 403) {
if (this.fallbackHsUrl) {
- return tryFallbackHs(originalLoginError);
+ return tryFallbackHs(originalLoginError!);
}
}
throw originalLoginError;
diff --git a/src/ScalarAuthClient.ts b/src/ScalarAuthClient.ts
index 1859399d41..558e6362b9 100644
--- a/src/ScalarAuthClient.ts
+++ b/src/ScalarAuthClient.ts
@@ -256,7 +256,7 @@ export default class ScalarAuthClient {
}
}
- public getScalarInterfaceUrlForRoom(room: Room, screen: string, id: string): string {
+ public getScalarInterfaceUrlForRoom(room: Room, screen?: string, id?: string): string {
const roomId = room.roomId;
const roomName = room.name;
let url = this.uiUrl;
diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts
index 73f4be06ea..2a56de8751 100644
--- a/src/SecurityManager.ts
+++ b/src/SecurityManager.ts
@@ -102,7 +102,7 @@ async function getSecretStorageKey({
}): Promise<[string, Uint8Array]> {
const cli = MatrixClientPeg.get();
let keyId = await cli.getDefaultSecretStorageKeyId();
- let keyInfo: ISecretStorageKeyInfo;
+ let keyInfo!: ISecretStorageKeyInfo;
if (keyId) {
// use the default SSSS key if set
keyInfo = keyInfos[keyId];
diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx
index e1f028bedd..66f673445d 100644
--- a/src/SlashCommands.tsx
+++ b/src/SlashCommands.tsx
@@ -82,6 +82,7 @@ const singleMxcUpload = async (): Promise => {
fileSelector.setAttribute("type", "file");
fileSelector.onchange = (ev: HTMLInputEvent) => {
const file = ev.target.files?.[0];
+ if (!file) return;
Modal.createDialog(UploadConfirmDialog, {
file,
@@ -304,7 +305,7 @@ export const Commands = [
if (args) {
const cli = MatrixClientPeg.get();
const room = cli.getRoom(roomId);
- if (!room.currentState.mayClientSendStateEvent("m.room.tombstone", cli)) {
+ if (!room?.currentState.mayClientSendStateEvent("m.room.tombstone", cli)) {
return reject(
newTranslatableError("You do not have the required permissions to use this command."),
);
@@ -313,7 +314,7 @@ export const Commands = [
const { finished } = Modal.createDialog(
RoomUpgradeWarningDialog,
{ roomId: roomId, targetVersion: args },
- /*className=*/ null,
+ /*className=*/ undefined,
/*isPriority=*/ false,
/*isStatic=*/ true,
);
@@ -1199,7 +1200,7 @@ export const Commands = [
description: _td("Switches to this room's virtual room, if it has one"),
category: CommandCategories.advanced,
isEnabled(): boolean {
- return LegacyCallHandler.instance.getSupportsVirtualRooms() && !isCurrentLocalRoom();
+ return !!LegacyCallHandler.instance.getSupportsVirtualRooms() && !isCurrentLocalRoom();
},
runFn: (roomId) => {
return success(
@@ -1389,7 +1390,7 @@ export function parseCommandString(input: string): { cmd?: string; args?: string
const bits = input.match(/^(\S+?)(?:[ \n]+((.|\n)*))?$/);
let cmd: string;
- let args: string;
+ let args: string | undefined;
if (bits) {
cmd = bits[1].substring(1).toLowerCase();
args = bits[2];
@@ -1414,7 +1415,7 @@ interface ICmd {
export function getCommand(input: string): ICmd {
const { cmd, args } = parseCommandString(input);
- if (CommandMap.has(cmd) && CommandMap.get(cmd)!.isEnabled()) {
+ if (cmd && CommandMap.has(cmd) && CommandMap.get(cmd)!.isEnabled()) {
return {
cmd: CommandMap.get(cmd),
args,
diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx
index 1798a5016f..790ce2571b 100644
--- a/src/TextForEvent.tsx
+++ b/src/TextForEvent.tsx
@@ -120,20 +120,20 @@ function textForMemberEvent(ev: MatrixEvent, allowJSX: boolean, showHiddenEvents
// We're taking the display namke directly from the event content here so we need
// to strip direction override chars which the js-sdk would normally do when
// calculating the display name
- oldDisplayName: removeDirectionOverrideChars(prevContent.displayname),
- displayName: removeDirectionOverrideChars(content.displayname),
+ oldDisplayName: removeDirectionOverrideChars(prevContent.displayname!),
+ displayName: removeDirectionOverrideChars(content.displayname!),
});
} else if (!prevContent.displayname && content.displayname) {
return () =>
_t("%(senderName)s set their display name to %(displayName)s", {
senderName: ev.getSender(),
- displayName: removeDirectionOverrideChars(content.displayname),
+ displayName: removeDirectionOverrideChars(content.displayname!),
});
} else if (prevContent.displayname && !content.displayname) {
return () =>
_t("%(senderName)s removed their display name (%(oldDisplayName)s)", {
senderName,
- oldDisplayName: removeDirectionOverrideChars(prevContent.displayname),
+ oldDisplayName: removeDirectionOverrideChars(prevContent.displayname!),
});
} else if (prevContent.avatar_url && !content.avatar_url) {
return () => _t("%(senderName)s removed their profile picture", { senderName });
@@ -545,7 +545,7 @@ function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): (() => Rende
if (newlyPinned.length === 1 && newlyUnpinned.length === 0) {
// A single message was pinned, include a link to that message.
if (allowJSX) {
- const messageId = newlyPinned.pop();
+ const messageId = newlyPinned.pop()!;
return () => (
@@ -578,7 +578,7 @@ function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): (() => Rende
if (newlyUnpinned.length === 1 && newlyPinned.length === 0) {
// A single message was unpinned, include a link to that message.
if (allowJSX) {
- const messageId = newlyUnpinned.pop();
+ const messageId = newlyUnpinned.pop()!;
return () => (
diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx
index 118e1d8d95..5e66c883e7 100644
--- a/src/components/structures/ContextMenu.tsx
+++ b/src/components/structures/ContextMenu.tsx
@@ -105,7 +105,7 @@ export interface IProps extends MenuProps {
}
interface IState {
- contextMenuElem: HTMLDivElement;
+ contextMenuElem?: HTMLDivElement;
}
// Generic ContextMenu Portal wrapper
@@ -122,9 +122,7 @@ export default class ContextMenu extends React.PureComponent {
public constructor(props: IProps) {
super(props);
- this.state = {
- contextMenuElem: null,
- };
+ this.state = {};
// persist what had focus when we got initialized so we can return it after
this.initialFocus = document.activeElement as HTMLElement;
@@ -181,7 +179,7 @@ export default class ContextMenu extends React.PureComponent {
button: 0, // Left
relatedTarget: null,
});
- document.elementFromPoint(x, y).dispatchEvent(clickEvent);
+ document.elementFromPoint(x, y)?.dispatchEvent(clickEvent);
});
}
};
@@ -239,7 +237,7 @@ export default class ContextMenu extends React.PureComponent {
// MessageActionBar), we should close any ContextMenu that is open.
KeyBindingAction.ArrowLeft,
KeyBindingAction.ArrowRight,
- ].includes(action)
+ ].includes(action!)
) {
this.props.onFinished();
}
@@ -312,12 +310,12 @@ export default class ContextMenu extends React.PureComponent {
position.top = Math.min(position.top, maxTop);
// Adjust the chevron if necessary
if (chevronOffset.top !== undefined) {
- chevronOffset.top = propsChevronOffset + top - position.top;
+ chevronOffset.top = propsChevronOffset! + top! - position.top;
}
} else if (position.bottom !== undefined) {
position.bottom = Math.min(position.bottom, windowHeight - contextMenuRect.height - WINDOW_PADDING);
if (chevronOffset.top !== undefined) {
- chevronOffset.top = propsChevronOffset + position.bottom - bottom;
+ chevronOffset.top = propsChevronOffset! + position.bottom - bottom!;
}
}
if (position.left !== undefined) {
@@ -327,12 +325,12 @@ export default class ContextMenu extends React.PureComponent {
}
position.left = Math.min(position.left, maxLeft);
if (chevronOffset.left !== undefined) {
- chevronOffset.left = propsChevronOffset + left - position.left;
+ chevronOffset.left = propsChevronOffset! + left! - position.left;
}
} else if (position.right !== undefined) {
position.right = Math.min(position.right, windowWidth - contextMenuRect.width - WINDOW_PADDING);
if (chevronOffset.left !== undefined) {
- chevronOffset.left = propsChevronOffset + position.right - right;
+ chevronOffset.left = propsChevronOffset! + position.right - right!;
}
}
}
@@ -389,7 +387,7 @@ export default class ContextMenu extends React.PureComponent {
const wrapperStyle: CSSProperties = {};
if (!isNaN(Number(zIndex))) {
- menuStyle["zIndex"] = zIndex + 1;
+ menuStyle["zIndex"] = zIndex! + 1;
wrapperStyle["zIndex"] = zIndex;
}
diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx
index f1c8913da8..3084440619 100644
--- a/src/components/views/dialogs/InviteDialog.tsx
+++ b/src/components/views/dialogs/InviteDialog.tsx
@@ -97,7 +97,7 @@ class DMUserTile extends React.PureComponent {
e.preventDefault();
e.stopPropagation();
- this.props.onRemove(this.props.member);
+ this.props.onRemove!(this.props.member);
};
public render(): React.ReactNode {
@@ -132,7 +132,7 @@ class DMUserTile extends React.PureComponent {
interface IDMRoomTileProps {
member: Member;
- lastActiveTs: number;
+ lastActiveTs?: number;
onToggle(member: Member): void;
highlightWord: string;
isSelected: boolean;
@@ -188,7 +188,7 @@ class DMRoomTile extends React.PureComponent {
}
public render(): React.ReactNode {
- let timestamp = null;
+ let timestamp: JSX.Element | undefined;
if (this.props.lastActiveTs) {
const humanTs = humanizeTime(this.props.lastActiveTs);
timestamp = {humanTs};
@@ -201,7 +201,7 @@ class DMRoomTile extends React.PureComponent {
{
/>
);
- let checkmark = null;
+ let checkmark: JSX.Element | undefined;
if (this.props.isSelected) {
// To reduce flickering we put the 'selected' room tile above the real avatar
checkmark = ;
@@ -301,7 +301,7 @@ interface IInviteDialogState {
// These two flags are used for the 'Go' button to communicate what is going on.
busy: boolean;
- errorText: string;
+ errorText?: string;
}
export default class InviteDialog extends React.PureComponent {
@@ -324,7 +324,7 @@ export default class InviteDialog extends React.PureComponent p.trim())
@@ -803,13 +808,11 @@ export default class InviteDialog extends React.PureComponent (kind === "recents" ? m.lastActive : null);
+ const lastActive = (m: Result): number | undefined => (kind === "recents" ? m.lastActive : undefined);
let sectionName = kind === "recents" ? _t("Recent Conversations") : _t("Suggestions");
if (this.props.kind === KIND_INVITE) {
@@ -924,7 +927,7 @@ export default class InviteDialog extends React.PureComponent
@@ -960,7 +963,7 @@ export default class InviteDialog extends React.PureComponent (
-
+
));
const input = (
0)}
autoComplete="off"
- placeholder={hasPlaceholder ? _t("Search") : null}
+ placeholder={hasPlaceholder ? _t("Search") : undefined}
data-testid="invite-dialog-input"
/>
);
@@ -985,7 +988,7 @@ export default class InviteDialog extends React.PureComponent;
}
@@ -1108,7 +1111,7 @@ export default class InviteDialog extends React.PureComponent 0 || (this.state.filterText && this.state.filterText.includes("@"));
const cli = MatrixClientPeg.get();
- const userId = cli.getUserId();
+ const userId = cli.getUserId()!;
if (this.props.kind === KIND_DM) {
title = _t("Direct Messages");
@@ -1150,11 +1153,11 @@ export default class InviteDialog extends React.PureComponent{_t("If you can't see who you're looking for, send them your invite link below.")}
);
- const link = makeUserPermalink(MatrixClientPeg.get().getUserId());
+ const link = makeUserPermalink(MatrixClientPeg.get().getUserId()!);
footer = (
{_t("Or send invite link")}
-
makeUserPermalink(MatrixClientPeg.get().getUserId())}>
+ makeUserPermalink(MatrixClientPeg.get().getUserId()!)}>
{link}
@@ -1296,7 +1299,7 @@ export default class InviteDialog extends React.PureComponent it.toLowerCase()) || []),
- ].filter(Boolean),
+ ].filter(Boolean) as string[],
});
const toRoomResult = (room: Room): IRoomResult => {
@@ -310,7 +310,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n
}, [cli]);
const msc3946ProcessDynamicPredecessor = useFeatureEnabled("feature_dynamic_room_predecessors");
- const ownInviteLink = makeUserPermalink(cli.getUserId());
+ const ownInviteLink = makeUserPermalink(cli.getUserId()!);
const [inviteLinkCopied, setInviteLinkCopied] = useState(false);
const trimmedQuery = useMemo(() => query.trim(), [query]);
@@ -465,7 +465,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n
useWebSearchMetrics(numResults, query.length, true);
const activeSpace = SpaceStore.instance.activeSpaceRoom;
- const [spaceResults, spaceResultsLoading] = useSpaceResults(activeSpace, query);
+ const [spaceResults, spaceResultsLoading] = useSpaceResults(activeSpace ?? undefined, query);
const setQuery = (e: ChangeEvent): void => {
const newQuery = e.currentTarget.value;
@@ -473,7 +473,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n
};
useEffect(() => {
setImmediate(() => {
- let ref: Ref;
+ let ref: Ref | undefined;
if (rovingContext.state.refs) {
ref = rovingContext.state.refs[0];
}
@@ -521,7 +521,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n
onFinished();
};
- let otherSearchesSection: JSX.Element;
+ let otherSearchesSection: JSX.Element | undefined;
if (trimmedQuery || filter !== Filter.PublicRooms) {
otherSearchesSection = (
= ({ initialText = "", initialFilter = n
);
};
- let peopleSection: JSX.Element;
+ let peopleSection: JSX.Element | undefined;
if (results[Section.People].length) {
peopleSection = (
= ({ initialText = "", initialFilter = n
);
}
- let suggestionsSection: JSX.Element;
+ let suggestionsSection: JSX.Element | undefined;
if (results[Section.Suggestions].length && filter === Filter.People) {
suggestionsSection = (
= ({ initialText = "", initialFilter = n
);
}
- let roomsSection: JSX.Element;
+ let roomsSection: JSX.Element | undefined;
if (results[Section.Rooms].length) {
roomsSection = (
= ({ initialText = "", initialFilter = n
);
}
- let spacesSection: JSX.Element;
+ let spacesSection: JSX.Element | undefined;
if (results[Section.Spaces].length) {
spacesSection = (
= ({ initialText = "", initialFilter = n
);
}
- let publicRoomsSection: JSX.Element;
+ let publicRoomsSection: JSX.Element | undefined;
if (filter === Filter.PublicRooms) {
publicRoomsSection = (
= ({ initialText = "", initialFilter = n
);
}
- let spaceRoomsSection: JSX.Element;
+ let spaceRoomsSection: JSX.Element | undefined;
if (spaceResults.length && activeSpace && filter === null) {
spaceRoomsSection = (
= ({ initialText = "", initialFilter = n
);
}
- let joinRoomSection: JSX.Element;
+ let joinRoomSection: JSX.Element | undefined;
if (
trimmedQuery.startsWith("#") &&
trimmedQuery.includes(":") &&
@@ -868,7 +868,7 @@ const SpotlightDialog: React.FC
= ({ initialText = "", initialFilter = n
);
}
- let hiddenResultsSection: JSX.Element;
+ let hiddenResultsSection: JSX.Element | undefined;
if (filter === Filter.People) {
hiddenResultsSection = (
@@ -921,7 +921,7 @@ const SpotlightDialog: React.FC
= ({ initialText = "", initialFilter = n
);
}
- let groupChatSection: JSX.Element;
+ let groupChatSection: JSX.Element | undefined;
if (filter === Filter.People) {
groupChatSection = (
= ({ initialText = "", initialFilter = n
);
}
- let messageSearchSection: JSX.Element;
+ let messageSearchSection: JSX.Element | undefined;
if (filter === null) {
messageSearchSection = (
= ({ initialText = "", initialFilter = n
>
);
} else {
- let recentSearchesSection: JSX.Element;
+ let recentSearchesSection: JSX.Element | undefined;
if (recentSearches.length) {
recentSearchesSection = (
= ({ initialText = "", initialFilter = n
break;
}
- let ref: RefObject
;
+ let ref: RefObject | undefined;
const accessibilityAction = getKeyBindingsManager().getAccessibilityAction(ev);
switch (accessibilityAction) {
case KeyBindingAction.Escape:
diff --git a/src/components/views/spaces/SpaceBasicSettings.tsx b/src/components/views/spaces/SpaceBasicSettings.tsx
index d5db0370a1..84f762d15e 100644
--- a/src/components/views/spaces/SpaceBasicSettings.tsx
+++ b/src/components/views/spaces/SpaceBasicSettings.tsx
@@ -24,11 +24,11 @@ import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds";
interface IProps {
avatarUrl?: string;
avatarDisabled?: boolean;
- name?: string;
+ name: string;
nameDisabled?: boolean;
topic?: string;
topicDisabled?: boolean;
- setAvatar(avatar: File): void;
+ setAvatar(avatar?: File): void;
setName(name: string): void;
setTopic(topic: string): void;
}
@@ -102,7 +102,7 @@ export const SpaceAvatar: React.FC {
- setAvatarDataUrl(ev.target.result as string);
+ setAvatarDataUrl(ev.target?.result as string);
};
reader.readAsDataURL(file);
}}
diff --git a/src/components/views/spaces/SpaceChildrenPicker.tsx b/src/components/views/spaces/SpaceChildrenPicker.tsx
index 8bbf0e3868..3cf63fd0ad 100644
--- a/src/components/views/spaces/SpaceChildrenPicker.tsx
+++ b/src/components/views/spaces/SpaceChildrenPicker.tsx
@@ -53,7 +53,7 @@ const SpecificChildrenPicker: React.FC = ({
const matcher = new QueryMatcher(rooms, {
keys: ["name"],
- funcs: [(r) => [r.getCanonicalAlias(), ...r.getAltAliases()].filter(Boolean)],
+ funcs: [(r) => [r.getCanonicalAlias(), ...r.getAltAliases()].filter(Boolean) as string[]],
shouldMatchWordsOnly: false,
});
diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx
index 01fa0faf84..3a23b4074b 100644
--- a/src/components/views/spaces/SpaceCreateMenu.tsx
+++ b/src/components/views/spaces/SpaceCreateMenu.tsx
@@ -245,14 +245,14 @@ export const SpaceCreateForm: React.FC = ({
const SpaceCreateMenu: React.FC<{
onFinished(): void;
}> = ({ onFinished }) => {
- const [visibility, setVisibility] = useState(null);
+ const [visibility, setVisibility] = useState(null);
const [busy, setBusy] = useState(false);
const [name, setName] = useState("");
const spaceNameField = useRef();
const [alias, setAlias] = useState("");
const spaceAliasField = useRef();
- const [avatar, setAvatar] = useState(null);
+ const [avatar, setAvatar] = useState(undefined);
const [topic, setTopic] = useState("");
const onSpaceCreateClick = async (e: ButtonEvent): Promise => {
diff --git a/src/components/views/spaces/SpacePanel.tsx b/src/components/views/spaces/SpacePanel.tsx
index 7d3bd5bd22..92d919c5d2 100644
--- a/src/components/views/spaces/SpacePanel.tsx
+++ b/src/components/views/spaces/SpacePanel.tsx
@@ -215,7 +215,7 @@ const CreateSpaceButton: React.FC;
}
diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx
index 6e39c818d8..8338101794 100644
--- a/src/components/views/spaces/SpaceTreeLevel.tsx
+++ b/src/components/views/spaces/SpaceTreeLevel.tsx
@@ -121,11 +121,11 @@ export const SpaceButton = forwardRef(
);
}
- let contextMenu: JSX.Element;
- if (menuDisplayed && ContextMenuComponent) {
+ let contextMenu: JSX.Element | undefined;
+ if (menuDisplayed && handle.current && ContextMenuComponent) {
contextMenu = (
@@ -242,7 +242,7 @@ export class SpaceItem extends React.PureComponent {
}
private get isCollapsed(): boolean {
- return this.state.collapsed || this.props.isPanelCollapsed;
+ return this.state.collapsed || !!this.props.isPanelCollapsed;
}
private toggleCollapse = (evt: ButtonEvent): void => {
diff --git a/src/components/views/user-onboarding/UserOnboardingHeader.tsx b/src/components/views/user-onboarding/UserOnboardingHeader.tsx
index 77902a9aca..42ed7f0695 100644
--- a/src/components/views/user-onboarding/UserOnboardingHeader.tsx
+++ b/src/components/views/user-onboarding/UserOnboardingHeader.tsx
@@ -30,7 +30,7 @@ const onClickSendDm = (ev: ButtonEvent): void => {
};
interface Props {
- useCase: UseCase;
+ useCase: UseCase | null;
}
export function UserOnboardingHeader({ useCase }: Props): JSX.Element {
diff --git a/src/components/views/user-onboarding/UserOnboardingPage.tsx b/src/components/views/user-onboarding/UserOnboardingPage.tsx
index 8f8be5da95..242023deb5 100644
--- a/src/components/views/user-onboarding/UserOnboardingPage.tsx
+++ b/src/components/views/user-onboarding/UserOnboardingPage.tsx
@@ -38,7 +38,7 @@ interface Props {
// We decided to only show the new user onboarding page to new users
// For now, that means we set the cutoff at 2022-07-01 00:00 UTC
const USER_ONBOARDING_CUTOFF_DATE = new Date(1_656_633_600);
-export function showUserOnboardingPage(useCase: UseCase): boolean {
+export function showUserOnboardingPage(useCase: UseCase | null): boolean {
return useCase !== null || MatrixClientPeg.userRegisteredAfter(USER_ONBOARDING_CUTOFF_DATE);
}
@@ -55,13 +55,11 @@ export function UserOnboardingPage({ justRegistered = false }: Props): JSX.Eleme
const [showList, setShowList] = useState(false);
useEffect(() => {
if (initialSyncComplete) {
- let handler: number | null = window.setTimeout(() => {
- handler = null;
+ const handler = window.setTimeout(() => {
setShowList(true);
}, ANIMATION_DURATION);
return () => {
clearTimeout(handler);
- handler = null;
};
} else {
setShowList(false);
diff --git a/src/components/views/voip/DialPad.tsx b/src/components/views/voip/DialPad.tsx
index 407e0d72a6..634b88d144 100644
--- a/src/components/views/voip/DialPad.tsx
+++ b/src/components/views/voip/DialPad.tsx
@@ -18,6 +18,7 @@ import * as React from "react";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import { _t } from "../../../languageHandler";
+import { XOR } from "../../../@types/common";
const BUTTONS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"];
const BUTTON_LETTERS = ["", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ", "", "+", ""];
@@ -31,7 +32,7 @@ interface IButtonProps {
kind: DialPadButtonKind;
digit?: string;
digitSubtext?: string;
- onButtonPress: (digit: string, ev: ButtonEvent) => void;
+ onButtonPress: (digit: string | undefined, ev: ButtonEvent) => void;
}
class DialPadButton extends React.PureComponent {
@@ -60,16 +61,24 @@ class DialPadButton extends React.PureComponent {
}
}
-interface IProps {
+interface IBaseProps {
onDigitPress: (digit: string, ev: ButtonEvent) => void;
- hasDial: boolean;
onDeletePress?: (ev: ButtonEvent) => void;
- onDialPress?: () => void;
+ hasDial: boolean;
}
-export default class Dialpad extends React.PureComponent {
+interface IProps extends IBaseProps {
+ hasDial: false;
+}
+
+interface IDialProps extends IBaseProps {
+ hasDial: true;
+ onDialPress: () => void;
+}
+
+export default class Dialpad extends React.PureComponent> {
public render(): React.ReactNode {
- const buttonNodes = [];
+ const buttonNodes: JSX.Element[] = [];
for (let i = 0; i < BUTTONS.length; i++) {
const button = BUTTONS[i];
diff --git a/src/components/views/voip/LegacyCallView.tsx b/src/components/views/voip/LegacyCallView.tsx
index 41ad1897a2..1e8b4621f9 100644
--- a/src/components/views/voip/LegacyCallView.tsx
+++ b/src/components/views/voip/LegacyCallView.tsx
@@ -76,7 +76,7 @@ interface IState {
sidebarShown: boolean;
}
-function getFullScreenElement(): Element | undefined {
+function getFullScreenElement(): Element | null {
return (
document.fullscreenElement ||
// moz omitted because firefox supports this unprefixed now (webkit here for safari)
@@ -180,7 +180,7 @@ export default class LegacyCallView extends React.Component {
}
};
- private updateCallListeners(oldCall: MatrixCall, newCall: MatrixCall | null): void {
+ private updateCallListeners(oldCall: MatrixCall | null, newCall: MatrixCall | null): void {
if (oldCall === newCall) return;
if (oldCall) {
@@ -245,7 +245,7 @@ export default class LegacyCallView extends React.Component {
};
}
- let primary: CallFeed;
+ let primary: CallFeed | undefined;
// Try to use a screensharing as primary, a remote one if possible
const screensharingFeeds = feeds.filter((feed) => feed.purpose === SDPStreamMetadataPurpose.Screenshare);
@@ -289,7 +289,7 @@ export default class LegacyCallView extends React.Component {
if (this.state.screensharing) {
isScreensharing = await this.props.call.setScreensharingEnabled(false);
} else {
- if (PlatformPeg.get().supportsDesktopCapturer()) {
+ if (PlatformPeg.get()?.supportsDesktopCapturer()) {
const { finished } = Modal.createDialog<[string]>(DesktopCapturerSourcePicker);
const [source] = await finished;
if (!source) return;
@@ -403,7 +403,7 @@ export default class LegacyCallView extends React.Component {
);
}
- private renderToast(): JSX.Element {
+ private renderToast(): JSX.Element | null {
const { call } = this.props;
const someoneIsScreensharing = call.getFeeds().some((feed) => {
return feed.purpose === SDPStreamMetadataPurpose.Screenshare;
@@ -413,8 +413,8 @@ export default class LegacyCallView extends React.Component {
const isScreensharing = call.isScreensharing();
const { primaryFeed, sidebarShown } = this.state;
- const sharerName = primaryFeed?.getMember().name;
- if (!sharerName) return;
+ const sharerName = primaryFeed?.getMember()?.name;
+ if (!sharerName) return null;
let text = isScreensharing ? _t("You are presenting") : _t("%(sharerName)s is presenting", { sharerName });
if (!sidebarShown) {
@@ -495,7 +495,7 @@ export default class LegacyCallView extends React.Component {
);
} else if (isLocalOnHold) {
onHoldText = _t("%(peerName)s held the call", {
- peerName: call.getOpponentMember().name,
+ peerName: call.getOpponentMember()?.name,
});
}
@@ -556,8 +556,8 @@ export default class LegacyCallView extends React.Component {
const client = MatrixClientPeg.get();
const callRoomId = LegacyCallHandler.instance.roomIdForCall(call);
const secondaryCallRoomId = LegacyCallHandler.instance.roomIdForCall(secondaryCall);
- const callRoom = client.getRoom(callRoomId);
- const secCallRoom = secondaryCall ? client.getRoom(secondaryCallRoomId) : null;
+ const callRoom = callRoomId ? client.getRoom(callRoomId) : null;
+ const secCallRoom = secondaryCallRoomId ? client.getRoom(secondaryCallRoomId) : null;
const callViewClasses = classNames({
mx_LegacyCallView: true,
diff --git a/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx b/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx
index b7125eb6a0..0ff66fc4e8 100644
--- a/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx
+++ b/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx
@@ -104,9 +104,9 @@ const LegacyCallViewDropdownButton: React.FC = ({ state, d
onHover={(hovering) => setHoveringDropdown(hovering)}
state={state}
/>
- {menuDisplayed && (
+ {menuDisplayed && buttonRef.current && (
@@ -117,7 +117,7 @@ const LegacyCallViewDropdownButton: React.FC = ({ state, d
interface IProps {
call: MatrixCall;
- pipMode: boolean;
+ pipMode?: boolean;
handlers: {
onHangupClick: () => void;
onScreenshareClick: () => void;
@@ -150,7 +150,7 @@ interface IState {
export default class LegacyCallViewButtons extends React.Component {
private dialpadButton = createRef();
private contextMenuButton = createRef();
- private controlsHideTimer: number = null;
+ private controlsHideTimer: number | null = null;
public constructor(props: IProps) {
super(props);
@@ -223,7 +223,7 @@ export default class LegacyCallViewButtons extends React.Component = ({ callRoom }) => {
};
interface LegacyCallViewHeaderProps {
- pipMode: boolean;
- callRooms?: Room[];
- onPipMouseDown: (event: React.MouseEvent) => void;
+ pipMode?: boolean;
+ callRooms: [Room, Room | null];
+ onPipMouseDown?: (event: React.MouseEvent) => void;
onExpand?: () => void;
onPin?: () => void;
onMaximize?: () => void;
@@ -81,7 +81,7 @@ interface LegacyCallViewHeaderProps {
const LegacyCallViewHeader: React.FC = ({
pipMode = false,
- callRooms = [],
+ callRooms,
onPipMouseDown,
onExpand,
onPin,
diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx
index 9cd0086c31..35fb851f4a 100644
--- a/src/components/views/voip/VideoFeed.tsx
+++ b/src/components/views/voip/VideoFeed.tsx
@@ -95,7 +95,7 @@ export default class VideoFeed extends React.PureComponent {
element.addEventListener("resize", this.onResize);
};
- private updateFeed(oldFeed: CallFeed, newFeed: CallFeed): void {
+ private updateFeed(oldFeed: CallFeed | null, newFeed: CallFeed | null): void {
if (oldFeed === newFeed) return;
if (oldFeed) {
diff --git a/src/customisations/Media.ts b/src/customisations/Media.ts
index c3debef86f..9c07288b18 100644
--- a/src/customisations/Media.ts
+++ b/src/customisations/Media.ts
@@ -84,7 +84,7 @@ export class Media {
* The HTTP URL for the thumbnail media (without any specified width, height, etc). Null/undefined
* if no thumbnail media recorded.
*/
- public get thumbnailHttp(): string | undefined | null {
+ public get thumbnailHttp(): string | null {
if (!this.hasThumbnail) return null;
// eslint-disable-next-line no-restricted-properties
return this.client.mxcUrlToHttp(this.thumbnailMxc!);
diff --git a/src/editor/commands.tsx b/src/editor/commands.tsx
index 55dae83503..f65507054b 100644
--- a/src/editor/commands.tsx
+++ b/src/editor/commands.tsx
@@ -45,7 +45,7 @@ export function isSlashCommand(model: EditorModel): boolean {
return false;
}
-export function getSlashCommand(model: EditorModel): [Command, string, string] {
+export function getSlashCommand(model: EditorModel): [Command | undefined, string | undefined, string] {
const commandText = model.parts.reduce((text, part) => {
// use mxid to textify user pills in a command and room alias/id for room pills
if (part.type === Type.UserPill || part.type === Type.RoomPill) {
@@ -69,7 +69,7 @@ export async function runSlashCommand(
if (result.promise) {
try {
if (cmd.category === CommandCategories.messages || cmd.category === CommandCategories.effects) {
- messageContent = await result.promise;
+ messageContent = (await result.promise) ?? null;
} else {
await result.promise;
}
diff --git a/src/editor/dom.ts b/src/editor/dom.ts
index 19bccdbef7..05d5789066 100644
--- a/src/editor/dom.ts
+++ b/src/editor/dom.ts
@@ -32,7 +32,7 @@ export function walkDOMDepthFirst(rootNode: Node, enterNodeCallback: Predicate,
} else if (node.nextSibling) {
node = node.nextSibling;
} else {
- while (!node.nextSibling && node !== rootNode) {
+ while (node && !node.nextSibling && node !== rootNode) {
node = node.parentElement;
if (node !== rootNode) {
leaveNodeCallback(node);
diff --git a/src/editor/model.ts b/src/editor/model.ts
index 975e63aa4c..83f0a232f6 100644
--- a/src/editor/model.ts
+++ b/src/editor/model.ts
@@ -127,7 +127,7 @@ export default class EditorModel {
return this._parts;
}
- public get autoComplete(): AutocompleteWrapperModel {
+ public get autoComplete(): AutocompleteWrapperModel | null {
if (this.activePartIdx === this.autoCompletePartIdx) {
return this._autoComplete;
}
@@ -212,12 +212,12 @@ export default class EditorModel {
const transformAddedLen = this.getTransformAddedLen(newPosition, inputType, diff);
newPosition = this.positionForOffset(caretOffset + transformAddedLen, true);
}
- this.updateCallback(newPosition, inputType, diff);
+ this.updateCallback?.(newPosition, inputType, diff);
return acPromise;
}
private getTransformAddedLen(newPosition: DocumentPosition, inputType: string, diff: IDiff): number {
- const result = this.transformCallback(newPosition, inputType, diff);
+ const result = this.transformCallback?.(newPosition, inputType, diff);
return Number.isFinite(result) ? (result as number) : 0;
}
@@ -268,13 +268,13 @@ export default class EditorModel {
// rerender even if editor contents didn't change
// to make sure the MessageEditor checks
// model.autoComplete being empty and closes it
- this.updateCallback(pos);
+ this.updateCallback?.(pos);
};
private mergeAdjacentParts(): void {
let prevPart: Part | undefined;
for (let i = 0; i < this._parts.length; ++i) {
- let part = this._parts[i];
+ let part: Part | undefined = this._parts[i];
const isEmpty = !part.text.length;
const isMerged = !isEmpty && prevPart && prevPart.merge?.(part);
if (isEmpty || isMerged) {
@@ -452,13 +452,13 @@ export default class EditorModel {
*/
public transform(callback: ManualTransformCallback): Promise {
const pos = callback();
- let acPromise: Promise = null;
+ let acPromise: Promise | null = null;
if (!(pos instanceof Range)) {
acPromise = this.setActivePart(pos, true);
} else {
acPromise = Promise.resolve();
}
- this.updateCallback(pos);
+ this.updateCallback?.(pos);
return acPromise;
}
}
diff --git a/src/editor/parts.ts b/src/editor/parts.ts
index d5a5c39988..8fde5e4f84 100644
--- a/src/editor/parts.ts
+++ b/src/editor/parts.ts
@@ -422,7 +422,7 @@ class RoomPillPart extends PillPart {
protected setAvatar(node: HTMLElement): void {
let initialLetter = "";
- let avatarUrl = Avatar.avatarUrlForRoom(this.room, 16, 16, "crop");
+ let avatarUrl = Avatar.avatarUrlForRoom(this.room ?? null, 16, 16, "crop");
if (!avatarUrl) {
initialLetter = Avatar.getInitialLetter(this.room?.name || this.resourceId) ?? "";
avatarUrl = Avatar.defaultAvatarUrlForString(this.room?.roomId ?? this.resourceId);
@@ -541,7 +541,7 @@ export class PartCreator {
public constructor(
private readonly room: Room,
private readonly client: MatrixClient,
- autoCompleteCreator: AutoCompleteCreator = null,
+ autoCompleteCreator: AutoCompleteCreator | null = null,
) {
// pre-create the creator as an object even without callback so it can already be passed
// to PillCandidatePart (e.g. while deserializing) and set later on
@@ -574,7 +574,7 @@ export class PartCreator {
return this.plain(text);
}
- public deserializePart(part: SerializedPart): Part {
+ public deserializePart(part: SerializedPart): Part | undefined {
switch (part.type) {
case Type.Plain:
return this.plain(part.text);
@@ -612,7 +612,7 @@ export class PartCreator {
public roomPill(alias: string, roomId?: string): RoomPillPart {
let room: Room | undefined;
if (roomId || alias[0] !== "#") {
- room = this.client.getRoom(roomId || alias);
+ room = this.client.getRoom(roomId || alias) ?? undefined;
} else {
room = this.client.getRooms().find((r) => {
return r.getCanonicalAlias() === alias || r.getAltAliases().includes(alias);
@@ -691,7 +691,7 @@ export class CommandPartCreator extends PartCreator {
return new CommandPart(text, this.autoCompleteCreator);
}
- public deserializePart(part: SerializedPart): Part {
+ public deserializePart(part: SerializedPart): Part | undefined {
if (part.type === Type.Command) {
return this.command(part.text);
} else {
diff --git a/src/editor/render.ts b/src/editor/render.ts
index a5c90a9077..213d68413c 100644
--- a/src/editor/render.ts
+++ b/src/editor/render.ts
@@ -93,8 +93,8 @@ function reconcileLine(lineContainer: ChildNode, parts: Part[]): void {
if (needsCaretNodeBefore(part, prevPart)) {
if (isCaretNode(currentNode as Element)) {
- updateCaretNode(currentNode);
- currentNode = currentNode.nextSibling;
+ updateCaretNode(currentNode!);
+ currentNode = currentNode!.nextSibling;
} else {
lineContainer.insertBefore(createCaretNode(), currentNode);
}
diff --git a/src/editor/serialize.ts b/src/editor/serialize.ts
index eb27c122dc..20ed9ab67e 100644
--- a/src/editor/serialize.ts
+++ b/src/editor/serialize.ts
@@ -63,7 +63,7 @@ interface ISerializeOpts {
export function htmlSerializeIfNeeded(
model: EditorModel,
{ forceHTML = false, useMarkdown = true }: ISerializeOpts = {},
-): string {
+): string | undefined {
if (!useMarkdown) {
return escapeHtml(textSerialize(model)).replace(/\n/g, "
");
}
@@ -72,7 +72,7 @@ export function htmlSerializeIfNeeded(
return htmlSerializeFromMdIfNeeded(md, { forceHTML });
}
-export function htmlSerializeFromMdIfNeeded(md: string, { forceHTML = false } = {}): string {
+export function htmlSerializeFromMdIfNeeded(md: string, { forceHTML = false } = {}): string | undefined {
// copy of raw input to remove unwanted math later
const orig = md;
diff --git a/src/hooks/usePublicRoomDirectory.ts b/src/hooks/usePublicRoomDirectory.ts
index eeda3480f1..e1bf806c0b 100644
--- a/src/hooks/usePublicRoomDirectory.ts
+++ b/src/hooks/usePublicRoomDirectory.ts
@@ -139,7 +139,7 @@ export const usePublicRoomDirectory = (): {
SdkConfig.getObject("room_directory")?.get("servers")?.includes(lsRoomServer) ||
SettingsStore.getValue("room_directory_servers")?.includes(lsRoomServer)
) {
- roomServer = lsRoomServer;
+ roomServer = lsRoomServer!;
}
let instanceId: string | undefined = undefined;
diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts
index 1e5ef56952..cabd4cbee9 100644
--- a/src/hooks/useSettings.ts
+++ b/src/hooks/useSettings.ts
@@ -19,7 +19,7 @@ import { useEffect, useState } from "react";
import SettingsStore from "../settings/SettingsStore";
// Hook to fetch the value of a setting and dynamically update when it changes
-export const useSettingValue = (settingName: string, roomId: string = null, excludeDefault = false): T => {
+export const useSettingValue = (settingName: string, roomId: string | null = null, excludeDefault = false): T => {
const [value, setValue] = useState(SettingsStore.getValue(settingName, roomId, excludeDefault));
useEffect(() => {
@@ -36,7 +36,7 @@ export const useSettingValue = (settingName: string, roomId: string = null, e
};
// Hook to fetch whether a feature is enabled and dynamically update when that changes
-export const useFeatureEnabled = (featureName: string, roomId: string = null): boolean => {
+export const useFeatureEnabled = (featureName: string, roomId: string | null = null): boolean => {
const [enabled, setEnabled] = useState(SettingsStore.getValue(featureName, roomId));
useEffect(() => {
diff --git a/src/hooks/useSlidingSyncRoomSearch.ts b/src/hooks/useSlidingSyncRoomSearch.ts
index 7d5d1d92aa..c4dfbbf409 100644
--- a/src/hooks/useSlidingSyncRoomSearch.ts
+++ b/src/hooks/useSlidingSyncRoomSearch.ts
@@ -23,7 +23,7 @@ import { SlidingSyncManager } from "../SlidingSyncManager";
export interface SlidingSyncRoomSearchOpts {
limit: number;
- query?: string;
+ query: string;
}
export const useSlidingSyncRoomSearch = (): {
@@ -55,7 +55,7 @@ export const useSlidingSyncRoomSearch = (): {
room_name_like: term,
},
});
- const rooms = [];
+ const rooms: Room[] = [];
const { roomIndexToRoomId } = SlidingSyncManager.instance.slidingSync.getListData(
SlidingSyncManager.ListSearch,
)!;
diff --git a/src/hooks/useTimeout.ts b/src/hooks/useTimeout.ts
index 411dcf8501..df00e8bbb5 100644
--- a/src/hooks/useTimeout.ts
+++ b/src/hooks/useTimeout.ts
@@ -31,7 +31,7 @@ export const useTimeout = (handler: Handler, timeoutMs: number): void => {
// Set up timer
useEffect(() => {
const timeoutID = window.setTimeout(() => {
- savedHandler.current();
+ savedHandler.current?.();
}, timeoutMs);
return () => clearTimeout(timeoutID);
}, [timeoutMs]);
@@ -50,7 +50,7 @@ export const useInterval = (handler: Handler, intervalMs: number): void => {
// Set up timer
useEffect(() => {
const intervalID = window.setInterval(() => {
- savedHandler.current();
+ savedHandler.current?.();
}, intervalMs);
return () => clearInterval(intervalID);
}, [intervalMs]);
diff --git a/src/hooks/useUserDirectory.ts b/src/hooks/useUserDirectory.ts
index c256112af7..d775994e3a 100644
--- a/src/hooks/useUserDirectory.ts
+++ b/src/hooks/useUserDirectory.ts
@@ -22,7 +22,7 @@ import { useLatestResult } from "./useLatestResult";
export interface IUserDirectoryOpts {
limit: number;
- query?: string;
+ query: string;
}
export const useUserDirectory = (): {
diff --git a/src/indexing/EventIndex.ts b/src/indexing/EventIndex.ts
index e3407e73b0..fbc528dec4 100644
--- a/src/indexing/EventIndex.ts
+++ b/src/indexing/EventIndex.ts
@@ -27,6 +27,7 @@ import { IEventWithRoomId, IMatrixProfile, IResultRoomEvents } from "matrix-js-s
import { logger } from "matrix-js-sdk/src/logger";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/client";
+import { ISyncStateData, SyncState } from "matrix-js-sdk/src/sync";
import PlatformPeg from "../PlatformPeg";
import { MatrixClientPeg } from "../MatrixClientPeg";
@@ -50,11 +51,11 @@ interface ICrawler {
*/
export default class EventIndex extends EventEmitter {
private crawlerCheckpoints: ICrawlerCheckpoint[] = [];
- private crawler: ICrawler = null;
- private currentCheckpoint: ICrawlerCheckpoint = null;
+ private crawler: ICrawler | null = null;
+ private currentCheckpoint: ICrawlerCheckpoint | null = null;
public async init(): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
this.crawlerCheckpoints = await indexManager.loadCheckpoints();
logger.log("EventIndex: Loaded checkpoints", this.crawlerCheckpoints);
@@ -91,7 +92,7 @@ export default class EventIndex extends EventEmitter {
* Get crawler checkpoints for the encrypted rooms and store them in the index.
*/
public async addInitialCheckpoints(): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
const client = MatrixClientPeg.get();
const rooms = client.getRooms();
@@ -157,8 +158,8 @@ export default class EventIndex extends EventEmitter {
* - Every other sync, tell the event index to commit all the queued up
* live events
*/
- private onSync = async (state: string, prevState: string, data: object): Promise => {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ private onSync = async (state: SyncState, prevState: SyncState | null, data?: ISyncStateData): Promise => {
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
if (prevState === "PREPARED" && state === "SYNCING") {
// If our indexer is empty we're most likely running Element the
@@ -188,7 +189,7 @@ export default class EventIndex extends EventEmitter {
*/
private onRoomTimeline = async (
ev: MatrixEvent,
- room: Room | null,
+ room: Room | undefined,
toStartOfTimeline: boolean,
removed: boolean,
data: IRoomTimelineData,
@@ -198,7 +199,7 @@ export default class EventIndex extends EventEmitter {
const client = MatrixClientPeg.get();
// We only index encrypted rooms locally.
- if (!client.isRoomEncrypted(ev.getRoomId())) return;
+ if (!client.isRoomEncrypted(ev.getRoomId()!)) return;
if (ev.isRedaction()) {
return this.redactEvent(ev);
@@ -228,7 +229,7 @@ export default class EventIndex extends EventEmitter {
* We cannot rely on Room.redaction as this only fires if the redaction applied to an event the js-sdk has loaded.
*/
private redactEvent = async (ev: MatrixEvent): Promise => {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
try {
await indexManager.deleteEvent(ev.getAssociatedId());
@@ -321,15 +322,15 @@ export default class EventIndex extends EventEmitter {
* @param {MatrixEvent} ev The event that should be added to the index.
*/
private async addLiveEventToIndex(ev: MatrixEvent): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
- if (!this.isValidEvent(ev)) return;
+ if (!indexManager || !this.isValidEvent(ev)) return;
const e = this.eventToJson(ev);
const profile = {
- displayname: ev.sender.rawDisplayName,
- avatar_url: ev.sender.getMxcAvatarUrl(),
+ displayname: ev.sender?.rawDisplayName,
+ avatar_url: ev.sender?.getMxcAvatarUrl(),
};
await indexManager.addEventToIndex(e, profile);
@@ -353,7 +354,7 @@ export default class EventIndex extends EventEmitter {
}
private async addRoomCheckpoint(roomId: string, fullCrawl = false): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
const client = MatrixClientPeg.get();
const room = client.getRoom(roomId);
@@ -401,7 +402,7 @@ export default class EventIndex extends EventEmitter {
let cancelled = false;
const client = MatrixClientPeg.get();
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
this.crawler = {
cancel: () => {
@@ -649,7 +650,7 @@ export default class EventIndex extends EventEmitter {
* task, and closes the index.
*/
public async close(): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
this.removeListeners();
this.stopCrawler();
await indexManager.closeEventIndex();
@@ -665,7 +666,7 @@ export default class EventIndex extends EventEmitter {
* of search results once the search is done.
*/
public async search(searchArgs: ISearchArgs): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
return indexManager.searchEventIndex(searchArgs);
}
@@ -693,11 +694,11 @@ export default class EventIndex extends EventEmitter {
public async loadFileEvents(
room: Room,
limit = 10,
- fromEvent: string = null,
+ fromEvent?: string,
direction: string = EventTimeline.BACKWARDS,
): Promise {
const client = MatrixClientPeg.get();
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
const loadArgs: ILoadArgs = {
roomId: room.roomId,
@@ -790,7 +791,7 @@ export default class EventIndex extends EventEmitter {
timeline: EventTimeline,
room: Room,
limit = 10,
- fromEvent: string = null,
+ fromEvent?: string,
direction: string = EventTimeline.BACKWARDS,
): Promise {
const matrixEvents = await this.loadFileEvents(room, limit, fromEvent, direction);
@@ -807,7 +808,7 @@ export default class EventIndex extends EventEmitter {
// Add the events to the timeline of the file panel.
matrixEvents.forEach((e) => {
- if (!timelineSet.eventIdToTimeline(e.getId())) {
+ if (!timelineSet.eventIdToTimeline(e.getId()!)) {
timelineSet.addEventToTimeline(e, timeline, direction == EventTimeline.BACKWARDS);
}
});
@@ -817,7 +818,7 @@ export default class EventIndex extends EventEmitter {
// Set the pagination token to the oldest event that we retrieved.
if (matrixEvents.length > 0) {
- paginationToken = matrixEvents[matrixEvents.length - 1].getId();
+ paginationToken = matrixEvents[matrixEvents.length - 1].getId()!;
ret = true;
}
@@ -878,11 +879,11 @@ export default class EventIndex extends EventEmitter {
): Promise => {
const timeline = timelineIndex.timeline;
const timelineSet = timeline.getTimelineSet();
- const token = timeline.getPaginationToken(direction);
+ const token = timeline.getPaginationToken(direction) ?? undefined;
const ret = await this.populateFileTimeline(timelineSet, timeline, room, limit, token, direction);
- timelineIndex.pendingPaginate = null;
+ timelineIndex.pendingPaginate = undefined;
timelineWindow.extend(direction, limit);
return ret;
@@ -900,9 +901,9 @@ export default class EventIndex extends EventEmitter {
* @return {Promise} A promise that will resolve to the index
* statistics.
*/
- public async getStats(): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
- return indexManager.getStats();
+ public async getStats(): Promise {
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
+ return indexManager?.getStats();
}
/**
@@ -914,9 +915,9 @@ export default class EventIndex extends EventEmitter {
* @return {Promise} Returns true if the index contains events for
* the given room, false otherwise.
*/
- public async isRoomIndexed(roomId: string): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
- return indexManager.isRoomIndexed(roomId);
+ public async isRoomIndexed(roomId: string): Promise {
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
+ return indexManager?.isRoomIndexed(roomId);
}
/**
diff --git a/src/indexing/EventIndexPeg.ts b/src/indexing/EventIndexPeg.ts
index 77b93bf6f5..11c4696fc1 100644
--- a/src/indexing/EventIndexPeg.ts
+++ b/src/indexing/EventIndexPeg.ts
@@ -36,8 +36,8 @@ const INDEX_VERSION = 1;
* you'll find a `EventIndex` hanging on the `EventIndexPeg`.
*/
export class EventIndexPeg {
- public index: EventIndex = null;
- public error: Error = null;
+ public index: EventIndex | null = null;
+ public error: Error | null = null;
private _supportIsInstalled = false;
@@ -49,7 +49,7 @@ export class EventIndexPeg {
* EventIndex was successfully initialized, false otherwise.
*/
public async init(): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
if (!indexManager) {
logger.log("EventIndex: Platform doesn't support event indexing, not initializing.");
return false;
@@ -78,11 +78,14 @@ export class EventIndexPeg {
*/
public async initEventIndex(): Promise {
const index = new EventIndex();
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
const client = MatrixClientPeg.get();
+ if (!indexManager || !client) {
+ throw new Error("Unable to init event index");
+ }
- const userId = client.getUserId();
- const deviceId = client.getDeviceId();
+ const userId = client.getUserId()!;
+ const deviceId = client.getDeviceId()!;
try {
await indexManager.initEventIndex(userId, deviceId);
@@ -120,7 +123,7 @@ export class EventIndexPeg {
* does not mean that support is installed.
*/
public platformHasSupport(): boolean {
- return PlatformPeg.get().getEventIndexingManager() !== null;
+ return PlatformPeg.get()?.getEventIndexingManager() != null;
}
/**
@@ -141,7 +144,7 @@ export class EventIndexPeg {
*
* @return {EventIndex} The current event index.
*/
- public get(): EventIndex {
+ public get(): EventIndex | null {
return this.index;
}
@@ -178,9 +181,9 @@ export class EventIndexPeg {
* deleted.
*/
public async deleteEventIndex(): Promise {
- const indexManager = PlatformPeg.get().getEventIndexingManager();
+ const indexManager = PlatformPeg.get()?.getEventIndexingManager();
- if (indexManager !== null) {
+ if (indexManager) {
await this.unset();
logger.log("EventIndex: Deleting event index.");
await indexManager.deleteEventIndex();
diff --git a/src/integrations/IntegrationManagerInstance.ts b/src/integrations/IntegrationManagerInstance.ts
index 68ca528e77..8a61705dae 100644
--- a/src/integrations/IntegrationManagerInstance.ts
+++ b/src/integrations/IntegrationManagerInstance.ts
@@ -33,18 +33,13 @@ export enum Kind {
}
export class IntegrationManagerInstance {
- public readonly apiUrl: string;
- public readonly uiUrl: string;
- public readonly kind: string;
- public readonly id: string; // only applicable in some cases
-
// Per the spec: UI URL is optional.
- public constructor(kind: string, apiUrl: string, uiUrl: string = apiUrl, id?: string) {
- this.kind = kind;
- this.apiUrl = apiUrl;
- this.uiUrl = uiUrl;
- this.id = id;
- }
+ public constructor(
+ public readonly kind: string,
+ public readonly apiUrl: string,
+ public readonly uiUrl: string = apiUrl,
+ public readonly id?: string, // only applicable in some cases
+ ) {}
public get name(): string {
const parsed = url.parse(this.uiUrl);
@@ -62,7 +57,7 @@ export class IntegrationManagerInstance {
return new ScalarAuthClient(this.apiUrl, this.uiUrl);
}
- public async open(room: Room = null, screen: string = null, integrationId: string = null): Promise {
+ public async open(room: Room, screen?: string, integrationId?: string): Promise {
if (!SettingsStore.getValue("integrationProvisioning")) {
return IntegrationManagers.sharedInstance().showDisabledDialog();
}
diff --git a/src/integrations/IntegrationManagers.ts b/src/integrations/IntegrationManagers.ts
index 7aeaf4ab47..c1f8eb5a3c 100644
--- a/src/integrations/IntegrationManagers.ts
+++ b/src/integrations/IntegrationManagers.ts
@@ -40,7 +40,7 @@ export class IntegrationManagers {
private managers: IntegrationManagerInstance[] = [];
private client: MatrixClient;
- private primaryManager: IntegrationManagerInstance;
+ private primaryManager: IntegrationManagerInstance | null;
public static sharedInstance(): IntegrationManagers {
if (!IntegrationManagers.instance) {
@@ -146,7 +146,7 @@ export class IntegrationManagers {
}
public getOrderedManagers(): IntegrationManagerInstance[] {
- const ordered = [];
+ const ordered: IntegrationManagerInstance[] = [];
for (const kind of KIND_PREFERENCE) {
const managers = this.managers.filter((m) => m.kind === kind);
if (!managers || !managers.length) continue;
@@ -161,7 +161,7 @@ export class IntegrationManagers {
return ordered;
}
- public getPrimaryManager(): IntegrationManagerInstance {
+ public getPrimaryManager(): IntegrationManagerInstance | null {
if (this.hasManager()) {
if (this.primaryManager) return this.primaryManager;
@@ -195,7 +195,7 @@ export class IntegrationManagers {
* @returns {Promise} Resolves to an integration manager instance,
* or null if none was found.
*/
- public async tryDiscoverManager(domainName: string): Promise {
+ public async tryDiscoverManager(domainName: string): Promise {
logger.log("Looking up integration manager via .well-known");
if (domainName.startsWith("http:") || domainName.startsWith("https:")) {
// trim off the scheme and just use the domain
diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx
index 623737175d..ec37d32965 100644
--- a/src/languageHandler.tsx
+++ b/src/languageHandler.tsx
@@ -194,7 +194,7 @@ const annotateStrings = (result: TranslatedString, translationKey: string): Tran
*/
// eslint-next-line @typescript-eslint/naming-convention
export function _t(text: string, variables?: IVariables): string;
-export function _t(text: string, variables: IVariables, tags: Tags): React.ReactNode;
+export function _t(text: string, variables: IVariables | undefined, tags: Tags): React.ReactNode;
export function _t(text: string, variables?: IVariables, tags?: Tags): TranslatedString {
// The translation returns text so there's no XSS vector here (no unsafe HTML, no code execution)
const { translated } = safeCounterpartTranslate(text, variables);
diff --git a/src/linkify-matrix.ts b/src/linkify-matrix.ts
index 64a66345ed..29258558ce 100644
--- a/src/linkify-matrix.ts
+++ b/src/linkify-matrix.ts
@@ -19,7 +19,7 @@ import * as linkifyjs from "linkifyjs";
import { Opts, registerCustomProtocol, registerPlugin } from "linkifyjs";
import linkifyElement from "linkify-element";
import linkifyString from "linkify-string";
-import { RoomMember } from "matrix-js-sdk/src/models/room-member";
+import { User } from "matrix-js-sdk/src/matrix";
import {
parsePermalink,
@@ -105,13 +105,9 @@ function matrixOpaqueIdLinkifyParser({
function onUserClick(event: MouseEvent, userId: string): void {
event.preventDefault();
- const member = new RoomMember(null, userId);
- if (!member) {
- return;
- }
dis.dispatch({
action: Action.ViewUser,
- member: member,
+ member: new User(userId),
});
}
diff --git a/src/modules/ProxiedModuleApi.ts b/src/modules/ProxiedModuleApi.ts
index 03374a7df0..56fc3ff121 100644
--- a/src/modules/ProxiedModuleApi.ts
+++ b/src/modules/ProxiedModuleApi.ts
@@ -101,10 +101,10 @@ export class ProxiedModuleApi implements ModuleApi {
password: string,
displayName?: string,
): Promise {
- const hsUrl = SdkConfig.get("validated_server_config").hsUrl;
+ const hsUrl = SdkConfig.get("validated_server_config")?.hsUrl;
const client = Matrix.createClient({ baseUrl: hsUrl });
const deviceName =
- SdkConfig.get("default_device_display_name") || PlatformPeg.get().getDefaultDeviceDisplayName();
+ SdkConfig.get("default_device_display_name") || PlatformPeg.get()?.getDefaultDeviceDisplayName();
const req: IRegisterRequestParams = {
username,
password,
@@ -134,9 +134,9 @@ export class ProxiedModuleApi implements ModuleApi {
return {
homeserverUrl: hsUrl,
- userId: creds.user_id,
- deviceId: creds.device_id,
- accessToken: creds.access_token,
+ userId: creds.user_id!,
+ deviceId: creds.device_id!,
+ accessToken: creds.access_token!,
};
}
@@ -163,8 +163,8 @@ export class ProxiedModuleApi implements ModuleApi {
navigateToPermalink(uri);
const parts = parsePermalink(uri);
- if (parts.roomIdOrAlias && andJoin) {
- let roomId = parts.roomIdOrAlias;
+ if (parts?.roomIdOrAlias && andJoin) {
+ let roomId: string | undefined = parts.roomIdOrAlias;
let servers = parts.viaServers;
if (roomId.startsWith("#")) {
roomId = getCachedRoomIDForAlias(parts.roomIdOrAlias);
diff --git a/src/notifications/PushRuleVectorState.ts b/src/notifications/PushRuleVectorState.ts
index 47b4e93774..2ff504815f 100644
--- a/src/notifications/PushRuleVectorState.ts
+++ b/src/notifications/PushRuleVectorState.ts
@@ -53,6 +53,7 @@ export class PushRuleVectorState {
} else if (pushRuleVectorState === VectorState.Loud) {
return StandardActions.ACTION_HIGHLIGHT_DEFAULT_SOUND;
}
+ return [];
}
/**
diff --git a/src/rageshake/rageshake.ts b/src/rageshake/rageshake.ts
index c0b538f6fb..9238e230dd 100644
--- a/src/rageshake/rageshake.ts
+++ b/src/rageshake/rageshake.ts
@@ -76,7 +76,7 @@ export class ConsoleLogger {
}
public bypassRageshake(fnName: LogFunctionName, ...args: (Error | DOMException | object | string)[]): void {
- this.originalFunctions[fnName](...args);
+ this.originalFunctions[fnName]?.(...args);
}
public log(level: string, ...args: (Error | DOMException | object | string)[]): void {
@@ -152,7 +152,7 @@ export class IndexedDBLogStore {
};
req.onerror = () => {
- const err = "Failed to open log database: " + req.error.name;
+ const err = "Failed to open log database: " + req.error?.name;
logger.error(err);
reject(new Error(err));
};
@@ -234,7 +234,7 @@ export class IndexedDBLogStore {
};
txn.onerror = () => {
logger.error("Failed to flush logs : ", txn.error);
- reject(new Error("Failed to write logs: " + txn.error.message));
+ reject(new Error("Failed to write logs: " + txn.error?.message));
};
objStore.add(this.generateLogEntry(lines));
const lastModStore = txn.objectStore("logslastmod");
@@ -267,7 +267,7 @@ export class IndexedDBLogStore {
const query = objectStore.index("id").openCursor(IDBKeyRange.only(id), "prev");
let lines = "";
query.onerror = () => {
- reject(new Error("Query failed: " + query.error.message));
+ reject(new Error("Query failed: " + query.error?.message));
};
query.onsuccess = () => {
const cursor = query.result;
@@ -322,7 +322,7 @@ export class IndexedDBLogStore {
resolve();
};
txn.onerror = () => {
- reject(new Error("Failed to delete logs for " + `'${id}' : ${query.error.message}`));
+ reject(new Error("Failed to delete logs for " + `'${id}' : ${query.error?.message}`));
};
// delete last modified entries
const lastModStore = txn.objectStore("logslastmod");
@@ -401,14 +401,14 @@ export class IndexedDBLogStore {
*/
function selectQuery(
store: IDBIndex | IDBObjectStore,
- keyRange: IDBKeyRange,
+ keyRange: IDBKeyRange | undefined,
resultMapper: (cursor: IDBCursorWithValue) => T,
): Promise {
const query = store.openCursor(keyRange);
return new Promise((resolve, reject) => {
const results: T[] = [];
query.onerror = () => {
- reject(new Error("Query failed: " + query.error.message));
+ reject(new Error("Query failed: " + query.error?.message));
};
// collect results
query.onsuccess = () => {
diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts
index ef03e96683..bcc7b14509 100644
--- a/src/settings/SettingsStore.ts
+++ b/src/settings/SettingsStore.ts
@@ -437,7 +437,7 @@ export default class SettingsStore {
level: SettingLevel,
roomId: string | null,
calculatedValue: any,
- calculatedAtLevel: SettingLevel,
+ calculatedAtLevel: SettingLevel | null,
): any {
let resultingValue = calculatedValue;
diff --git a/src/settings/controllers/IncompatibleController.ts b/src/settings/controllers/IncompatibleController.ts
index 3621a736a4..e69848733d 100644
--- a/src/settings/controllers/IncompatibleController.ts
+++ b/src/settings/controllers/IncompatibleController.ts
@@ -36,7 +36,7 @@ export default class IncompatibleController extends SettingController {
level: SettingLevel,
roomId: string,
calculatedValue: any,
- calculatedAtLevel: SettingLevel,
+ calculatedAtLevel: SettingLevel | null,
): any {
if (this.incompatibleSetting) {
return this.forcedValue;
diff --git a/src/settings/controllers/NotificationControllers.ts b/src/settings/controllers/NotificationControllers.ts
index 6c8c351b0f..aae9b16ba2 100644
--- a/src/settings/controllers/NotificationControllers.ts
+++ b/src/settings/controllers/NotificationControllers.ts
@@ -53,7 +53,7 @@ export class NotificationsEnabledController extends SettingController {
level: SettingLevel,
roomId: string,
calculatedValue: any,
- calculatedAtLevel: SettingLevel,
+ calculatedAtLevel: SettingLevel | null,
): any {
if (!getNotifier().isPossible()) return false;
diff --git a/src/settings/controllers/OrderedMultiController.ts b/src/settings/controllers/OrderedMultiController.ts
index 70ffa99b68..fa8535ffd6 100644
--- a/src/settings/controllers/OrderedMultiController.ts
+++ b/src/settings/controllers/OrderedMultiController.ts
@@ -35,7 +35,7 @@ export class OrderedMultiController extends SettingController {
level: SettingLevel,
roomId: string,
calculatedValue: any,
- calculatedAtLevel: SettingLevel,
+ calculatedAtLevel: SettingLevel | null,
): any {
for (const controller of this.controllers) {
const override = controller.getValueOverride(level, roomId, calculatedValue, calculatedAtLevel);
diff --git a/src/settings/controllers/ReducedMotionController.ts b/src/settings/controllers/ReducedMotionController.ts
index d98ca16513..c9f293fbd7 100644
--- a/src/settings/controllers/ReducedMotionController.ts
+++ b/src/settings/controllers/ReducedMotionController.ts
@@ -27,7 +27,7 @@ export default class ReducedMotionController extends SettingController {
level: SettingLevel,
roomId: string,
calculatedValue: any,
- calculatedAtLevel: SettingLevel,
+ calculatedAtLevel: SettingLevel | null,
): any {
if (this.prefersReducedMotion()) {
return false;
diff --git a/src/settings/controllers/SettingController.ts b/src/settings/controllers/SettingController.ts
index 725dccc623..d3a52dbb8c 100644
--- a/src/settings/controllers/SettingController.ts
+++ b/src/settings/controllers/SettingController.ts
@@ -41,7 +41,7 @@ export default abstract class SettingController {
level: SettingLevel,
roomId: string | null,
calculatedValue: any,
- calculatedAtLevel: SettingLevel,
+ calculatedAtLevel: SettingLevel | null,
): any {
return null; // no override
}
diff --git a/src/settings/controllers/ThemeController.ts b/src/settings/controllers/ThemeController.ts
index ab5410c459..9c7ce6cc7a 100644
--- a/src/settings/controllers/ThemeController.ts
+++ b/src/settings/controllers/ThemeController.ts
@@ -26,7 +26,7 @@ export default class ThemeController extends SettingController {
level: SettingLevel,
roomId: string,
calculatedValue: any,
- calculatedAtLevel: SettingLevel,
+ calculatedAtLevel: SettingLevel | null,
): any {
if (!calculatedValue) return null; // Don't override null themes
diff --git a/src/settings/controllers/UIFeatureController.ts b/src/settings/controllers/UIFeatureController.ts
index 2748eec16a..31a2be0efc 100644
--- a/src/settings/controllers/UIFeatureController.ts
+++ b/src/settings/controllers/UIFeatureController.ts
@@ -34,7 +34,7 @@ export default class UIFeatureController extends SettingController {
level: SettingLevel,
roomId: string,
calculatedValue: any,
- calculatedAtLevel: SettingLevel,
+ calculatedAtLevel: SettingLevel | null,
): any {
if (this.settingDisabled) {
// per the docs: we force a disabled state when the feature isn't active
diff --git a/src/settings/enums/ImageSize.ts b/src/settings/enums/ImageSize.ts
index cc5596a344..28f72cb8de 100644
--- a/src/settings/enums/ImageSize.ts
+++ b/src/settings/enums/ImageSize.ts
@@ -22,7 +22,7 @@ const SIZE_LARGE = { w: 800, h: 600 };
const SIZE_NORMAL_LANDSCAPE = { w: 324, h: 324 }; // for w > h
const SIZE_NORMAL_PORTRAIT = { w: Math.ceil(324 * (9 / 16)), h: 324 }; // for h > w
-type Dimensions = { w: number; h: number };
+type Dimensions = { w?: number; h?: number };
export enum ImageSize {
Normal = "normal",
@@ -36,7 +36,7 @@ export enum ImageSize {
* @returns {Dimensions} The suggested maximum dimensions for the image
*/
export function suggestedSize(size: ImageSize, contentSize: Dimensions, maxHeight?: number): Dimensions {
- const aspectRatio = contentSize.w / contentSize.h;
+ const aspectRatio = contentSize.w! / contentSize.h!;
const portrait = aspectRatio < 1;
const maxSize = size === ImageSize.Large ? SIZE_LARGE : portrait ? SIZE_NORMAL_PORTRAIT : SIZE_NORMAL_LANDSCAPE;
diff --git a/src/stores/RoomScrollStateStore.ts b/src/stores/RoomScrollStateStore.ts
index 87b48dad57..61e89ed8de 100644
--- a/src/stores/RoomScrollStateStore.ts
+++ b/src/stores/RoomScrollStateStore.ts
@@ -38,7 +38,7 @@ export class RoomScrollStateStore {
// from the focussedEvent.
private scrollStateMap = new Map();
- public getScrollState(roomId: string): ScrollState {
+ public getScrollState(roomId: string): ScrollState | undefined {
return this.scrollStateMap.get(roomId);
}
diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx
index 6dca6dce24..86f0f6bdb2 100644
--- a/src/stores/RoomViewStore.tsx
+++ b/src/stores/RoomViewStore.tsx
@@ -712,7 +712,7 @@ export class RoomViewStore extends EventEmitter {
}
// The mxEvent if one is currently being replied to/quoted
- public getQuotingEvent(): Optional {
+ public getQuotingEvent(): MatrixEvent | null {
return this.state.replyingToEvent;
}
diff --git a/src/stores/room-list/SlidingRoomListStore.ts b/src/stores/room-list/SlidingRoomListStore.ts
index ff2113379d..cc4de473b8 100644
--- a/src/stores/room-list/SlidingRoomListStore.ts
+++ b/src/stores/room-list/SlidingRoomListStore.ts
@@ -17,6 +17,7 @@ limitations under the License.
import { Room } from "matrix-js-sdk/src/models/room";
import { logger } from "matrix-js-sdk/src/logger";
import { MSC3575Filter, SlidingSyncEvent } from "matrix-js-sdk/src/sliding-sync";
+import { Optional } from "matrix-events-sdk";
import { RoomUpdateCause, TagID, OrderedDefaultTagIDs, DefaultTagID } from "./models";
import { ITagMap, ListAlgorithm, SortAlgorithm } from "./algorithms/models";
@@ -79,12 +80,11 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient impl
private tagIdToSortAlgo: Record = {};
private tagMap: ITagMap = {};
private counts: Record = {};
- private stickyRoomId: string | null;
+ private stickyRoomId: Optional;
public constructor(dis: MatrixDispatcher, private readonly context: SdkContextClass) {
super(dis);
this.setMaxListeners(20); // RoomList + LeftPanel + 8xRoomSubList + spares
- this.stickyRoomId = null;
}
public async setTagSorting(tagId: TagID, sort: SortAlgorithm): Promise {
diff --git a/src/stores/room-list/previews/ReactionEventPreview.ts b/src/stores/room-list/previews/ReactionEventPreview.ts
index 6a9ae21afc..6af7ebab70 100644
--- a/src/stores/room-list/previews/ReactionEventPreview.ts
+++ b/src/stores/room-list/previews/ReactionEventPreview.ts
@@ -24,14 +24,17 @@ import SettingsStore from "../../../settings/SettingsStore";
import DMRoomMap from "../../../utils/DMRoomMap";
export class ReactionEventPreview implements IPreview {
- public getTextFor(event: MatrixEvent, tagId?: TagID, isThread?: boolean): string {
+ public getTextFor(event: MatrixEvent, tagId?: TagID, isThread?: boolean): string | null {
const showDms = SettingsStore.getValue("feature_roomlist_preview_reactions_dms");
const showAll = SettingsStore.getValue("feature_roomlist_preview_reactions_all");
+ const roomId = event.getRoomId();
+ if (!roomId) return null; // not a room event
+
// If we're not showing all reactions, see if we're showing DMs instead
if (!showAll) {
// If we're not showing reactions on DMs, or we are and the room isn't a DM, skip
- if (!(showDms && DMRoomMap.shared().getUserIdForRoomId(event.getRoomId()))) {
+ if (!(showDms && DMRoomMap.shared().getUserIdForRoomId(roomId))) {
return null;
}
}
@@ -42,7 +45,7 @@ export class ReactionEventPreview implements IPreview {
const reaction = relation.key;
if (!reaction) return null; // invalid reaction (unknown format)
- if (isThread || isSelf(event) || !shouldPrefixMessagesIn(event.getRoomId(), tagId)) {
+ if (isThread || isSelf(event) || !shouldPrefixMessagesIn(roomId, tagId)) {
return reaction;
} else {
return _t("%(senderName)s: %(reaction)s", { senderName: getSenderName(event), reaction });
diff --git a/src/stores/room-list/previews/utils.ts b/src/stores/room-list/previews/utils.ts
index b12128943b..116e97b515 100644
--- a/src/stores/room-list/previews/utils.ts
+++ b/src/stores/room-list/previews/utils.ts
@@ -27,7 +27,7 @@ export function isSelf(event: MatrixEvent): boolean {
return event.getSender() === selfUserId;
}
-export function shouldPrefixMessagesIn(roomId: string, tagId: TagID): boolean {
+export function shouldPrefixMessagesIn(roomId: string, tagId?: TagID): boolean {
if (tagId !== DefaultTagID.DM) return true;
// We don't prefix anything in 1:1s
diff --git a/src/stores/spaces/SpaceStore.ts b/src/stores/spaces/SpaceStore.ts
index 5188af7354..3405155382 100644
--- a/src/stores/spaces/SpaceStore.ts
+++ b/src/stores/spaces/SpaceStore.ts
@@ -137,7 +137,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
userIdsBySpace: new Map>(),
};
// The space currently selected in the Space Panel
- private _activeSpace?: SpaceKey = MetaSpace.Home; // set properly by onReady
+ private _activeSpace: SpaceKey = MetaSpace.Home; // set properly by onReady
private _suggestedRooms: ISuggestedRoom[] = [];
private _invitedSpaces = new Set();
private spaceOrderLocalEchoMap = new Map();
@@ -812,13 +812,13 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
const spaceDiff = mapDiff(prevChildSpacesBySpace, this.childSpacesBySpace);
// filter out keys which changed by reference only by checking whether the sets differ
const roomsChanged = roomDiff.changed.filter((k) => {
- return setHasDiff(prevRoomsBySpace.get(k), this.roomIdsBySpace.get(k));
+ return setHasDiff(prevRoomsBySpace.get(k)!, this.roomIdsBySpace.get(k)!);
});
const usersChanged = userDiff.changed.filter((k) => {
- return setHasDiff(prevUsersBySpace.get(k), this.userIdsBySpace.get(k));
+ return setHasDiff(prevUsersBySpace.get(k)!, this.userIdsBySpace.get(k)!);
});
const spacesChanged = spaceDiff.changed.filter((k) => {
- return setHasDiff(prevChildSpacesBySpace.get(k), this.childSpacesBySpace.get(k));
+ return setHasDiff(prevChildSpacesBySpace.get(k)!, this.childSpacesBySpace.get(k)!);
});
const changeSet = new Set([
@@ -1142,9 +1142,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
// restore selected state from last session if any and still valid
const lastSpaceId = window.localStorage.getItem(ACTIVE_SPACE_LS_KEY);
const valid =
- lastSpaceId && !isMetaSpace(lastSpaceId)
- ? this.matrixClient.getRoom(lastSpaceId)
- : enabledMetaSpaces[lastSpaceId];
+ lastSpaceId &&
+ (!isMetaSpace(lastSpaceId) ? this.matrixClient.getRoom(lastSpaceId) : enabledMetaSpaces[lastSpaceId]);
if (valid) {
// don't context switch here as it may break permalinks
this.setActiveSpace(lastSpaceId, false);
@@ -1285,7 +1284,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
public getNotificationState(key: SpaceKey): SpaceNotificationState {
if (this.notificationStateMap.has(key)) {
- return this.notificationStateMap.get(key);
+ return this.notificationStateMap.get(key)!;
}
const state = new SpaceNotificationState(getRoomFn);
diff --git a/src/stores/spaces/SpaceTreeLevelLayoutStore.ts b/src/stores/spaces/SpaceTreeLevelLayoutStore.ts
index 3e5d5faa98..ced6ea5a71 100644
--- a/src/stores/spaces/SpaceTreeLevelLayoutStore.ts
+++ b/src/stores/spaces/SpaceTreeLevelLayoutStore.ts
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-const getSpaceCollapsedKey = (roomId: string, parents: Set): string => {
+const getSpaceCollapsedKey = (roomId: string, parents?: Set): string => {
const separator = "/";
let path = "";
if (parents) {
@@ -35,12 +35,12 @@ export default class SpaceTreeLevelLayoutStore {
return SpaceTreeLevelLayoutStore.internalInstance;
}
- public setSpaceCollapsedState(roomId: string, parents: Set, collapsed: boolean): void {
+ public setSpaceCollapsedState(roomId: string, parents: Set | undefined, collapsed: boolean): void {
// XXX: localStorage doesn't allow booleans
localStorage.setItem(getSpaceCollapsedKey(roomId, parents), collapsed.toString());
}
- public getSpaceCollapsedState(roomId: string, parents: Set, fallback: boolean): boolean {
+ public getSpaceCollapsedState(roomId: string, parents: Set | undefined, fallback: boolean): boolean {
const collapsedLocalStorage = localStorage.getItem(getSpaceCollapsedKey(roomId, parents));
// XXX: localStorage doesn't allow booleans
return collapsedLocalStorage ? collapsedLocalStorage === "true" : fallback;
diff --git a/src/stores/widgets/StopGapWidget.ts b/src/stores/widgets/StopGapWidget.ts
index f87da3bc18..3b0a49f818 100644
--- a/src/stores/widgets/StopGapWidget.ts
+++ b/src/stores/widgets/StopGapWidget.ts
@@ -216,8 +216,8 @@ export class StopGapWidget extends EventEmitter {
const defaults: ITemplateParams = {
widgetRoomId: this.roomId,
currentUserId: this.client.getUserId()!,
- userDisplayName: OwnProfileStore.instance.displayName,
- userHttpAvatarUrl: OwnProfileStore.instance.getHttpAvatarUrl(),
+ userDisplayName: OwnProfileStore.instance.displayName ?? undefined,
+ userHttpAvatarUrl: OwnProfileStore.instance.getHttpAvatarUrl() ?? undefined,
clientId: ELEMENT_CLIENT_ID,
clientTheme: SettingsStore.getValue("theme"),
clientLanguage: getUserLanguage(),
diff --git a/src/stores/widgets/WidgetLayoutStore.ts b/src/stores/widgets/WidgetLayoutStore.ts
index 1d3b2aa1d9..a204b7d6ed 100644
--- a/src/stores/widgets/WidgetLayoutStore.ts
+++ b/src/stores/widgets/WidgetLayoutStore.ts
@@ -477,7 +477,7 @@ export class WidgetLayoutStore extends ReadyWatchingStore {
this.updateUserLayout(room, newLayout);
}
- public hasMaximisedWidget(room: Room): boolean {
+ public hasMaximisedWidget(room?: Room): boolean {
return this.getContainerWidgets(room, Container.Center).length > 0;
}
diff --git a/src/toasts/SetupEncryptionToast.ts b/src/toasts/SetupEncryptionToast.ts
index b711cce972..3b60705ec7 100644
--- a/src/toasts/SetupEncryptionToast.ts
+++ b/src/toasts/SetupEncryptionToast.ts
@@ -85,11 +85,11 @@ export const showToast = (kind: Kind): void => {
const onAccept = async (): Promise => {
if (kind === Kind.VERIFY_THIS_SESSION) {
- Modal.createDialog(SetupEncryptionDialog, {}, null, /* priority = */ false, /* static = */ true);
+ Modal.createDialog(SetupEncryptionDialog, {}, undefined, /* priority = */ false, /* static = */ true);
} else {
const modal = Modal.createDialog(
Spinner,
- null,
+ undefined,
"mx_Dialog_spinner",
/* priority */ false,
/* static */ true,
diff --git a/src/utils/IdentityServerUtils.ts b/src/utils/IdentityServerUtils.ts
index 7b820dc5c8..a9a5c754a0 100644
--- a/src/utils/IdentityServerUtils.ts
+++ b/src/utils/IdentityServerUtils.ts
@@ -19,6 +19,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import SdkConfig from "../SdkConfig";
import { MatrixClientPeg } from "../MatrixClientPeg";
+import { Policies } from "../Terms";
export function getDefaultIdentityServerUrl(): string {
return SdkConfig.get("validated_server_config").isUrl;
@@ -33,7 +34,7 @@ export function setToDefaultIdentityServer(): void {
}
export async function doesIdentityServerHaveTerms(fullUrl: string): Promise {
- let terms;
+ let terms: { policies?: Policies } | null;
try {
terms = await MatrixClientPeg.get().getTerms(SERVICE_TYPES.IS, fullUrl);
} catch (e) {
@@ -45,7 +46,7 @@ export async function doesIdentityServerHaveTerms(fullUrl: string): Promise 0;
+ return !!terms?.["policies"] && Object.keys(terms["policies"]).length > 0;
}
export function doesAccountDataHaveIdentityServer(): boolean {
diff --git a/src/utils/MediaEventHelper.ts b/src/utils/MediaEventHelper.ts
index 18b119b63f..2e576f9a11 100644
--- a/src/utils/MediaEventHelper.ts
+++ b/src/utils/MediaEventHelper.ts
@@ -28,12 +28,12 @@ import { IDestroyable } from "./IDestroyable";
export class MediaEventHelper implements IDestroyable {
// Either an HTTP or Object URL (when encrypted) to the media.
- public readonly sourceUrl: LazyValue;
- public readonly thumbnailUrl: LazyValue;
+ public readonly sourceUrl: LazyValue;
+ public readonly thumbnailUrl: LazyValue;
// Either the raw or decrypted (when encrypted) contents of the file.
public readonly sourceBlob: LazyValue;
- public readonly thumbnailBlob: LazyValue;
+ public readonly thumbnailBlob: LazyValue;
public readonly media: Media;
@@ -56,12 +56,12 @@ export class MediaEventHelper implements IDestroyable {
public destroy(): void {
if (this.media.isEncrypted) {
- if (this.sourceUrl.present) URL.revokeObjectURL(this.sourceUrl.cachedValue);
- if (this.thumbnailUrl.present) URL.revokeObjectURL(this.thumbnailUrl.cachedValue);
+ if (this.sourceUrl.cachedValue) URL.revokeObjectURL(this.sourceUrl.cachedValue);
+ if (this.thumbnailUrl.cachedValue) URL.revokeObjectURL(this.thumbnailUrl.cachedValue);
}
}
- private prepareSourceUrl = async (): Promise => {
+ private prepareSourceUrl = async (): Promise => {
if (this.media.isEncrypted) {
const blob = await this.sourceBlob.value;
return URL.createObjectURL(blob);
@@ -70,7 +70,7 @@ export class MediaEventHelper implements IDestroyable {
}
};
- private prepareThumbnailUrl = async (): Promise => {
+ private prepareThumbnailUrl = async (): Promise => {
if (this.media.isEncrypted) {
const blob = await this.thumbnailBlob.value;
if (blob === null) return null;
@@ -83,12 +83,12 @@ export class MediaEventHelper implements IDestroyable {
private fetchSource = (): Promise => {
if (this.media.isEncrypted) {
const content = this.event.getContent();
- return decryptFile(content.file, content.info);
+ return decryptFile(content.file!, content.info);
}
return this.media.downloadSource().then((r) => r.blob());
};
- private fetchThumbnail = (): Promise => {
+ private fetchThumbnail = (): Promise => {
if (!this.media.hasThumbnail) return Promise.resolve(null);
if (this.media.isEncrypted) {
@@ -113,7 +113,7 @@ export class MediaEventHelper implements IDestroyable {
const content = event.getContent();
const mediaMsgTypes: string[] = [MsgType.Video, MsgType.Audio, MsgType.Image, MsgType.File];
- if (mediaMsgTypes.includes(content.msgtype)) return true;
+ if (mediaMsgTypes.includes(content.msgtype!)) return true;
if (typeof content.url === "string") return true;
// Finally, it's probably not media
diff --git a/src/utils/WidgetUtils.ts b/src/utils/WidgetUtils.ts
index e8d1dd1e32..3d4dca2fe2 100644
--- a/src/utils/WidgetUtils.ts
+++ b/src/utils/WidgetUtils.ts
@@ -96,7 +96,7 @@ export default class WidgetUtils {
* @param {[type]} testUrlString URL to check
* @return {Boolean} True if specified URL is a scalar URL
*/
- public static isScalarUrl(testUrlString: string): boolean {
+ public static isScalarUrl(testUrlString?: string): boolean {
if (!testUrlString) {
logger.error("Scalar URL check failed. No URL specified");
return false;
@@ -554,7 +554,7 @@ export default class WidgetUtils {
// noinspection JSIgnoredPromiseFromCall
IntegrationManagers.sharedInstance()
.getPrimaryManager()
- .open(room, "type_" + app.type, app.id);
+ ?.open(room, "type_" + app.type, app.id);
}
public static isManagedByManager(app: IApp): boolean {
@@ -563,7 +563,7 @@ export default class WidgetUtils {
if (managers.hasManager()) {
// TODO: Pick the right manager for the widget
const defaultManager = managers.getPrimaryManager();
- return WidgetUtils.isScalarUrl(defaultManager.apiUrl);
+ return WidgetUtils.isScalarUrl(defaultManager?.apiUrl);
}
}
return false;
diff --git a/src/utils/beacon/useBeacon.ts b/src/utils/beacon/useBeacon.ts
index 2726262ec4..f857fc8b66 100644
--- a/src/utils/beacon/useBeacon.ts
+++ b/src/utils/beacon/useBeacon.ts
@@ -29,7 +29,7 @@ export const useBeacon = (beaconInfoEvent: MatrixEvent): Beacon | undefined => {
const beaconIdentifier = getBeaconInfoIdentifier(beaconInfoEvent);
const room = matrixClient.getRoom(roomId);
- const beaconInstance = room.currentState.beacons.get(beaconIdentifier);
+ const beaconInstance = room?.currentState.beacons.get(beaconIdentifier);
// TODO could this be less stupid?
diff --git a/src/utils/direct-messages.ts b/src/utils/direct-messages.ts
index 5e5a5d9c19..aede86f93b 100644
--- a/src/utils/direct-messages.ts
+++ b/src/utils/direct-messages.ts
@@ -173,7 +173,7 @@ export class ThreepidMember extends Member {
export interface IDMUserTileProps {
member: Member;
- onRemove(member: Member): void;
+ onRemove?(member: Member): void;
}
/**
diff --git a/src/utils/dm/createDmLocalRoom.ts b/src/utils/dm/createDmLocalRoom.ts
index ed7a849a33..ac14834303 100644
--- a/src/utils/dm/createDmLocalRoom.ts
+++ b/src/utils/dm/createDmLocalRoom.ts
@@ -92,7 +92,7 @@ export async function createDmLocalRoom(client: MatrixClient, targets: Member[])
type: EventType.RoomMember,
content: {
displayname: target.name,
- avatar_url: target.getMxcAvatarUrl(),
+ avatar_url: target.getMxcAvatarUrl() ?? undefined,
membership: "invite",
isDirect: true,
},
@@ -107,7 +107,7 @@ export async function createDmLocalRoom(client: MatrixClient, targets: Member[])
type: EventType.RoomMember,
content: {
displayname: target.name,
- avatar_url: target.getMxcAvatarUrl(),
+ avatar_url: target.getMxcAvatarUrl() ?? undefined,
membership: "join",
},
state_key: target.userId,
diff --git a/src/utils/leave-behaviour.ts b/src/utils/leave-behaviour.ts
index 11047c5fb7..1031997724 100644
--- a/src/utils/leave-behaviour.ts
+++ b/src/utils/leave-behaviour.ts
@@ -37,7 +37,7 @@ import { bulkSpaceBehaviour } from "./space";
import { SdkContextClass } from "../contexts/SDKContext";
export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = true): Promise {
- let spinnerModal: IHandle;
+ let spinnerModal: IHandle | undefined;
if (spinner) {
spinnerModal = Modal.createDialog(Spinner, undefined, "mx_Dialog_spinner");
}
@@ -60,7 +60,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
room
.getPendingEvents()
.filter((ev) => {
- return [EventStatus.QUEUED, EventStatus.ENCRYPTING, EventStatus.SENDING].includes(ev.status);
+ return [EventStatus.QUEUED, EventStatus.ENCRYPTING, EventStatus.SENDING].includes(ev.status!);
})
.map(
(ev) =>
diff --git a/src/utils/location/parseGeoUri.ts b/src/utils/location/parseGeoUri.ts
index 080ff5359b..0ad4adbad9 100644
--- a/src/utils/location/parseGeoUri.ts
+++ b/src/utils/location/parseGeoUri.ts
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-export const parseGeoUri = (uri: string): GeolocationCoordinates => {
- function parse(s: string): number {
+export const parseGeoUri = (uri: string): GeolocationCoordinates | undefined => {
+ function parse(s: string): number | undefined {
const ret = parseFloat(s);
if (Number.isNaN(ret)) {
return undefined;
@@ -28,7 +28,7 @@ export const parseGeoUri = (uri: string): GeolocationCoordinates => {
if (!m) return;
const parts = m[1].split(";");
const coords = parts[0].split(",");
- let uncertainty: number;
+ let uncertainty: number | undefined;
for (const param of parts.slice(1)) {
const m = param.match(/u=(.*)/);
if (m) uncertainty = parse(m[1]);
diff --git a/src/utils/login.ts b/src/utils/login.ts
index 8e66909952..2688e0e151 100644
--- a/src/utils/login.ts
+++ b/src/utils/login.ts
@@ -23,5 +23,5 @@ export function isLoggedIn(): boolean {
// store to hold this state.
// See also https://github.com/vector-im/element-web/issues/15034.
const app = window.matrixChat;
- return app && (app as MatrixChat).state.view === Views.LOGGED_IN;
+ return (app as MatrixChat)?.state.view === Views.LOGGED_IN;
}
diff --git a/src/utils/pillify.tsx b/src/utils/pillify.tsx
index ff21567b9c..8100b6c453 100644
--- a/src/utils/pillify.tsx
+++ b/src/utils/pillify.tsx
@@ -38,7 +38,7 @@ import { parsePermalink } from "./permalinks/Permalinks";
* The initial caller should pass in an empty array to seed the accumulator.
*/
export function pillifyLinks(nodes: ArrayLike, mxEvent: MatrixEvent, pills: Element[]): void {
- const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
+ const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId()) ?? undefined;
const shouldShowPillAvatar = SettingsStore.getValue("Pill.shouldShowPillAvatar");
let node = nodes[0];
while (node) {
@@ -49,7 +49,7 @@ export function pillifyLinks(nodes: ArrayLike, mxEvent: MatrixEvent, pi
node = node.nextSibling as Element;
continue;
} else if (node.tagName === "A" && node.getAttribute("href")) {
- const href = node.getAttribute("href");
+ const href = node.getAttribute("href")!;
const parts = parsePermalink(href);
// If the link is a (localised) matrix.to link, replace it with a pill
// We don't want to pill event permalinks, so those are ignored.
diff --git a/src/voice-broadcast/stores/VoiceBroadcastPlaybacksStore.ts b/src/voice-broadcast/stores/VoiceBroadcastPlaybacksStore.ts
index e0afea2bc1..d76241b7d1 100644
--- a/src/voice-broadcast/stores/VoiceBroadcastPlaybacksStore.ts
+++ b/src/voice-broadcast/stores/VoiceBroadcastPlaybacksStore.ts
@@ -71,17 +71,17 @@ export class VoiceBroadcastPlaybacksStore
}
public getByInfoEvent(infoEvent: MatrixEvent, client: MatrixClient): VoiceBroadcastPlayback {
- const infoEventId = infoEvent.getId();
+ const infoEventId = infoEvent.getId()!;
if (!this.playbacks.has(infoEventId)) {
this.addPlayback(new VoiceBroadcastPlayback(infoEvent, client, this.recordings));
}
- return this.playbacks.get(infoEventId);
+ return this.playbacks.get(infoEventId)!;
}
private addPlayback(playback: VoiceBroadcastPlayback): void {
- const infoEventId = playback.infoEvent.getId();
+ const infoEventId = playback.infoEvent.getId()!;
if (this.playbacks.has(infoEventId)) return;
diff --git a/test/ContentMessages-test.ts b/test/ContentMessages-test.ts
index 5bfc9c315f..323cb1834b 100644
--- a/test/ContentMessages-test.ts
+++ b/test/ContentMessages-test.ts
@@ -57,7 +57,7 @@ describe("ContentMessages", () => {
uploadContent: jest.fn().mockResolvedValue({ content_uri: "mxc://server/file" }),
} as unknown as MatrixClient;
contentMessages = new ContentMessages();
- prom = Promise.resolve(null);
+ prom = Promise.resolve({ event_id: "$event_id" });
});
describe("sendStickerContentToRoom", () => {
@@ -98,7 +98,7 @@ describe("ContentMessages", () => {
mocked(doMaybeLocalRoomAction).mockImplementation(
(roomId: string, fn: (actualRoomId: string) => Promise) => fn(roomId),
);
- mocked(BlurhashEncoder.instance.getBlurhash).mockResolvedValue(undefined);
+ mocked(BlurhashEncoder.instance.getBlurhash).mockResolvedValue("blurhashstring");
});
it("should use m.image for image files", async () => {
@@ -134,7 +134,7 @@ describe("ContentMessages", () => {
const element = createElement(tagName);
if (tagName === "video") {
(element).load = jest.fn();
- (element).play = () => element.onloadeddata(new Event("loadeddata"));
+ (element).play = () => element.onloadeddata!(new Event("loadeddata"));
(element).pause = jest.fn();
Object.defineProperty(element, "videoHeight", {
get() {
@@ -200,8 +200,8 @@ describe("ContentMessages", () => {
expect(upload.loaded).toBe(0);
expect(upload.total).toBe(file.size);
- const { progressHandler } = mocked(client.uploadContent).mock.calls[0][1];
- progressHandler({ loaded: 123, total: 1234 });
+ const { progressHandler } = mocked(client.uploadContent).mock.calls[0][1]!;
+ progressHandler!({ loaded: 123, total: 1234 });
expect(upload.loaded).toBe(123);
expect(upload.total).toBe(1234);
await prom;
@@ -256,11 +256,11 @@ describe("ContentMessages", () => {
mocked(client.uploadContent).mockReturnValue(deferred.promise);
const file1 = new File([], "file1");
const prom = contentMessages.sendContentToRoom(file1, roomId, undefined, client, undefined);
- const { abortController } = mocked(client.uploadContent).mock.calls[0][1];
- expect(abortController.signal.aborted).toBeFalsy();
+ const { abortController } = mocked(client.uploadContent).mock.calls[0][1]!;
+ expect(abortController!.signal.aborted).toBeFalsy();
const [upload] = contentMessages.getCurrentUploads();
contentMessages.cancelUpload(upload);
- expect(abortController.signal.aborted).toBeTruthy();
+ expect(abortController!.signal.aborted).toBeTruthy();
deferred.resolve({} as UploadResponse);
await prom;
});
@@ -325,7 +325,7 @@ describe("uploadFile", () => {
const file = new Blob([]);
const prom = uploadFile(client, "!roomId:server", file);
- mocked(client.uploadContent).mock.calls[0][1].abortController.abort();
+ mocked(client.uploadContent).mock.calls[0][1]!.abortController!.abort();
deferred.resolve({ content_uri: "mxc://foo/bar" });
await expect(prom).rejects.toThrowError(UploadCanceledError);
});
diff --git a/test/Reply-test.ts b/test/Reply-test.ts
index 4ae7f6fa82..358e34e540 100644
--- a/test/Reply-test.ts
+++ b/test/Reply-test.ts
@@ -134,12 +134,14 @@ But this is not
expect(getNestedReplyText(event, mockPermalinkGenerator)).toMatchSnapshot();
});
- [
- ["m.room.message", MsgType.Location, LocationAssetType.Pin],
- ["m.room.message", MsgType.Location, LocationAssetType.Self],
- [M_BEACON_INFO.name, undefined, LocationAssetType.Pin],
- [M_BEACON_INFO.name, undefined, LocationAssetType.Self],
- ].forEach(([type, msgType, assetType]) => {
+ (
+ [
+ ["m.room.message", MsgType.Location, LocationAssetType.Pin],
+ ["m.room.message", MsgType.Location, LocationAssetType.Self],
+ [M_BEACON_INFO.name, undefined, LocationAssetType.Pin],
+ [M_BEACON_INFO.name, undefined, LocationAssetType.Self],
+ ] as const
+ ).forEach(([type, msgType, assetType]) => {
it(`should create the expected fallback text for ${assetType} ${type}/${msgType}`, () => {
const event = makeTestEvent(type, {
body: "body",
diff --git a/test/Terms-test.tsx b/test/Terms-test.tsx
index e96d4f253d..7d02c3fe66 100644
--- a/test/Terms-test.tsx
+++ b/test/Terms-test.tsx
@@ -49,7 +49,7 @@ describe("Terms", function () {
beforeEach(function () {
jest.clearAllMocks();
- mockClient.getAccountData.mockReturnValue(null);
+ mockClient.getAccountData.mockReturnValue(undefined);
mockClient.getTerms.mockResolvedValue(null);
mockClient.setAccountData.mockResolvedValue({});
});
@@ -59,7 +59,7 @@ describe("Terms", function () {
});
it("should prompt for all terms & services if no account data", async function () {
- mockClient.getAccountData.mockReturnValue(null);
+ mockClient.getAccountData.mockReturnValue(undefined);
mockClient.getTerms.mockResolvedValue({
policies: {
policy_the_first: POLICY_ONE,
diff --git a/test/components/structures/RoomStatusBar-test.tsx b/test/components/structures/RoomStatusBar-test.tsx
index aad8251c2a..a11bd899d3 100644
--- a/test/components/structures/RoomStatusBar-test.tsx
+++ b/test/components/structures/RoomStatusBar-test.tsx
@@ -34,7 +34,7 @@ describe("RoomStatusBar", () => {
stubClient();
client = MatrixClientPeg.get();
- room = new Room(ROOM_ID, client, client.getUserId(), {
+ room = new Room(ROOM_ID, client, client.getUserId()!, {
pendingEventOrdering: PendingEventOrdering.Detached,
});
event = mkEvent({
@@ -72,7 +72,7 @@ describe("RoomStatusBar", () => {
length: 2,
});
rootEvent.status = EventStatus.NOT_SENT;
- room.addPendingEvent(rootEvent, rootEvent.getId());
+ room.addPendingEvent(rootEvent, rootEvent.getId()!);
for (const event of events) {
event.status = EventStatus.NOT_SENT;
room.addPendingEvent(event, Date.now() + Math.random() + "");
diff --git a/test/components/structures/ThreadView-test.tsx b/test/components/structures/ThreadView-test.tsx
index 31ec611557..2993a3b6d6 100644
--- a/test/components/structures/ThreadView-test.tsx
+++ b/test/components/structures/ThreadView-test.tsx
@@ -99,10 +99,10 @@ describe("ThreadView", () => {
"is_falling_back": true,
"m.in_reply_to": {
event_id: rootEvent
- .getThread()
+ .getThread()!
.lastReply((ev: MatrixEvent) => {
return ev.isRelation(THREAD_RELATION_TYPE.name);
- })
+ })!
.getId(),
},
"rel_type": RelationType.Thread,
@@ -126,8 +126,8 @@ describe("ThreadView", () => {
const res = mkThread({
room,
client: mockClient,
- authorId: mockClient.getUserId(),
- participantUserIds: [mockClient.getUserId()],
+ authorId: mockClient.getUserId()!,
+ participantUserIds: [mockClient.getUserId()!],
});
rootEvent = res.rootEvent;
@@ -154,8 +154,8 @@ describe("ThreadView", () => {
const { rootEvent: rootEvent2 } = mkThread({
room,
client: mockClient,
- authorId: mockClient.getUserId(),
- participantUserIds: [mockClient.getUserId()],
+ authorId: mockClient.getUserId()!,
+ participantUserIds: [mockClient.getUserId()!],
});
act(() => {
diff --git a/test/components/views/context_menus/ThreadListContextMenu-test.tsx b/test/components/views/context_menus/ThreadListContextMenu-test.tsx
index 74c74addc5..2f1c5df7f5 100644
--- a/test/components/views/context_menus/ThreadListContextMenu-test.tsx
+++ b/test/components/views/context_menus/ThreadListContextMenu-test.tsx
@@ -54,8 +54,8 @@ describe("ThreadListContextMenu", () => {
const res = mkThread({
room,
client: mockClient,
- authorId: mockClient.getUserId(),
- participantUserIds: [mockClient.getUserId()],
+ authorId: mockClient.getUserId()!,
+ participantUserIds: [mockClient.getUserId()!],
});
event = res.rootEvent;
diff --git a/test/components/views/dialogs/ExportDialog-test.tsx b/test/components/views/dialogs/ExportDialog-test.tsx
index 9e4d0148dc..afc490546f 100644
--- a/test/components/views/dialogs/ExportDialog-test.tsx
+++ b/test/components/views/dialogs/ExportDialog-test.tsx
@@ -109,7 +109,7 @@ describe("", () => {
plainTextExporterInstance.export.mockClear();
// default setting value
- ChatExportMock.getForceChatExportParameters.mockClear().mockReturnValue({});
+ mocked(ChatExportMock.getForceChatExportParameters!).mockClear().mockReturnValue({});
});
it("renders export dialog", () => {
@@ -145,7 +145,7 @@ describe("", () => {
});
it("exports room using values set from ForceRoomExportParameters", async () => {
- ChatExportMock.getForceChatExportParameters.mockReturnValue({
+ mocked(ChatExportMock.getForceChatExportParameters!).mockReturnValue({
format: ExportFormat.PlainText,
range: ExportType.Beginning,
sizeMb: 7000,
@@ -198,7 +198,7 @@ describe("", () => {
});
it("does not render export format when set in ForceRoomExportParameters", () => {
- ChatExportMock.getForceChatExportParameters.mockReturnValue({
+ mocked(ChatExportMock.getForceChatExportParameters!).mockReturnValue({
format: ExportFormat.PlainText,
});
const component = getComponent();
@@ -219,7 +219,7 @@ describe("", () => {
});
it("does not render export type when set in ForceRoomExportParameters", () => {
- ChatExportMock.getForceChatExportParameters.mockReturnValue({
+ mocked(ChatExportMock.getForceChatExportParameters!).mockReturnValue({
range: ExportType.Beginning,
});
const component = getComponent();
@@ -310,7 +310,7 @@ describe("", () => {
});
it("does not render size limit input when set in ForceRoomExportParameters", () => {
- ChatExportMock.getForceChatExportParameters.mockReturnValue({
+ mocked(ChatExportMock.getForceChatExportParameters!).mockReturnValue({
sizeMb: 10000,
});
const component = getComponent();
@@ -321,7 +321,7 @@ describe("", () => {
* 2000mb size limit does not apply when higher limit is configured in config
*/
it("exports when size limit set in ForceRoomExportParameters is larger than 2000", async () => {
- ChatExportMock.getForceChatExportParameters.mockReturnValue({
+ mocked(ChatExportMock.getForceChatExportParameters!).mockReturnValue({
sizeMb: 10000,
});
const component = getComponent();
@@ -344,7 +344,7 @@ describe("", () => {
});
it("does not render input when set in ForceRoomExportParameters", () => {
- ChatExportMock.getForceChatExportParameters.mockReturnValue({
+ mocked(ChatExportMock.getForceChatExportParameters!).mockReturnValue({
includeAttachments: false,
});
const component = getComponent();
diff --git a/test/components/views/settings/DevicesPanel-test.tsx b/test/components/views/settings/DevicesPanel-test.tsx
index 3565e59c43..530bf55a79 100644
--- a/test/components/views/settings/DevicesPanel-test.tsx
+++ b/test/components/views/settings/DevicesPanel-test.tsx
@@ -74,7 +74,7 @@ describe("", () => {
const toggleDeviceSelection = (container: HTMLElement, deviceId: string) =>
act(() => {
- const checkbox = container.querySelector(`#device-tile-checkbox-${deviceId}`);
+ const checkbox = container.querySelector(`#device-tile-checkbox-${deviceId}`)!;
fireEvent.click(checkbox);
});
@@ -204,7 +204,7 @@ describe("", () => {
// close the modal without submission
act(() => {
- const modalCloseButton = document.querySelector('[aria-label="Close dialog"]');
+ const modalCloseButton = document.querySelector('[aria-label="Close dialog"]')!;
fireEvent.click(modalCloseButton);
});
diff --git a/test/components/views/settings/tabs/user/PreferencesUserSettingsTab-test.tsx b/test/components/views/settings/tabs/user/PreferencesUserSettingsTab-test.tsx
index 0e69f1878c..4f7441f59a 100644
--- a/test/components/views/settings/tabs/user/PreferencesUserSettingsTab-test.tsx
+++ b/test/components/views/settings/tabs/user/PreferencesUserSettingsTab-test.tsx
@@ -49,6 +49,7 @@ describe("PreferencesUserSettingsTab", () => {
const client = MatrixClientPeg.get();
jest.spyOn(client, "isVersionSupported").mockImplementation(async (version: string) => {
if (version === "v1.4") return val;
+ return false;
});
};
@@ -61,8 +62,12 @@ describe("PreferencesUserSettingsTab", () => {
};
};
- const expectSetValueToHaveBeenCalled = (name: string, roomId: string, level: SettingLevel, value: boolean) =>
- expect(SettingsStore.setValue).toHaveBeenCalledWith(name, roomId, level, value);
+ const expectSetValueToHaveBeenCalled = (
+ name: string,
+ roomId: string | undefined,
+ level: SettingLevel,
+ value: boolean,
+ ) => expect(SettingsStore.setValue).toHaveBeenCalledWith(name, roomId, level, value);
describe("with server support", () => {
beforeEach(() => {
diff --git a/test/models/Call-test.ts b/test/models/Call-test.ts
index 2f01f06636..028cf12018 100644
--- a/test/models/Call-test.ts
+++ b/test/models/Call-test.ts
@@ -923,7 +923,7 @@ describe("ElementCall", () => {
jest.spyOn(Modal, "createDialog").mockReturnValue({
finished: new Promise((r) => r([sourceId])),
} as IHandle);
- jest.spyOn(PlatformPeg.get(), "supportsDesktopCapturer").mockReturnValue(true);
+ jest.spyOn(PlatformPeg.get()!, "supportsDesktopCapturer").mockReturnValue(true);
await call.connect();
@@ -951,7 +951,7 @@ describe("ElementCall", () => {
jest.spyOn(Modal, "createDialog").mockReturnValue({
finished: new Promise((r) => r([null])),
} as IHandle);
- jest.spyOn(PlatformPeg.get(), "supportsDesktopCapturer").mockReturnValue(true);
+ jest.spyOn(PlatformPeg.get()!, "supportsDesktopCapturer").mockReturnValue(true);
await call.connect();
@@ -976,7 +976,7 @@ describe("ElementCall", () => {
});
it("replies with pending: false if we don't support desktop capturer", async () => {
- jest.spyOn(PlatformPeg.get(), "supportsDesktopCapturer").mockReturnValue(false);
+ jest.spyOn(PlatformPeg.get()!, "supportsDesktopCapturer").mockReturnValue(false);
await call.connect();
diff --git a/test/settings/enums/ImageSize-test.ts b/test/settings/enums/ImageSize-test.ts
index 0eb89a45bb..9103bb7307 100644
--- a/test/settings/enums/ImageSize-test.ts
+++ b/test/settings/enums/ImageSize-test.ts
@@ -31,7 +31,7 @@ describe("ImageSize", () => {
expect(size).toStrictEqual({ w: 800, h: 400 });
});
it("returns max values if content size is not specified", () => {
- const size = suggestedSize(ImageSize.Normal, { w: null, h: null });
+ const size = suggestedSize(ImageSize.Normal, {});
expect(size).toStrictEqual({ w: 324, h: 324 });
});
it("returns integer values", () => {
diff --git a/test/stores/OwnBeaconStore-test.ts b/test/stores/OwnBeaconStore-test.ts
index afe48edd32..79ff78530e 100644
--- a/test/stores/OwnBeaconStore-test.ts
+++ b/test/stores/OwnBeaconStore-test.ts
@@ -102,9 +102,9 @@ describe("OwnBeaconStore", () => {
};
const expireBeaconAndEmit = (store: OwnBeaconStore, beaconInfoEvent: MatrixEvent): void => {
- const beacon = store.getBeaconById(getBeaconInfoIdentifier(beaconInfoEvent));
+ const beacon = store.getBeaconById(getBeaconInfoIdentifier(beaconInfoEvent))!;
// time travel until beacon is expired
- advanceDateAndTime(beacon.beaconInfo.timeout + 100);
+ advanceDateAndTime(beacon.beaconInfo!.timeout + 100);
// force an update on the beacon
// @ts-ignore
@@ -118,13 +118,13 @@ describe("OwnBeaconStore", () => {
beaconInfoEvent: MatrixEvent,
isLive: boolean,
): void => {
- const beacon = store.getBeaconById(getBeaconInfoIdentifier(beaconInfoEvent));
+ const beacon = store.getBeaconById(getBeaconInfoIdentifier(beaconInfoEvent))!;
// matches original state of event content
// except for live property
const updateEvent = makeBeaconInfoEvent(
- beaconInfoEvent.getSender(),
- beaconInfoEvent.getRoomId(),
- { isLive, timeout: beacon.beaconInfo.timeout },
+ beaconInfoEvent.getSender()!,
+ beaconInfoEvent.getRoomId()!,
+ { isLive, timeout: beacon.beaconInfo!.timeout },
"update-event-id",
);
beacon.update(updateEvent);
@@ -236,12 +236,12 @@ describe("OwnBeaconStore", () => {
expect(mockClient.sendEvent).toHaveBeenCalledWith(
room1Id,
M_BEACON.name,
- makeBeaconContent(defaultLocationUri, now, alicesRoom1BeaconInfo.getId()),
+ makeBeaconContent(defaultLocationUri, now, alicesRoom1BeaconInfo.getId()!),
);
expect(mockClient.sendEvent).toHaveBeenCalledWith(
room2Id,
M_BEACON.name,
- makeBeaconContent(defaultLocationUri, now, alicesRoom2BeaconInfo.getId()),
+ makeBeaconContent(defaultLocationUri, now, alicesRoom2BeaconInfo.getId()!),
);
});
});
@@ -263,7 +263,7 @@ describe("OwnBeaconStore", () => {
it("destroys beacons", async () => {
const [room1] = makeRoomsWithStateEvents([alicesRoom1BeaconInfo]);
const store = await makeOwnBeaconStore();
- const beacon = room1.currentState.beacons.get(getBeaconInfoIdentifier(alicesRoom1BeaconInfo));
+ const beacon = room1.currentState.beacons.get(getBeaconInfoIdentifier(alicesRoom1BeaconInfo))!;
const destroySpy = jest.spyOn(beacon, "destroy");
// @ts-ignore
store.onNotReady();
@@ -559,7 +559,7 @@ describe("OwnBeaconStore", () => {
const [room1] = makeRoomsWithStateEvents([alicesRoom1BeaconInfo, alicesRoom2BeaconInfo]);
const store = await makeOwnBeaconStore();
- const room1BeaconInstance = store.beacons.get(getBeaconInfoIdentifier(alicesRoom1BeaconInfo));
+ const room1BeaconInstance = store.beacons.get(getBeaconInfoIdentifier(alicesRoom1BeaconInfo))!;
const beaconDestroySpy = jest.spyOn(room1BeaconInstance, "destroy");
const emitSpy = jest.spyOn(store, "emit");
@@ -610,7 +610,7 @@ describe("OwnBeaconStore", () => {
expect(store.hasLiveBeacons()).toBe(true);
const emitSpy = jest.spyOn(store, "emit");
- const beacon = store.getBeaconById(getBeaconInfoIdentifier(alicesRoom1BeaconInfo));
+ const beacon = store.getBeaconById(getBeaconInfoIdentifier(alicesRoom1BeaconInfo))!;
beacon.destroy();
mockClient.emit(BeaconEvent.Destroy, beacon.identifier);
diff --git a/test/stores/SpaceStore-test.ts b/test/stores/SpaceStore-test.ts
index 1b9ae8da60..907d000a48 100644
--- a/test/stores/SpaceStore-test.ts
+++ b/test/stores/SpaceStore-test.ts
@@ -103,10 +103,11 @@ describe("SpaceStore", () => {
const viewRoom = (roomId: string) => defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: roomId }, true);
const run = async () => {
- mocked(client).getRoom.mockImplementation((roomId) => rooms.find((room) => room.roomId === roomId));
- mocked(client).getRoomUpgradeHistory.mockImplementation((roomId) => [
- rooms.find((room) => room.roomId === roomId),
- ]);
+ mocked(client).getRoom.mockImplementation((roomId) => rooms.find((room) => room.roomId === roomId) || null);
+ mocked(client).getRoomUpgradeHistory.mockImplementation((roomId) => {
+ const room = rooms.find((room) => room.roomId === roomId);
+ return room ? [room] : [];
+ });
await testUtils.setupAsyncStoreWithClient(store, client);
jest.runOnlyPendingTimers();
};
@@ -312,10 +313,12 @@ describe("SpaceStore", () => {
mkSpace(space3, [invite2]);
mkSpace(space4, [room4, fav2, space2, space3]);
- mocked(client).getRoom.mockImplementation((roomId) => rooms.find((room) => room.roomId === roomId));
+ mocked(client).getRoom.mockImplementation(
+ (roomId) => rooms.find((room) => room.roomId === roomId) || null,
+ );
[fav1, fav2, fav3].forEach((roomId) => {
- client.getRoom(roomId).tags = {
+ client.getRoom(roomId)!.tags = {
"m.favourite": {
order: 0.5,
},
@@ -323,20 +326,20 @@ describe("SpaceStore", () => {
});
[invite1, invite2].forEach((roomId) => {
- mocked(client.getRoom(roomId)).getMyMembership.mockReturnValue("invite");
+ mocked(client.getRoom(roomId)!).getMyMembership.mockReturnValue("invite");
});
// have dmPartner1 be in space1 with you
const mySpace1Member = new RoomMember(space1, testUserId);
mySpace1Member.membership = "join";
- (rooms.find((r) => r.roomId === space1).getMembers as jest.Mock).mockReturnValue([
+ (rooms.find((r) => r.roomId === space1)!.getMembers as jest.Mock).mockReturnValue([
mySpace1Member,
dm1Partner,
]);
// have dmPartner2 be in space2 with you
const mySpace2Member = new RoomMember(space2, testUserId);
mySpace2Member.membership = "join";
- (rooms.find((r) => r.roomId === space2).getMembers as jest.Mock).mockReturnValue([
+ (rooms.find((r) => r.roomId === space2)!.getMembers as jest.Mock).mockReturnValue([
mySpace2Member,
dm2Partner,
]);
@@ -349,15 +352,15 @@ describe("SpaceStore", () => {
event: true,
type: EventType.SpaceParent,
room: room2,
- user: client.getUserId(),
+ user: client.getUserId()!,
skey: space2,
content: { via: [], canonical: true },
ts: Date.now(),
}) as MatrixEvent,
]);
- mocked(cliRoom2.currentState).getStateEvents.mockImplementation(room2MockStateEvents);
+ mocked(cliRoom2!.currentState).getStateEvents.mockImplementation(room2MockStateEvents);
const cliSpace2 = client.getRoom(space2);
- mocked(cliSpace2.currentState).maySendStateEvent.mockImplementation(
+ mocked(cliSpace2!.currentState).maySendStateEvent.mockImplementation(
(evType: string, userId: string) => {
if (evType === EventType.SpaceChild) {
return userId === client.getUserId();
@@ -368,13 +371,13 @@ describe("SpaceStore", () => {
// room 3 claims to be a child of space3 but is not due to invalid m.space.parent (permissions)
const cliRoom3 = client.getRoom(room3);
- mocked(cliRoom3.currentState).getStateEvents.mockImplementation(
+ mocked(cliRoom3!.currentState).getStateEvents.mockImplementation(
testUtils.mockStateEventImplementation([
mkEvent({
event: true,
type: EventType.SpaceParent,
room: room3,
- user: client.getUserId(),
+ user: client.getUserId()!,
skey: space3,
content: { via: [], canonical: true },
ts: Date.now(),
@@ -382,7 +385,7 @@ describe("SpaceStore", () => {
]),
);
const cliSpace3 = client.getRoom(space3);
- mocked(cliSpace3.currentState).maySendStateEvent.mockImplementation(
+ mocked(cliSpace3!.currentState).maySendStateEvent.mockImplementation(
(evType: string, userId: string) => {
if (evType === EventType.SpaceChild) {
return false;
@@ -813,7 +816,7 @@ describe("SpaceStore", () => {
content: { membership: "join" },
ts: Date.now(),
});
- const spaceRoom = client.getRoom(spaceId);
+ const spaceRoom = client.getRoom(spaceId)!;
mocked(spaceRoom.currentState).getStateEvents.mockImplementation(
testUtils.mockStateEventImplementation([memberEvent]),
);
@@ -929,7 +932,7 @@ describe("SpaceStore", () => {
it("switch to unknown space is a nop", async () => {
expect(store.activeSpace).toBe(MetaSpace.Home);
- const space = client.getRoom(room1); // not a space
+ const space = client.getRoom(room1)!; // not a space
store.setActiveSpace(space.roomId);
expect(fn).not.toHaveBeenCalledWith(UPDATE_SELECTED_SPACE, space.roomId);
expect(store.activeSpace).toBe(MetaSpace.Home);
@@ -962,6 +965,7 @@ describe("SpaceStore", () => {
member.membership = "join";
return member;
}
+ return null;
});
client.emit(RoomStateEvent.Members, event, space.currentState, dm1Partner);
@@ -1088,7 +1092,7 @@ describe("SpaceStore", () => {
mkSpace(space1, [room1, room2, room3]);
mkSpace(space2, [room1, room2]);
- const cliRoom2 = client.getRoom(room2);
+ const cliRoom2 = client.getRoom(room2)!;
mocked(cliRoom2.currentState).getStateEvents.mockImplementation(
testUtils.mockStateEventImplementation([
mkEvent({
@@ -1267,8 +1271,9 @@ describe("SpaceStore", () => {
case dm1Partner.userId:
return rootSpaceFriend;
}
+ return null;
});
- expect(SpaceStore.instance.getSpaceFilteredUserIds(space1).has(dm1Partner.userId)).toBeFalsy();
+ expect(SpaceStore.instance.getSpaceFilteredUserIds(space1)!.has(dm1Partner.userId)).toBeFalsy();
const memberEvent = mkEvent({
event: true,
type: EventType.RoomMember,
@@ -1281,7 +1286,7 @@ describe("SpaceStore", () => {
});
client.emit(RoomStateEvent.Members, memberEvent, rootSpace.currentState, dm1Partner);
jest.runOnlyPendingTimers();
- expect(SpaceStore.instance.getSpaceFilteredUserIds(space1).has(dm1Partner.userId)).toBeTruthy();
+ expect(SpaceStore.instance.getSpaceFilteredUserIds(space1)!.has(dm1Partner.userId)).toBeTruthy();
const dm1Room = mkRoom(dm1);
dm1Room.getMyMembership.mockReturnValue("join");
client.emit(ClientEvent.Room, dm1Room);
diff --git a/test/stores/room-list/SlidingRoomListStore-test.ts b/test/stores/room-list/SlidingRoomListStore-test.ts
index 3014423349..6d23e16698 100644
--- a/test/stores/room-list/SlidingRoomListStore-test.ts
+++ b/test/stores/room-list/SlidingRoomListStore-test.ts
@@ -198,10 +198,10 @@ describe("SlidingRoomListStore", () => {
return keyToListData[key] || null;
});
- expect(store.getTagsForRoom(new Room(roomA, context.client!, context.client!.getUserId()))).toEqual([
+ expect(store.getTagsForRoom(new Room(roomA, context.client!, context.client!.getUserId()!))).toEqual([
DefaultTagID.Untagged,
]);
- expect(store.getTagsForRoom(new Room(roomB, context.client!, context.client!.getUserId()))).toEqual([
+ expect(store.getTagsForRoom(new Room(roomB, context.client!, context.client!.getUserId()!))).toEqual([
DefaultTagID.Favourite,
DefaultTagID.Untagged,
]);
@@ -221,9 +221,9 @@ describe("SlidingRoomListStore", () => {
0: roomA,
};
const rooms = [
- new Room(roomA, context.client!, context.client!.getUserId()),
- new Room(roomB, context.client!, context.client!.getUserId()),
- new Room(roomC, context.client!, context.client!.getUserId()),
+ new Room(roomA, context.client!, context.client!.getUserId()!),
+ new Room(roomB, context.client!, context.client!.getUserId()!),
+ new Room(roomC, context.client!, context.client!.getUserId()!),
];
mocked(context.client!.getRoom).mockImplementation((roomId: string) => {
switch (roomId) {
@@ -257,9 +257,9 @@ describe("SlidingRoomListStore", () => {
2: roomIdC,
0: roomIdA,
};
- const roomA = new Room(roomIdA, context.client!, context.client!.getUserId());
- const roomB = new Room(roomIdB, context.client!, context.client!.getUserId());
- const roomC = new Room(roomIdC, context.client!, context.client!.getUserId());
+ const roomA = new Room(roomIdA, context.client!, context.client!.getUserId()!);
+ const roomB = new Room(roomIdB, context.client!, context.client!.getUserId()!);
+ const roomC = new Room(roomIdC, context.client!, context.client!.getUserId()!);
mocked(context.client!.getRoom).mockImplementation((roomId: string) => {
switch (roomId) {
case roomIdA:
@@ -321,8 +321,8 @@ describe("SlidingRoomListStore", () => {
const tagId = DefaultTagID.Favourite;
const joinCount = 10;
// seed the store with 2 rooms
- const roomA = new Room(roomIdA, context.client!, context.client!.getUserId());
- const roomC = new Room(roomIdC, context.client!, context.client!.getUserId());
+ const roomA = new Room(roomIdA, context.client!, context.client!.getUserId()!);
+ const roomC = new Room(roomIdC, context.client!, context.client!.getUserId()!);
mocked(context.client!.getRoom).mockImplementation((roomId: string) => {
switch (roomId) {
case roomIdA:
diff --git a/test/stores/room-list/SpaceWatcher-test.ts b/test/stores/room-list/SpaceWatcher-test.ts
index e8d43b66bd..c8a7c4f660 100644
--- a/test/stores/room-list/SpaceWatcher-test.ts
+++ b/test/stores/room-list/SpaceWatcher-test.ts
@@ -29,11 +29,13 @@ import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
import { SpaceFilterCondition } from "../../../src/stores/room-list/filters/SpaceFilterCondition";
import DMRoomMap from "../../../src/utils/DMRoomMap";
-let filter: SpaceFilterCondition = null;
+let filter: SpaceFilterCondition | null = null;
const mockRoomListStore = {
addFilter: (f: SpaceFilterCondition) => (filter = f),
- removeFilter: (): void => (filter = null),
+ removeFilter: (): void => {
+ filter = null;
+ },
} as unknown as RoomListStoreClass;
const getUserIdForRoomId = jest.fn();
@@ -74,7 +76,7 @@ describe("SpaceWatcher", () => {
[MetaSpace.Orphans]: true,
});
- client.getRoom.mockImplementation((roomId) => rooms.find((room) => room.roomId === roomId));
+ client.getRoom.mockImplementation((roomId) => rooms.find((room) => room.roomId === roomId) || null);
await setupAsyncStoreWithClient(store, client);
});
@@ -99,7 +101,7 @@ describe("SpaceWatcher", () => {
await setShowAllRooms(false);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(MetaSpace.Home);
+ expect(filter!["space"]).toBe(MetaSpace.Home);
});
it("sets filter correctly for all -> space transition", async () => {
@@ -109,7 +111,7 @@ describe("SpaceWatcher", () => {
SpaceStore.instance.setActiveSpace(space1);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
});
it("removes filter for home -> all transition", async () => {
@@ -128,7 +130,7 @@ describe("SpaceWatcher", () => {
SpaceStore.instance.setActiveSpace(space1);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
});
it("removes filter for space -> all transition", async () => {
@@ -137,7 +139,7 @@ describe("SpaceWatcher", () => {
SpaceStore.instance.setActiveSpace(space1);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
SpaceStore.instance.setActiveSpace(MetaSpace.Home);
expect(filter).toBeNull();
@@ -149,7 +151,7 @@ describe("SpaceWatcher", () => {
SpaceStore.instance.setActiveSpace(MetaSpace.Favourites);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(MetaSpace.Favourites);
+ expect(filter!["space"]).toBe(MetaSpace.Favourites);
SpaceStore.instance.setActiveSpace(MetaSpace.Home);
expect(filter).toBeNull();
@@ -161,7 +163,7 @@ describe("SpaceWatcher", () => {
SpaceStore.instance.setActiveSpace(MetaSpace.People);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(MetaSpace.People);
+ expect(filter!["space"]).toBe(MetaSpace.People);
SpaceStore.instance.setActiveSpace(MetaSpace.Home);
expect(filter).toBeNull();
@@ -173,7 +175,7 @@ describe("SpaceWatcher", () => {
SpaceStore.instance.setActiveSpace(MetaSpace.Orphans);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(MetaSpace.Orphans);
+ expect(filter!["space"]).toBe(MetaSpace.Orphans);
SpaceStore.instance.setActiveSpace(MetaSpace.Home);
expect(filter).toBeNull();
@@ -185,11 +187,11 @@ describe("SpaceWatcher", () => {
new SpaceWatcher(mockRoomListStore);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
SpaceStore.instance.setActiveSpace(MetaSpace.Home);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(MetaSpace.Home);
+ expect(filter!["space"]).toBe(MetaSpace.Home);
});
it("updates filter correctly for space -> orphans transition", async () => {
@@ -198,11 +200,11 @@ describe("SpaceWatcher", () => {
new SpaceWatcher(mockRoomListStore);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
SpaceStore.instance.setActiveSpace(MetaSpace.Orphans);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(MetaSpace.Orphans);
+ expect(filter!["space"]).toBe(MetaSpace.Orphans);
});
it("updates filter correctly for orphans -> people transition", async () => {
@@ -211,11 +213,11 @@ describe("SpaceWatcher", () => {
new SpaceWatcher(mockRoomListStore);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(MetaSpace.Orphans);
+ expect(filter!["space"]).toBe(MetaSpace.Orphans);
SpaceStore.instance.setActiveSpace(MetaSpace.People);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(MetaSpace.People);
+ expect(filter!["space"]).toBe(MetaSpace.People);
});
it("updates filter correctly for space -> space transition", async () => {
@@ -224,11 +226,11 @@ describe("SpaceWatcher", () => {
new SpaceWatcher(mockRoomListStore);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
SpaceStore.instance.setActiveSpace(space2);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space2);
+ expect(filter!["space"]).toBe(space2);
});
it("doesn't change filter when changing showAllRooms mode to true", async () => {
@@ -237,11 +239,11 @@ describe("SpaceWatcher", () => {
new SpaceWatcher(mockRoomListStore);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
await setShowAllRooms(true);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
});
it("doesn't change filter when changing showAllRooms mode to false", async () => {
@@ -250,10 +252,10 @@ describe("SpaceWatcher", () => {
new SpaceWatcher(mockRoomListStore);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
await setShowAllRooms(false);
expect(filter).toBeInstanceOf(SpaceFilterCondition);
- expect(filter["space"]).toBe(space1);
+ expect(filter!["space"]).toBe(space1);
});
});
diff --git a/test/stores/room-list/filters/VisibilityProvider-test.ts b/test/stores/room-list/filters/VisibilityProvider-test.ts
index e8f2781fec..80296c2bda 100644
--- a/test/stores/room-list/filters/VisibilityProvider-test.ts
+++ b/test/stores/room-list/filters/VisibilityProvider-test.ts
@@ -109,14 +109,14 @@ describe("VisibilityProvider", () => {
});
it("should return false if visibility customisation returns false", () => {
- mocked(RoomListCustomisations.isRoomVisible).mockReturnValue(false);
+ mocked(RoomListCustomisations.isRoomVisible!).mockReturnValue(false);
const room = createRoom();
expect(VisibilityProvider.instance.isRoomVisible(room)).toBe(false);
expect(RoomListCustomisations.isRoomVisible).toHaveBeenCalledWith(room);
});
it("should return true if visibility customisation returns true", () => {
- mocked(RoomListCustomisations.isRoomVisible).mockReturnValue(true);
+ mocked(RoomListCustomisations.isRoomVisible!).mockReturnValue(true);
const room = createRoom();
expect(VisibilityProvider.instance.isRoomVisible(room)).toBe(true);
expect(RoomListCustomisations.isRoomVisible).toHaveBeenCalledWith(room);
diff --git a/test/stores/widgets/StopGapWidget-test.ts b/test/stores/widgets/StopGapWidget-test.ts
index 66b7a25e35..38e9983d49 100644
--- a/test/stores/widgets/StopGapWidget-test.ts
+++ b/test/stores/widgets/StopGapWidget-test.ts
@@ -80,8 +80,8 @@ describe("StopGapWidget", () => {
beforeEach(() => {
voiceBroadcastInfoEvent = mkEvent({
event: true,
- room: client.getRoom("x").roomId,
- user: client.getUserId(),
+ room: client.getRoom("x")?.roomId,
+ user: client.getUserId()!,
type: VoiceBroadcastInfoEventType,
content: {},
});
diff --git a/test/stores/widgets/WidgetPermissionStore-test.ts b/test/stores/widgets/WidgetPermissionStore-test.ts
index aa3af71f79..d9f1cbb804 100644
--- a/test/stores/widgets/WidgetPermissionStore-test.ts
+++ b/test/stores/widgets/WidgetPermissionStore-test.ts
@@ -59,22 +59,22 @@ describe("WidgetPermissionStore", () => {
});
it("should persist OIDCState.Allowed for a widget", () => {
- widgetPermissionStore.setOIDCState(w, WidgetKind.Account, null, OIDCState.Allowed);
+ widgetPermissionStore.setOIDCState(w, WidgetKind.Account, roomId, OIDCState.Allowed);
// check it remembered the value
- expect(widgetPermissionStore.getOIDCState(w, WidgetKind.Account, null)).toEqual(OIDCState.Allowed);
+ expect(widgetPermissionStore.getOIDCState(w, WidgetKind.Account, roomId)).toEqual(OIDCState.Allowed);
});
it("should persist OIDCState.Denied for a widget", () => {
- widgetPermissionStore.setOIDCState(w, WidgetKind.Account, null, OIDCState.Denied);
+ widgetPermissionStore.setOIDCState(w, WidgetKind.Account, roomId, OIDCState.Denied);
// check it remembered the value
- expect(widgetPermissionStore.getOIDCState(w, WidgetKind.Account, null)).toEqual(OIDCState.Denied);
+ expect(widgetPermissionStore.getOIDCState(w, WidgetKind.Account, roomId)).toEqual(OIDCState.Denied);
});
it("should update OIDCState for a widget", () => {
- widgetPermissionStore.setOIDCState(w, WidgetKind.Account, null, OIDCState.Allowed);
- widgetPermissionStore.setOIDCState(w, WidgetKind.Account, null, OIDCState.Denied);
+ widgetPermissionStore.setOIDCState(w, WidgetKind.Account, roomId, OIDCState.Allowed);
+ widgetPermissionStore.setOIDCState(w, WidgetKind.Account, roomId, OIDCState.Denied);
// check it remembered the latest value
- expect(widgetPermissionStore.getOIDCState(w, WidgetKind.Account, null)).toEqual(OIDCState.Denied);
+ expect(widgetPermissionStore.getOIDCState(w, WidgetKind.Account, roomId)).toEqual(OIDCState.Denied);
});
it("should scope the location for a widget when setting OIDC state", () => {
diff --git a/test/test-utils/beacon.ts b/test/test-utils/beacon.ts
index 0a388336a7..18ef73bdae 100644
--- a/test/test-utils/beacon.ts
+++ b/test/test-utils/beacon.ts
@@ -197,7 +197,7 @@ export const makeRoomWithBeacons = (
locationEvents?: MatrixEvent[],
): Beacon[] => {
const room = makeRoomWithStateEvents(beaconInfoEvents, { roomId, mockClient });
- const beacons = beaconInfoEvents.map((event) => room.currentState.beacons.get(getBeaconInfoIdentifier(event)));
+ const beacons = beaconInfoEvents.map((event) => room.currentState.beacons.get(getBeaconInfoIdentifier(event))!);
if (locationEvents) {
beacons.forEach((beacon) => {
// this filtering happens in roomState, which is bypassed here
diff --git a/test/test-utils/composer.ts b/test/test-utils/composer.ts
index 80cc9f0470..85227acbc1 100644
--- a/test/test-utils/composer.ts
+++ b/test/test-utils/composer.ts
@@ -31,7 +31,7 @@ export const addTextToComposer = (container: HTMLElement, text: string) =>
getData: (type: string) => (type === "text/plain" ? text : undefined),
} as unknown as DataTransfer,
};
- fireEvent.paste(container.querySelector('[role="textbox"]'), pasteEvent);
+ fireEvent.paste(container.querySelector('[role="textbox"]')!, pasteEvent);
});
export const addTextToComposerEnzyme = (wrapper: ReactWrapper, text: string) =>
diff --git a/test/test-utils/utilities.ts b/test/test-utils/utilities.ts
index e2acc904e3..a03e10b83e 100644
--- a/test/test-utils/utilities.ts
+++ b/test/test-utils/utilities.ts
@@ -37,7 +37,7 @@ export function untilDispatch(
dispatcher = defaultDispatcher,
timeout = 1000,
): Promise {
- const callerLine = new Error().stack.toString().split("\n")[2];
+ const callerLine = new Error().stack!.toString().split("\n")[2];
if (typeof waitForAction === "string") {
const action = waitForAction;
waitForAction = (payload) => {
@@ -89,10 +89,10 @@ export function untilDispatch(
export function untilEmission(
emitter: EventEmitter,
eventName: string,
- check: (...args: any[]) => boolean = undefined,
+ check?: (...args: any[]) => boolean,
timeout = 1000,
): Promise {
- const callerLine = new Error().stack.toString().split("\n")[2];
+ const callerLine = new Error().stack!.toString().split("\n")[2];
return new Promise((resolve, reject) => {
let fulfilled = false;
let timeoutId: number;
diff --git a/test/theme-test.ts b/test/theme-test.ts
index 0298cd48c8..d1dc5f68cc 100644
--- a/test/theme-test.ts
+++ b/test/theme-test.ts
@@ -58,7 +58,7 @@ describe("theme", () => {
// When
await new Promise((resolve) => {
setTheme("light").then(resolve);
- lightTheme.onload(void 0);
+ lightTheme.onload!({} as Event);
});
// Then
@@ -72,7 +72,7 @@ describe("theme", () => {
return expect(
new Promise((resolve) => {
setTheme("light").catch((e) => resolve(e));
- lightTheme.onerror("call onerror");
+ lightTheme.onerror!("call onerror");
}),
).resolves.toBe("call onerror");
});
diff --git a/test/useTopic-test.tsx b/test/useTopic-test.tsx
index 5cab29e9b6..2f7e0ac757 100644
--- a/test/useTopic-test.tsx
+++ b/test/useTopic-test.tsx
@@ -42,7 +42,7 @@ describe("useTopic", () => {
function RoomTopic() {
const topic = useTopic(room);
- return {topic.text}
;
+ return {topic!.text}
;
}
render();
diff --git a/test/utils/MegolmExportEncryption-test.ts b/test/utils/MegolmExportEncryption-test.ts
index 4e22c7aec4..69d803073f 100644
--- a/test/utils/MegolmExportEncryption-test.ts
+++ b/test/utils/MegolmExportEncryption-test.ts
@@ -85,10 +85,6 @@ describe("MegolmExportEncryption", function () {
MegolmExportEncryption = require("../../src/utils/MegolmExportEncryption");
});
- afterAll(() => {
- window.crypto = undefined;
- });
-
describe("decrypt", function () {
it("should handle missing header", function () {
const input = stringToArray(`-----`);
diff --git a/test/utils/beacon/geolocation-test.ts b/test/utils/beacon/geolocation-test.ts
index 0f9aba483f..c3407a01f5 100644
--- a/test/utils/beacon/geolocation-test.ts
+++ b/test/utils/beacon/geolocation-test.ts
@@ -62,8 +62,6 @@ describe("geolocation utilities", () => {
const pos: GenericPosition = {
latitude: 43.2,
longitude: 12.4,
- altitude: null,
- accuracy: null,
timestamp: 12334,
};
diff --git a/test/utils/export-test.tsx b/test/utils/export-test.tsx
index 95d4799d31..a75af856db 100644
--- a/test/utils/export-test.tsx
+++ b/test/utils/export-test.tsx
@@ -45,6 +45,8 @@ interface ITestContent extends IContent {
}
describe("export", function () {
+ const setProgressText = jest.fn();
+
let mockExportOptions: IExportOptions;
let mockRoom: Room;
let ts0: number;
@@ -63,7 +65,7 @@ describe("export", function () {
};
function createRoom() {
- const room = new Room(generateRoomId(), null, client.getUserId());
+ const room = new Room(generateRoomId(), client, client.getUserId()!);
return room;
}
mockRoom = createRoom();
@@ -146,7 +148,7 @@ describe("export", function () {
}
function mkEvents() {
- const matrixEvents = [];
+ const matrixEvents: MatrixEvent[] = [];
let i: number;
// plain text
for (i = 0; i < 10; i++) {
@@ -237,7 +239,7 @@ describe("export", function () {
});
it("checks if the icons' html corresponds to export regex", function () {
- const exporter = new HTMLExporter(mockRoom, ExportType.Beginning, mockExportOptions, null);
+ const exporter = new HTMLExporter(mockRoom, ExportType.Beginning, mockExportOptions, setProgressText);
const fileRegex = /.*?<\/span>/;
expect(fileRegex.test(renderToString(exporter.getEventTile(mkFileEvent(), true)))).toBeTruthy();
});
@@ -251,7 +253,7 @@ describe("export", function () {
maxSize: 100 * 1024 * 1024,
attachmentsIncluded: true,
},
- null,
+ setProgressText,
);
const imageRegex = //;
expect(imageRegex.test(renderToString(exporter.getEventTile(mkImageEvent(), true)))).toBeTruthy();
@@ -284,13 +286,13 @@ describe("export", function () {
],
];
it.each(invalidExportOptions)("%s", (_d, options) => {
- expect(() => new PlainTextExporter(mockRoom, ExportType.Beginning, options, null)).toThrowError(
+ expect(() => new PlainTextExporter(mockRoom, ExportType.Beginning, options, setProgressText)).toThrowError(
"Invalid export options",
);
});
it("tests the file extension splitter", function () {
- const exporter = new PlainTextExporter(mockRoom, ExportType.Beginning, mockExportOptions, null);
+ const exporter = new PlainTextExporter(mockRoom, ExportType.Beginning, mockExportOptions, setProgressText);
const fileNameWithExtensions: Record = {
"": ["", ""],
"name": ["name", ""],
@@ -327,14 +329,14 @@ describe("export", function () {
expectedText: '<@me:here "This"> Reply',
},
];
- const exporter = new PlainTextExporter(mockRoom, ExportType.Beginning, mockExportOptions, null);
+ const exporter = new PlainTextExporter(mockRoom, ExportType.Beginning, mockExportOptions, setProgressText);
for (const content of eventContents) {
expect(exporter.textForReplyEvent(content)).toBe(content.expectedText);
}
});
it("checks if the render to string doesn't throw any error for different types of events", function () {
- const exporter = new HTMLExporter(mockRoom, ExportType.Beginning, mockExportOptions, null);
+ const exporter = new HTMLExporter(mockRoom, ExportType.Beginning, mockExportOptions, setProgressText);
for (const event of events) {
expect(renderToString(exporter.getEventTile(event, false))).toBeTruthy();
}
diff --git a/test/voice-broadcast/audio/VoiceBroadcastRecorder-test.ts b/test/voice-broadcast/audio/VoiceBroadcastRecorder-test.ts
index b2a0e7da50..7d47918b1f 100644
--- a/test/voice-broadcast/audio/VoiceBroadcastRecorder-test.ts
+++ b/test/voice-broadcast/audio/VoiceBroadcastRecorder-test.ts
@@ -83,15 +83,15 @@ describe("VoiceBroadcastRecorder", () => {
const simulateFirstChunk = (): void => {
// send headers in wrong order and multiple times to test robustness for that
- voiceRecording.onDataAvailable(headers2);
- voiceRecording.onDataAvailable(headers1);
- voiceRecording.onDataAvailable(headers1);
- voiceRecording.onDataAvailable(headers2);
+ voiceRecording.onDataAvailable!(headers2);
+ voiceRecording.onDataAvailable!(headers1);
+ voiceRecording.onDataAvailable!(headers1);
+ voiceRecording.onDataAvailable!(headers2);
// set recorder seconds to something greater than the test chunk length of 30
// @ts-ignore
voiceRecording.recorderSeconds = 42;
- voiceRecording.onDataAvailable(chunk1);
- voiceRecording.onDataAvailable(headers1);
+ voiceRecording.onDataAvailable!(chunk1);
+ voiceRecording.onDataAvailable!(headers1);
};
const expectOnFirstChunkRecorded = (): void => {
@@ -164,7 +164,7 @@ describe("VoiceBroadcastRecorder", () => {
describe("when the first header from recorder has been received", () => {
beforeEach(() => {
- voiceRecording.onDataAvailable(headers1);
+ voiceRecording.onDataAvailable!(headers1);
});
itShouldNotEmitAChunkRecordedEvent();
@@ -172,8 +172,8 @@ describe("VoiceBroadcastRecorder", () => {
describe("when the second header from recorder has been received", () => {
beforeEach(() => {
- voiceRecording.onDataAvailable(headers1);
- voiceRecording.onDataAvailable(headers2);
+ voiceRecording.onDataAvailable!(headers1);
+ voiceRecording.onDataAvailable!(headers2);
});
itShouldNotEmitAChunkRecordedEvent();
@@ -181,9 +181,9 @@ describe("VoiceBroadcastRecorder", () => {
describe("when a third page from recorder has been received", () => {
beforeEach(() => {
- voiceRecording.onDataAvailable(headers1);
- voiceRecording.onDataAvailable(headers2);
- voiceRecording.onDataAvailable(chunk1);
+ voiceRecording.onDataAvailable!(headers1);
+ voiceRecording.onDataAvailable!(headers2);
+ voiceRecording.onDataAvailable!(chunk1);
});
itShouldNotEmitAChunkRecordedEvent();
@@ -235,15 +235,15 @@ describe("VoiceBroadcastRecorder", () => {
simulateFirstChunk();
// simulate a second chunk
- voiceRecording.onDataAvailable(chunk2a);
+ voiceRecording.onDataAvailable!(chunk2a);
// send headers again to test robustness for that
- voiceRecording.onDataAvailable(headers2);
+ voiceRecording.onDataAvailable!(headers2);
// add another 30 seconds for the next chunk
// @ts-ignore
voiceRecording.recorderSeconds = 72;
- voiceRecording.onDataAvailable(chunk2b);
+ voiceRecording.onDataAvailable!(chunk2b);
});
it("should emit ChunkRecorded events", () => {