diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx
index 89e9d76629..32ef26aaf0 100644
--- a/src/HtmlUtils.tsx
+++ b/src/HtmlUtils.tsx
@@ -466,7 +466,7 @@ const emojiToJsxSpan = (emoji: string, key: number): JSX.Element => (
*/
export function formatEmojis(message: string | undefined, isHtmlMessage?: false): JSX.Element[];
export function formatEmojis(message: string | undefined, isHtmlMessage: true): string[];
-export function formatEmojis(message: string | undefined, isHtmlMessage: boolean): (JSX.Element | string)[] {
+export function formatEmojis(message: string | undefined, isHtmlMessage?: boolean): (JSX.Element | string)[] {
const emojiToSpan = isHtmlMessage ? emojiToHtmlSpan : emojiToJsxSpan;
const result: (JSX.Element | string)[] = [];
if (!message) return result;
diff --git a/src/ScalarMessaging.ts b/src/ScalarMessaging.ts
index b3a0c5640b..e500c34828 100644
--- a/src/ScalarMessaging.ts
+++ b/src/ScalarMessaging.ts
@@ -626,7 +626,7 @@ async function setBotPower(
success: true,
});
} catch (err) {
- sendError(event, err.message ? err.message : _t("Failed to send request."), err);
+ sendError(event, err instanceof Error ? err.message : _t("Failed to send request."), err);
}
}
diff --git a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx
index d07c86daa1..c188319b3a 100644
--- a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx
+++ b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx
@@ -42,7 +42,7 @@ interface IState {
passPhraseConfirm: string;
copied: boolean;
downloaded: boolean;
- error?: string;
+ error?: boolean;
}
/*
@@ -94,7 +94,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
this.setState({
rejecting: false,
- rejectError: error,
});
},
);
@@ -1714,7 +1712,6 @@ export class RoomView extends React.Component {
this.setState({
rejecting: false,
- rejectError: error,
});
}
};
diff --git a/src/components/structures/ScrollPanel.tsx b/src/components/structures/ScrollPanel.tsx
index 63022d80c3..0dc31665d2 100644
--- a/src/components/structures/ScrollPanel.tsx
+++ b/src/components/structures/ScrollPanel.tsx
@@ -491,7 +491,7 @@ export default class ScrollPanel extends React.Component {
// This would cause jumping to happen on Chrome/macOS.
return new Promise((resolve) => window.setTimeout(resolve, 1))
.then(() => {
- return this.props.onFillRequest(backwards);
+ return this.props.onFillRequest?.(backwards);
})
.finally(() => {
this.pendingFillRequests[dir] = false;
diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx
index fc9b29d69f..47e53f18ae 100644
--- a/src/components/structures/TimelinePanel.tsx
+++ b/src/components/structures/TimelinePanel.tsx
@@ -1623,12 +1623,12 @@ class TimelinePanel extends React.Component {
// dialog, let's jump to the end of the timeline. If we weren't,
// something has gone badly wrong and rather than causing a loop of
// undismissable dialogs, let's just give up.
- if (eventId) {
+ if (eventId && this.props.timelineSet.room) {
onFinished = () => {
// go via the dispatcher so that the URL is updated
dis.dispatch({
action: Action.ViewRoom,
- room_id: this.props.timelineSet.room.roomId,
+ room_id: this.props.timelineSet.room!.roomId,
metricsTrigger: undefined, // room doesn't change
});
};
@@ -2098,7 +2098,7 @@ class TimelinePanel extends React.Component {
// forwards, otherwise if somebody hits the bottom of the loaded
// events when viewing historical messages, we get stuck in a loop
// of paginating our way through the entire history of the room.
- const stickyBottom = !this.timelineWindow.canPaginate(EventTimeline.FORWARDS);
+ const stickyBottom = !this.timelineWindow?.canPaginate(EventTimeline.FORWARDS);
// If the state is PREPARED or CATCHUP, we're still waiting for the js-sdk to sync with
// the HS and fetch the latest events, so we are effectively forward paginating.
diff --git a/src/components/structures/UserView.tsx b/src/components/structures/UserView.tsx
index e9a05880f6..84e5552e60 100644
--- a/src/components/structures/UserView.tsx
+++ b/src/components/structures/UserView.tsx
@@ -75,7 +75,7 @@ export default class UserView extends React.Component {
} catch (err) {
Modal.createDialog(ErrorDialog, {
title: _t("Could not load user profile"),
- description: err && err.message ? err.message : _t("Operation failed"),
+ description: err instanceof Error ? err.message : _t("Operation failed"),
});
this.setState({ loading: false });
return;
diff --git a/src/components/views/context_menus/WidgetContextMenu.tsx b/src/components/views/context_menus/WidgetContextMenu.tsx
index 8dc6ca62eb..6482b81773 100644
--- a/src/components/views/context_menus/WidgetContextMenu.tsx
+++ b/src/components/views/context_menus/WidgetContextMenu.tsx
@@ -71,7 +71,7 @@ export const WidgetContextMenu: React.FC = ({
} catch (err) {
logger.error("Failed to start livestream", err);
// XXX: won't i18n well, but looks like widget api only support 'message'?
- const message = err.message || _t("Unable to start audio streaming.");
+ const message = err instanceof Error ? err.message : _t("Unable to start audio streaming.");
Modal.createDialog(ErrorDialog, {
title: _t("Failed to start livestream"),
description: message,
diff --git a/src/components/views/dialogs/BugReportDialog.tsx b/src/components/views/dialogs/BugReportDialog.tsx
index ed706f97c5..6bf30b2914 100644
--- a/src/components/views/dialogs/BugReportDialog.tsx
+++ b/src/components/views/dialogs/BugReportDialog.tsx
@@ -160,7 +160,7 @@ export default class BugReportDialog extends React.Component {
if (!this.unmounted) {
this.setState({
downloadBusy: false,
- downloadProgress: _t("Failed to send logs: ") + `${err.message}`,
+ downloadProgress: _t("Failed to send logs: ") + `${err instanceof Error ? err.message : ""}`,
});
}
}
diff --git a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx
index 9989dc5434..40395b9787 100644
--- a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx
+++ b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx
@@ -16,6 +16,7 @@ limitations under the License.
import React from "react";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
+import { HTTPError, MatrixError } from "matrix-js-sdk/src/matrix";
import { _t } from "../../../languageHandler";
import ConfirmRedactDialog from "./ConfirmRedactDialog";
@@ -62,7 +63,13 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent {
this.openRequest();
await request.accept();
} catch (err) {
- logger.error(err.message);
+ logger.error(err);
}
}
};
@@ -86,7 +86,7 @@ export default class MKeyVerificationRequest extends React.Component {
try {
await request.cancel();
} catch (err) {
- logger.error(err.message);
+ logger.error(err);
}
}
};
diff --git a/src/components/views/room_settings/UrlPreviewSettings.tsx b/src/components/views/room_settings/UrlPreviewSettings.tsx
index 15d70132e2..35e0a37061 100644
--- a/src/components/views/room_settings/UrlPreviewSettings.tsx
+++ b/src/components/views/room_settings/UrlPreviewSettings.tsx
@@ -28,14 +28,14 @@ import { Action } from "../../../dispatcher/actions";
import { SettingLevel } from "../../../settings/SettingLevel";
import SettingsFlag from "../elements/SettingsFlag";
import SettingsFieldset from "../settings/SettingsFieldset";
-import AccessibleButton from "../elements/AccessibleButton";
+import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
interface IProps {
room: Room;
}
export default class UrlPreviewSettings extends React.Component {
- private onClickUserSettings = (e: React.MouseEvent): void => {
+ private onClickUserSettings = (e: ButtonEvent): void => {
e.preventDefault();
e.stopPropagation();
dis.fire(Action.ViewUserSettings);
diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx
index 7bf01fa3af..1dc6e5f9d8 100644
--- a/src/components/views/rooms/BasicMessageComposer.tsx
+++ b/src/components/views/rooms/BasicMessageComposer.tsx
@@ -132,7 +132,7 @@ export default class BasicMessageEditor extends React.Component
private hasTextSelected = false;
private _isCaretAtEnd = false;
- private lastCaret: DocumentOffset;
+ private lastCaret!: DocumentOffset;
private lastSelection: ReturnType | null = null;
private readonly useMarkdownHandle: string;
diff --git a/src/components/views/settings/ProfileSettings.tsx b/src/components/views/settings/ProfileSettings.tsx
index f277872c86..986501b54e 100644
--- a/src/components/views/settings/ProfileSettings.tsx
+++ b/src/components/views/settings/ProfileSettings.tsx
@@ -124,7 +124,7 @@ export default class ProfileSettings extends React.Component<{}, IState> {
logger.log("Failed to save profile", err);
Modal.createDialog(ErrorDialog, {
title: _t("Failed to save your profile"),
- description: err && err.message ? err.message : _t("The operation could not be completed"),
+ description: err instanceof Error ? err.message : _t("The operation could not be completed"),
});
}
diff --git a/test/settings/handlers/DeviceSettingsHandler-test.ts b/test/settings/handlers/DeviceSettingsHandler-test.ts
index ad9eec99e7..ec3bce41f8 100644
--- a/test/settings/handlers/DeviceSettingsHandler-test.ts
+++ b/test/settings/handlers/DeviceSettingsHandler-test.ts
@@ -66,7 +66,7 @@ describe("DeviceSettingsHandler", () => {
afterEach(() => {
MatrixClientPeg.get = () => null;
- MatrixClientPeg.safeGet = () => null;
+ MatrixClientPeg.safeGet = () => new MatrixClient({ baseUrl: "foobar" });
});
it("Returns the value for a disabled feature", () => {
diff --git a/test/stores/room-list/MessagePreviewStore-test.ts b/test/stores/room-list/MessagePreviewStore-test.ts
index 4cefedef95..fb6207ed52 100644
--- a/test/stores/room-list/MessagePreviewStore-test.ts
+++ b/test/stores/room-list/MessagePreviewStore-test.ts
@@ -208,8 +208,8 @@ describe("MessagePreviewStore", () => {
const preview = await store.getPreviewForRoom(room, DefaultTagID.Untagged);
expect(preview).toBeDefined();
- expect(preview.isThreadReply).toBe(false);
- expect(preview.text).toMatchInlineSnapshot(`"@sender:server reacted 🙃 to First message"`);
+ expect(preview?.isThreadReply).toBe(false);
+ expect(preview?.text).toMatchInlineSnapshot(`"@sender:server reacted 🙃 to First message"`);
});
it("should generate the correct preview for a reaction on a thread root", async () => {
@@ -227,7 +227,7 @@ describe("MessagePreviewStore", () => {
const preview = await store.getPreviewForRoom(room, DefaultTagID.Untagged);
expect(preview).toBeDefined();
- expect(preview.isThreadReply).toBe(false);
- expect(preview.text).toContain("You reacted 🙃 to root event message");
+ expect(preview?.isThreadReply).toBe(false);
+ expect(preview?.text).toContain("You reacted 🙃 to root event message");
});
});