From c290e7e37511e4167544c414e2b928f74e439628 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Aug 2024 09:30:19 +0100 Subject: [PATCH 01/42] Upgrade target to es2021 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../plugins/homeserver/dendrite/index.ts | 1 - playwright/tsconfig.json | 4 +- src/@types/global.d.ts | 57 +------------------ src/utils/MegolmExportEncryption.ts | 2 +- tsconfig.json | 2 +- 5 files changed, 5 insertions(+), 61 deletions(-) diff --git a/playwright/plugins/homeserver/dendrite/index.ts b/playwright/plugins/homeserver/dendrite/index.ts index 603bd360a8c..0ddaecc1b7d 100644 --- a/playwright/plugins/homeserver/dendrite/index.ts +++ b/playwright/plugins/homeserver/dendrite/index.ts @@ -29,7 +29,6 @@ const dendriteConfigFile = "dendrite.yaml"; // Surprisingly, Dendrite implements the same register user Admin API Synapse, so we can just extend it export class Dendrite extends Synapse implements Homeserver, HomeserverInstance { - public config: HomeserverConfig & { serverId: string }; protected image = "matrixdotorg/dendrite-monolith:main"; protected entrypoint = "/usr/bin/dendrite"; diff --git a/playwright/tsconfig.json b/playwright/tsconfig.json index 48ff1f8c02e..5f3083fd57b 100644 --- a/playwright/tsconfig.json +++ b/playwright/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { - "target": "es2018", + "target": "es2022", "jsx": "react", - "lib": ["ESNext", "es2021", "dom", "dom.iterable"], + "lib": ["ESNext", "es2022", "dom", "dom.iterable"], "resolveJsonModule": true, "esModuleInterop": true, "moduleResolution": "node", diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index e42e83d58db..fab9791ada1 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -144,69 +144,14 @@ declare global { usageDetails?: { [key: string]: number }; } - // https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas - interface OffscreenCanvas { - convertToBlob(opts?: { type?: string; quality?: number }): Promise; - } - - interface HTMLAudioElement { - type?: string; - } - - interface HTMLVideoElement { - type?: string; - } - - // Add Chrome-specific `instant` ScrollBehaviour - type _ScrollBehavior = ScrollBehavior | "instant"; - - interface _ScrollOptions { - behavior?: _ScrollBehavior; - } - - interface _ScrollIntoViewOptions extends _ScrollOptions { - block?: ScrollLogicalPosition; - inline?: ScrollLogicalPosition; - } - interface Element { // Safari & IE11 only have this prefixed: we used prefixed versions // previously so let's continue to support them for now webkitRequestFullScreen(options?: FullscreenOptions): Promise; msRequestFullscreen(options?: FullscreenOptions): Promise; - scrollIntoView(arg?: boolean | _ScrollIntoViewOptions): void; - } - - interface Error { - // Standard - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause - cause?: unknown; - - // Non-standard - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/fileName - fileName?: string; - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/lineNumber - lineNumber?: number; - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/columnNumber - columnNumber?: number; - } - - // We can remove these pieces if we ever update to `target: "es2022"` in our - // TypeScript config which supports the new `cause` property, see - // https://github.com/vector-im/element-web/issues/24913 - interface ErrorOptions { - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause - cause?: unknown; - } - - interface ErrorConstructor { - new (message?: string, options?: ErrorOptions): Error; - (message?: string, options?: ErrorOptions): Error; + // scrollIntoView(arg?: boolean | _ScrollIntoViewOptions): void; } - // eslint-disable-next-line no-var - var Error: ErrorConstructor; - // https://github.com/microsoft/TypeScript/issues/28308#issuecomment-650802278 interface AudioWorkletProcessor { readonly port: MessagePort; diff --git a/src/utils/MegolmExportEncryption.ts b/src/utils/MegolmExportEncryption.ts index de6ffea5f1c..fc0958c1795 100644 --- a/src/utils/MegolmExportEncryption.ts +++ b/src/utils/MegolmExportEncryption.ts @@ -20,7 +20,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../languageHandler"; import SdkConfig from "../SdkConfig"; -const subtleCrypto = window.crypto.subtle || window.crypto.webkitSubtle; +const subtleCrypto = window.crypto.subtle; /** * Make an Error object which has a friendlyText property which is already diff --git a/tsconfig.json b/tsconfig.json index 3118f598c4c..788ee414cb9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "esModuleInterop": true, "module": "es2022", "moduleResolution": "node", - "target": "es2018", + "target": "es2021", "noUnusedLocals": true, "sourceMap": false, "outDir": "./lib", From 1bb780348a46abaf9f59c9b01a6ddf4db1695aab Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Aug 2024 09:30:21 +0100 Subject: [PATCH 02/42] Upgrade target to es2021 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- tsconfig.json | 2 +- tsconfig.module_system.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 902b3469b6f..f7ace546ebe 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "esModuleInterop": true, "module": "es2022", "moduleResolution": "node", - "target": "es2018", + "target": "es2021", "noUnusedLocals": true, "sourceMap": false, "outDir": "./lib", diff --git a/tsconfig.module_system.json b/tsconfig.module_system.json index df928f828eb..dec7ca9e50e 100644 --- a/tsconfig.module_system.json +++ b/tsconfig.module_system.json @@ -4,7 +4,7 @@ "jsx": "preserve", "declaration": false, "outDir": "./lib/module_system", - "lib": ["es2020"], + "lib": ["es2022"], "types": ["node"] }, "include": ["./module_system/**/*.ts"] From 6d870298076e622f0238a926708b031e43f4d056 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Aug 2024 09:50:42 +0100 Subject: [PATCH 03/42] Upgrade to es2022 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- babel.config.js | 3 ++- src/components/structures/MessagePanel.tsx | 2 +- src/components/structures/RightPanel.tsx | 2 +- src/components/structures/RoomView.tsx | 2 +- src/components/structures/SpaceRoomView.tsx | 2 +- src/components/structures/ThreadView.tsx | 2 +- src/components/structures/TimelinePanel.tsx | 3 +-- src/components/structures/UserMenu.tsx | 3 +-- src/components/structures/UserView.tsx | 2 +- src/components/structures/auth/SoftLogout.tsx | 4 +--- .../context_menus/MessageContextMenu.tsx | 2 +- src/components/views/elements/AppTile.tsx | 3 +-- .../views/elements/EventListSummary.tsx | 2 +- .../views/elements/PersistentApp.tsx | 2 +- src/components/views/elements/ReplyChain.tsx | 2 +- .../views/elements/RoomAliasField.tsx | 2 +- .../views/emojipicker/ReactionPicker.tsx | 2 +- src/components/views/emojipicker/Search.tsx | 2 +- .../views/location/LocationPicker.tsx | 2 +- .../views/messages/EditHistoryMessage.tsx | 3 +-- src/components/views/messages/MAudioBody.tsx | 2 +- src/components/views/messages/MFileBody.tsx | 2 +- src/components/views/messages/MImageBody.tsx | 2 +- .../views/messages/MLocationBody.tsx | 2 +- src/components/views/messages/MPollBody.tsx | 2 +- src/components/views/messages/MVideoBody.tsx | 2 +- .../views/messages/MessageEvent.tsx | 2 +- .../views/messages/ReactionsRow.tsx | 3 +-- .../views/messages/ReactionsRowButton.tsx | 2 +- .../messages/ReactionsRowButtonTooltip.tsx | 2 +- src/components/views/messages/TextualBody.tsx | 2 +- .../views/room_settings/AliasSettings.tsx | 2 +- .../views/rooms/EditMessageComposer.tsx | 3 +-- src/components/views/rooms/EventTile.tsx | 2 +- .../views/rooms/LegacyRoomHeader.tsx | 2 +- src/components/views/rooms/MemberList.tsx | 2 +- .../views/rooms/MessageComposer.tsx | 2 +- .../views/rooms/MessageComposerButtons.tsx | 2 +- .../views/rooms/PinnedEventTile.tsx | 2 +- src/components/views/rooms/RoomList.tsx | 2 +- .../views/rooms/RoomUpgradeWarningBar.tsx | 2 +- .../views/rooms/SearchResultTile.tsx | 2 +- .../views/rooms/SendMessageComposer.tsx | 3 +-- .../views/rooms/VoiceRecordComposerTile.tsx | 2 +- .../settings/tabs/room/BridgeSettingsTab.tsx | 2 +- .../tabs/room/GeneralRoomSettingsTab.tsx | 2 +- .../tabs/room/NotificationSettingsTab.tsx | 2 +- .../tabs/room/RolesRoomSettingsTab.tsx | 4 ++-- .../tabs/room/SecurityRoomSettingsTab.tsx | 2 +- .../tabs/user/GeneralUserSettingsTab.tsx | 3 +-- .../tabs/user/HelpUserSettingsTab.tsx | 2 +- .../tabs/user/VoiceUserSettingsTab.tsx | 2 +- src/models/Call.ts | 6 +++-- .../previews/PollStartEventPreview.ts | 2 +- test/TestSdkContext.ts | 24 +++++++++---------- test/test-utils/call.ts | 3 ++- tsconfig.json | 3 ++- 57 files changed, 75 insertions(+), 80 deletions(-) diff --git a/babel.config.js b/babel.config.js index a9e4b5c137b..71016846103 100644 --- a/babel.config.js +++ b/babel.config.js @@ -10,9 +10,10 @@ module.exports = { "last 2 Safari versions", "last 2 Edge versions", ], + include: ["@babel/plugin-transform-class-properties"], }, ], - "@babel/preset-typescript", + ["@babel/preset-typescript", { allowDeclareFields: true }], "@babel/preset-react", ], plugins: [ diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index 3a97f27b381..07b600484ac 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -205,7 +205,7 @@ interface IReadReceiptForUser { */ export default class MessagePanel extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; public static defaultProps = { disableGrouping: false, diff --git a/src/components/structures/RightPanel.tsx b/src/components/structures/RightPanel.tsx index 1d6bf101b6e..9e228de611b 100644 --- a/src/components/structures/RightPanel.tsx +++ b/src/components/structures/RightPanel.tsx @@ -73,7 +73,7 @@ interface IState { export default class RightPanel extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: Props, context: React.ContextType) { super(props, context); diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index a0555abbf78..9c6ffb857f9 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -417,7 +417,7 @@ export class RoomView extends React.Component { private roomViewBody = createRef(); public static contextType = SDKContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IRoomProps, context: React.ContextType) { super(props, context); diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 4564741a290..1c188f8f73b 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -605,7 +605,7 @@ const SpaceSetupPrivateInvite: React.FC<{ export default class SpaceRoomView extends React.PureComponent { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; private readonly dispatcherRef: string; diff --git a/src/components/structures/ThreadView.tsx b/src/components/structures/ThreadView.tsx index a345faf9f74..a1c1df1e011 100644 --- a/src/components/structures/ThreadView.tsx +++ b/src/components/structures/ThreadView.tsx @@ -83,7 +83,7 @@ interface IState { export default class ThreadView extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private dispatcherRef: string | null = null; private readonly layoutWatcherRef: string; diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index b193403695c..976c00e2fdc 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -241,7 +241,7 @@ interface IEventIndexOpts { */ class TimelinePanel extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; // a map from room id to read marker event timestamp public static roomReadMarkerTsMap: Record = {}; @@ -273,7 +273,6 @@ class TimelinePanel extends React.Component { public constructor(props: IProps, context: React.ContextType) { super(props, context); - this.context = context; debuglog("mounting"); diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index 6921c262645..ca949f46d08 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -90,7 +90,7 @@ const below = (rect: PartialDOMRect): MenuProps => { export default class UserMenu extends React.Component { public static contextType = SDKContext; - public context!: React.ContextType; + public declare context: React.ContextType; private dispatcherRef?: string; private themeWatcherRef?: string; @@ -100,7 +100,6 @@ export default class UserMenu extends React.Component { public constructor(props: IProps, context: React.ContextType) { super(props, context); - this.context = context; this.state = { contextMenuPosition: null, isDarkTheme: this.isUserOnDarkTheme(), diff --git a/src/components/structures/UserView.tsx b/src/components/structures/UserView.tsx index 4d5dd258e01..27be0e095aa 100644 --- a/src/components/structures/UserView.tsx +++ b/src/components/structures/UserView.tsx @@ -41,7 +41,7 @@ interface IState { export default class UserView extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps) { super(props); diff --git a/src/components/structures/auth/SoftLogout.tsx b/src/components/structures/auth/SoftLogout.tsx index f623ae7dcbb..ca34e3830aa 100644 --- a/src/components/structures/auth/SoftLogout.tsx +++ b/src/components/structures/auth/SoftLogout.tsx @@ -72,13 +72,11 @@ interface IState { export default class SoftLogout extends React.Component { public static contextType = SDKContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps, context: React.ContextType) { super(props, context); - this.context = context; - this.state = { loginView: LoginView.Loading, busy: false, diff --git a/src/components/views/context_menus/MessageContextMenu.tsx b/src/components/views/context_menus/MessageContextMenu.tsx index e0fca0a4c0b..c56ac746cb9 100644 --- a/src/components/views/context_menus/MessageContextMenu.tsx +++ b/src/components/views/context_menus/MessageContextMenu.tsx @@ -133,7 +133,7 @@ interface IState { export default class MessageContextMenu extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private reactButtonRef = createRef(); // XXX Ref to a functional component diff --git a/src/components/views/elements/AppTile.tsx b/src/components/views/elements/AppTile.tsx index 0820ac62d12..5a617b97327 100644 --- a/src/components/views/elements/AppTile.tsx +++ b/src/components/views/elements/AppTile.tsx @@ -120,7 +120,7 @@ interface IState { export default class AppTile extends React.Component { public static contextType = MatrixClientContext; - public context!: ContextType; + public declare context: ContextType; public static defaultProps: Partial = { waitForIframeLoad: true, @@ -144,7 +144,6 @@ export default class AppTile extends React.Component { public constructor(props: IProps, context: ContextType) { super(props); - this.context = context; // XXX: workaround for lack of `declare` support on `public context!:` definition // Tiles in miniMode are floating, and therefore not docked if (!this.props.miniMode) { diff --git a/src/components/views/elements/EventListSummary.tsx b/src/components/views/elements/EventListSummary.tsx index a1270427ccd..4f5817e4c74 100644 --- a/src/components/views/elements/EventListSummary.tsx +++ b/src/components/views/elements/EventListSummary.tsx @@ -81,7 +81,7 @@ export default class EventListSummary extends React.Component< IProps & Required> > { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; public static defaultProps = { summaryLength: 1, diff --git a/src/components/views/elements/PersistentApp.tsx b/src/components/views/elements/PersistentApp.tsx index 812d3432498..dfed54a3ba0 100644 --- a/src/components/views/elements/PersistentApp.tsx +++ b/src/components/views/elements/PersistentApp.tsx @@ -32,7 +32,7 @@ interface IProps { export default class PersistentApp extends React.Component { public static contextType = MatrixClientContext; - public context!: ContextType; + public declare context: ContextType; private room: Room; public constructor(props: IProps, context: ContextType) { diff --git a/src/components/views/elements/ReplyChain.tsx b/src/components/views/elements/ReplyChain.tsx index b7e833a629b..621a360bc54 100644 --- a/src/components/views/elements/ReplyChain.tsx +++ b/src/components/views/elements/ReplyChain.tsx @@ -73,7 +73,7 @@ interface IState { // be low as each event being loaded (after the first) is triggered by an explicit user action. export default class ReplyChain extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private unmounted = false; private room: Room; diff --git a/src/components/views/elements/RoomAliasField.tsx b/src/components/views/elements/RoomAliasField.tsx index d5353dcabc3..1ec057fff10 100644 --- a/src/components/views/elements/RoomAliasField.tsx +++ b/src/components/views/elements/RoomAliasField.tsx @@ -41,7 +41,7 @@ interface IState { // Controlled form component wrapping Field for inputting a room alias scoped to a given domain export default class RoomAliasField extends React.PureComponent { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; private fieldRef = createRef(); diff --git a/src/components/views/emojipicker/ReactionPicker.tsx b/src/components/views/emojipicker/ReactionPicker.tsx index 075a6e6cee7..8265331a3cd 100644 --- a/src/components/views/emojipicker/ReactionPicker.tsx +++ b/src/components/views/emojipicker/ReactionPicker.tsx @@ -37,7 +37,7 @@ interface IState { class ReactionPicker extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps, context: React.ContextType) { super(props, context); diff --git a/src/components/views/emojipicker/Search.tsx b/src/components/views/emojipicker/Search.tsx index 33549b7489a..d7077f0591a 100644 --- a/src/components/views/emojipicker/Search.tsx +++ b/src/components/views/emojipicker/Search.tsx @@ -31,7 +31,7 @@ interface IProps { class Search extends React.PureComponent { public static contextType = RovingTabIndexContext; - public context!: React.ContextType; + public declare context: React.ContextType; private inputRef = React.createRef(); diff --git a/src/components/views/location/LocationPicker.tsx b/src/components/views/location/LocationPicker.tsx index 2ddd19dfe3d..44e97e5abdf 100644 --- a/src/components/views/location/LocationPicker.tsx +++ b/src/components/views/location/LocationPicker.tsx @@ -50,7 +50,7 @@ const isSharingOwnLocation = (shareType: LocationShareType): boolean => class LocationPicker extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; private map?: maplibregl.Map; private geolocate?: maplibregl.GeolocateControl; private marker?: maplibregl.Marker; diff --git a/src/components/views/messages/EditHistoryMessage.tsx b/src/components/views/messages/EditHistoryMessage.tsx index d688650353a..cef00b38ee4 100644 --- a/src/components/views/messages/EditHistoryMessage.tsx +++ b/src/components/views/messages/EditHistoryMessage.tsx @@ -52,7 +52,7 @@ interface IState { export default class EditHistoryMessage extends React.PureComponent { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; private content = createRef(); private pills: Element[] = []; @@ -60,7 +60,6 @@ export default class EditHistoryMessage extends React.PureComponent) { super(props); - this.context = context; const cli = this.context; const userId = cli.getSafeUserId(); diff --git a/src/components/views/messages/MAudioBody.tsx b/src/components/views/messages/MAudioBody.tsx index de30b65f724..9edfa629147 100644 --- a/src/components/views/messages/MAudioBody.tsx +++ b/src/components/views/messages/MAudioBody.tsx @@ -38,7 +38,7 @@ interface IState { export default class MAudioBody extends React.PureComponent { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IBodyProps) { super(props); diff --git a/src/components/views/messages/MFileBody.tsx b/src/components/views/messages/MFileBody.tsx index bf4922615f4..84293fec3d3 100644 --- a/src/components/views/messages/MFileBody.tsx +++ b/src/components/views/messages/MFileBody.tsx @@ -106,7 +106,7 @@ interface IState { export default class MFileBody extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; public static defaultProps = { showGenericPlaceholder: true, diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 36f3a851687..c0d407d5b99 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -65,7 +65,7 @@ interface IState { export default class MImageBody extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private unmounted = true; private image = createRef(); diff --git a/src/components/views/messages/MLocationBody.tsx b/src/components/views/messages/MLocationBody.tsx index eedf5a60465..fea4a2bae24 100644 --- a/src/components/views/messages/MLocationBody.tsx +++ b/src/components/views/messages/MLocationBody.tsx @@ -38,7 +38,7 @@ interface IState { export default class MLocationBody extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; private unmounted = false; private mapId: string; diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index d777ed9d779..2e59ee18479 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -147,7 +147,7 @@ export function launchPollEditor(mxEvent: MatrixEvent, getRelationsForEvent?: Ge export default class MPollBody extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; private seenEventIds: string[] = []; // Events we have already seen public constructor(props: IBodyProps) { diff --git a/src/components/views/messages/MVideoBody.tsx b/src/components/views/messages/MVideoBody.tsx index be6ae4442ce..8b0a70ab98c 100644 --- a/src/components/views/messages/MVideoBody.tsx +++ b/src/components/views/messages/MVideoBody.tsx @@ -42,7 +42,7 @@ interface IState { export default class MVideoBody extends React.PureComponent { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private videoRef = React.createRef(); private sizeWatcher?: string; diff --git a/src/components/views/messages/MessageEvent.tsx b/src/components/views/messages/MessageEvent.tsx index db0016de7b0..fb700579bea 100644 --- a/src/components/views/messages/MessageEvent.tsx +++ b/src/components/views/messages/MessageEvent.tsx @@ -90,7 +90,7 @@ export default class MessageEvent extends React.Component implements IMe private evTypes = new Map>(baseEvTypes.entries()); public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps, context: React.ContextType) { super(props, context); diff --git a/src/components/views/messages/ReactionsRow.tsx b/src/components/views/messages/ReactionsRow.tsx index e57326edd73..c5d004b12b0 100644 --- a/src/components/views/messages/ReactionsRow.tsx +++ b/src/components/views/messages/ReactionsRow.tsx @@ -83,11 +83,10 @@ interface IState { export default class ReactionsRow extends React.PureComponent { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps, context: React.ContextType) { super(props, context); - this.context = context; this.state = { myReactions: this.getMyReactions(), diff --git a/src/components/views/messages/ReactionsRowButton.tsx b/src/components/views/messages/ReactionsRowButton.tsx index 1dbd1bd7bf1..7c4dcc8b3cb 100644 --- a/src/components/views/messages/ReactionsRowButton.tsx +++ b/src/components/views/messages/ReactionsRowButton.tsx @@ -46,7 +46,7 @@ export interface IProps { export default class ReactionsRowButton extends React.PureComponent { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public onClick = (): void => { const { mxEvent, myReactionEvent, content } = this.props; diff --git a/src/components/views/messages/ReactionsRowButtonTooltip.tsx b/src/components/views/messages/ReactionsRowButtonTooltip.tsx index 5b4db10ed6b..f9a5c2d66f6 100644 --- a/src/components/views/messages/ReactionsRowButtonTooltip.tsx +++ b/src/components/views/messages/ReactionsRowButtonTooltip.tsx @@ -36,7 +36,7 @@ interface IProps { export default class ReactionsRowButtonTooltip extends React.PureComponent> { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public render(): React.ReactNode { const { content, reactionEvents, mxEvent, children } = this.props; diff --git a/src/components/views/messages/TextualBody.tsx b/src/components/views/messages/TextualBody.tsx index 98d5a7ce664..fc84a6b0413 100644 --- a/src/components/views/messages/TextualBody.tsx +++ b/src/components/views/messages/TextualBody.tsx @@ -66,7 +66,7 @@ export default class TextualBody extends React.Component { private tooltips: Element[] = []; public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IBodyProps) { super(props); diff --git a/src/components/views/room_settings/AliasSettings.tsx b/src/components/views/room_settings/AliasSettings.tsx index 3b2f294e5c1..a8fe6cdbe95 100644 --- a/src/components/views/room_settings/AliasSettings.tsx +++ b/src/components/views/room_settings/AliasSettings.tsx @@ -102,7 +102,7 @@ interface IState { export default class AliasSettings extends React.Component { public static contextType = MatrixClientContext; - public context!: ContextType; + public declare context: ContextType; public static defaultProps = { canSetAliases: false, diff --git a/src/components/views/rooms/EditMessageComposer.tsx b/src/components/views/rooms/EditMessageComposer.tsx index fabca13a1c7..468a9147ac4 100644 --- a/src/components/views/rooms/EditMessageComposer.tsx +++ b/src/components/views/rooms/EditMessageComposer.tsx @@ -129,7 +129,7 @@ interface IState { class EditMessageComposer extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private readonly editorRef = createRef(); private readonly dispatcherRef: string; @@ -138,7 +138,6 @@ class EditMessageComposer extends React.Component) { super(props); - this.context = context; // otherwise React will only set it prior to render due to type def above const isRestored = this.createEditorModel(); const ev = this.props.editState.getEvent(); diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 669e57a06a4..e0f8ab1161c 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -297,7 +297,7 @@ export class UnwrappedEventTile extends React.Component }; public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private unmounted = false; diff --git a/src/components/views/rooms/LegacyRoomHeader.tsx b/src/components/views/rooms/LegacyRoomHeader.tsx index b3f76e980f1..d3540269ab9 100644 --- a/src/components/views/rooms/LegacyRoomHeader.tsx +++ b/src/components/views/rooms/LegacyRoomHeader.tsx @@ -493,7 +493,7 @@ export default class RoomHeader extends React.Component { }; public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private readonly client = this.props.room.client; private readonly featureAskToJoinWatcher: string; diff --git a/src/components/views/rooms/MemberList.tsx b/src/components/views/rooms/MemberList.tsx index dea4dd58d37..4681e4cd41a 100644 --- a/src/components/views/rooms/MemberList.tsx +++ b/src/components/views/rooms/MemberList.tsx @@ -82,7 +82,7 @@ export default class MemberList extends React.Component { private mounted = false; public static contextType = SDKContext; - public context!: React.ContextType; + public declare context: React.ContextType; private tiles: Map = new Map(); public constructor(props: IProps, context: React.ContextType) { diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index bb4b4c72453..5261f4da103 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -119,7 +119,7 @@ export class MessageComposer extends React.Component { private _voiceRecording: Optional; public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; public static defaultProps = { compact: false, diff --git a/src/components/views/rooms/MessageComposerButtons.tsx b/src/components/views/rooms/MessageComposerButtons.tsx index 77d809d1f8d..dc5c14517b6 100644 --- a/src/components/views/rooms/MessageComposerButtons.tsx +++ b/src/components/views/rooms/MessageComposerButtons.tsx @@ -298,7 +298,7 @@ interface IPollButtonProps { class PollButton extends React.PureComponent { public static contextType = OverflowMenuContext; - public context!: React.ContextType; + public declare context: React.ContextType; private onCreateClick = (): void => { this.context?.(); // close overflow menu diff --git a/src/components/views/rooms/PinnedEventTile.tsx b/src/components/views/rooms/PinnedEventTile.tsx index 581583d1d5a..6c63efc3520 100644 --- a/src/components/views/rooms/PinnedEventTile.tsx +++ b/src/components/views/rooms/PinnedEventTile.tsx @@ -40,7 +40,7 @@ const AVATAR_SIZE = "24px"; export default class PinnedEventTile extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; private onTileClicked = (): void => { dis.dispatch({ diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index d088fbc927a..93179859635 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -432,7 +432,7 @@ export default class RoomList extends React.PureComponent { private treeRef = createRef(); public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps) { super(props); diff --git a/src/components/views/rooms/RoomUpgradeWarningBar.tsx b/src/components/views/rooms/RoomUpgradeWarningBar.tsx index 99ae4f7ba4b..ab374108e9d 100644 --- a/src/components/views/rooms/RoomUpgradeWarningBar.tsx +++ b/src/components/views/rooms/RoomUpgradeWarningBar.tsx @@ -33,7 +33,7 @@ interface IState { export default class RoomUpgradeWarningBar extends React.PureComponent { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps, context: React.ContextType) { super(props, context); diff --git a/src/components/views/rooms/SearchResultTile.tsx b/src/components/views/rooms/SearchResultTile.tsx index 99b5f0805c3..52977901cf9 100644 --- a/src/components/views/rooms/SearchResultTile.tsx +++ b/src/components/views/rooms/SearchResultTile.tsx @@ -44,7 +44,7 @@ interface IProps { export default class SearchResultTile extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; // A map of private callEventGroupers = new Map(); diff --git a/src/components/views/rooms/SendMessageComposer.tsx b/src/components/views/rooms/SendMessageComposer.tsx index c5972ee86ac..eee2a476a7e 100644 --- a/src/components/views/rooms/SendMessageComposer.tsx +++ b/src/components/views/rooms/SendMessageComposer.tsx @@ -254,7 +254,7 @@ interface ISendMessageComposerProps extends MatrixClientProps { export class SendMessageComposer extends React.Component { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private readonly prepareToEncrypt?: DebouncedFunc<() => void>; private readonly editorRef = createRef(); @@ -269,7 +269,6 @@ export class SendMessageComposer extends React.Component) { super(props, context); - this.context = context; // otherwise React will only set it prior to render due to type def above if (this.props.mxClient.isCryptoEnabled() && this.props.mxClient.isRoomEncrypted(this.props.room.roomId)) { this.prepareToEncrypt = throttle( diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index 1001def3869..ac633d2d144 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -63,7 +63,7 @@ interface IState { */ export default class VoiceRecordComposerTile extends React.PureComponent { public static contextType = RoomContext; - public context!: React.ContextType; + public declare context: React.ContextType; private voiceRecordingId: string; public constructor(props: IProps) { diff --git a/src/components/views/settings/tabs/room/BridgeSettingsTab.tsx b/src/components/views/settings/tabs/room/BridgeSettingsTab.tsx index cfe6b3ccd32..1f44f06323e 100644 --- a/src/components/views/settings/tabs/room/BridgeSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/BridgeSettingsTab.tsx @@ -36,7 +36,7 @@ interface IProps { export default class BridgeSettingsTab extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; private renderBridgeCard(event: MatrixEvent, room: Room | null): ReactNode { const content = event.getContent(); diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx index 7b260e3a7e6..97503ef50a7 100644 --- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx @@ -42,7 +42,7 @@ interface IState { export default class GeneralRoomSettingsTab extends React.Component { public static contextType = MatrixClientContext; - public context!: ContextType; + public declare context: ContextType; public constructor(props: IProps, context: ContextType) { super(props, context); diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx index 1c536ed6d64..1b0dbfdf1a9 100644 --- a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx @@ -50,7 +50,7 @@ export default class NotificationsSettingsTab extends React.Component(); public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps, context: React.ContextType) { super(props, context); diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx index 2197cad3dff..3105ba961a3 100644 --- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx @@ -89,7 +89,7 @@ interface IBannedUserProps { export class BannedUser extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; private onUnbanClick = (): void => { this.context.unban(this.props.member.roomId, this.props.member.userId).catch((err) => { @@ -137,7 +137,7 @@ interface IProps { export default class RolesRoomSettingsTab extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public componentDidMount(): void { this.context.on(RoomStateEvent.Update, this.onRoomStateUpdate); diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index 01fcbd1abb0..adbf1b72d96 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -67,7 +67,7 @@ interface IState { export default class SecurityRoomSettingsTab extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps, context: React.ContextType) { super(props, context); diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx index 8405dd83baa..ebf4da56fe6 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx @@ -50,11 +50,10 @@ interface IState { export default class GeneralUserSettingsTab extends React.Component { public static contextType = SDKContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps, context: React.ContextType) { super(props); - this.context = context; this.state = { canChangePassword: false, diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx index 2bf2c0f6042..716aa0aff20 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx @@ -40,7 +40,7 @@ interface IState { export default class HelpUserSettingsTab extends React.Component { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: IProps) { super(props); diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx index 758a48e1c57..f925cfd728d 100644 --- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx @@ -59,7 +59,7 @@ const mapDeviceKindToHandlerValue = (deviceKind: MediaDeviceKindEnum): string | export default class VoiceUserSettingsTab extends React.Component<{}, IState> { public static contextType = MatrixClientContext; - public context!: React.ContextType; + public declare context: React.ContextType; public constructor(props: {}) { super(props); diff --git a/src/models/Call.ts b/src/models/Call.ts index 7935025e5b2..fc23ef9d573 100644 --- a/src/models/Call.ts +++ b/src/models/Call.ts @@ -126,8 +126,8 @@ interface CallEventHandlerMap { * A group call accessed through a widget. */ export abstract class Call extends TypedEventEmitter { - protected readonly widgetUid = WidgetUtils.getWidgetUid(this.widget); - protected readonly room = this.client.getRoom(this.roomId)!; + protected readonly widgetUid; + protected readonly room; /** * The time after which device member state should be considered expired. @@ -184,6 +184,8 @@ export abstract class Call extends TypedEventEmitter; + public declare context: React.ContextType; public getTextFor(event: MatrixEvent, tagId?: TagID, isThread?: boolean): string | null { let eventContent = event.getContent(); diff --git a/test/TestSdkContext.ts b/test/TestSdkContext.ts index 5aad5bcfa51..154881db530 100644 --- a/test/TestSdkContext.ts +++ b/test/TestSdkContext.ts @@ -35,18 +35,18 @@ import { * replace individual stores. This is useful for tests which need to mock out stores. */ export class TestSdkContext extends SdkContextClass { - public _RightPanelStore?: RightPanelStore; - public _RoomNotificationStateStore?: RoomNotificationStateStore; - public _RoomViewStore?: RoomViewStore; - public _WidgetPermissionStore?: WidgetPermissionStore; - public _WidgetLayoutStore?: WidgetLayoutStore; - public _WidgetStore?: WidgetStore; - public _PosthogAnalytics?: PosthogAnalytics; - public _SlidingSyncManager?: SlidingSyncManager; - public _SpaceStore?: SpaceStoreClass; - public _VoiceBroadcastRecordingsStore?: VoiceBroadcastRecordingsStore; - public _VoiceBroadcastPreRecordingStore?: VoiceBroadcastPreRecordingStore; - public _VoiceBroadcastPlaybacksStore?: VoiceBroadcastPlaybacksStore; + public declare _RightPanelStore?: RightPanelStore; + public declare _RoomNotificationStateStore?: RoomNotificationStateStore; + public declare _RoomViewStore?: RoomViewStore; + public declare _WidgetPermissionStore?: WidgetPermissionStore; + public declare _WidgetLayoutStore?: WidgetLayoutStore; + public declare _WidgetStore?: WidgetStore; + public declare _PosthogAnalytics?: PosthogAnalytics; + public declare _SlidingSyncManager?: SlidingSyncManager; + public declare _SpaceStore?: SpaceStoreClass; + public declare _VoiceBroadcastRecordingsStore?: VoiceBroadcastRecordingsStore; + public declare _VoiceBroadcastPreRecordingStore?: VoiceBroadcastPreRecordingStore; + public declare _VoiceBroadcastPlaybacksStore?: VoiceBroadcastPlaybacksStore; constructor() { super(); diff --git a/test/test-utils/call.ts b/test/test-utils/call.ts index e97c7a59e9b..5aeb466244f 100644 --- a/test/test-utils/call.ts +++ b/test/test-utils/call.ts @@ -43,6 +43,7 @@ export class MockedCall extends Call { }, room.client, ); + this.groupCall = { creationTs: this.event.getTs() } as unknown as GroupCall; } public static get(room: Room): MockedCall | null { @@ -67,7 +68,7 @@ export class MockedCall extends Call { CallStore.instance.updateRoom(room); } - public readonly groupCall = { creationTs: this.event.getTs() } as unknown as GroupCall; + public readonly groupCall; public get participants(): Map> { return super.participants; diff --git a/tsconfig.json b/tsconfig.json index 788ee414cb9..55e83d95b97 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,9 +4,10 @@ "emitDecoratorMetadata": false, "resolveJsonModule": true, "esModuleInterop": true, + "useDefineForClassFields": true, "module": "es2022", "moduleResolution": "node", - "target": "es2021", + "target": "es2022", "noUnusedLocals": true, "sourceMap": false, "outDir": "./lib", From 9b4bfd495b046c7212ca713f952dfdffaca399e0 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Aug 2024 09:50:45 +0100 Subject: [PATCH 04/42] Upgrade to es2022 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- babel.config.js | 3 ++- tsconfig.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/babel.config.js b/babel.config.js index 93920120c64..9c56c45d158 100644 --- a/babel.config.js +++ b/babel.config.js @@ -10,9 +10,10 @@ module.exports = { "last 2 Safari versions", "last 2 Edge versions", ], + include: ["@babel/plugin-transform-class-properties"], }, ], - "@babel/preset-typescript", + ["@babel/preset-typescript", { allowDeclareFields: true }], "@babel/preset-react", ], plugins: [ diff --git a/tsconfig.json b/tsconfig.json index f7ace546ebe..bb2e3107cec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,9 +4,10 @@ "emitDecoratorMetadata": false, "resolveJsonModule": true, "esModuleInterop": true, + "useDefineForClassFields": true, "module": "es2022", "moduleResolution": "node", - "target": "es2021", + "target": "es2022", "noUnusedLocals": true, "sourceMap": false, "outDir": "./lib", From f33eec70edd8a65f4102242276df1a2072f25c6f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Aug 2024 09:59:28 +0100 Subject: [PATCH 05/42] Fix babel config Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- babel.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/babel.config.js b/babel.config.js index 71016846103..541c567770a 100644 --- a/babel.config.js +++ b/babel.config.js @@ -19,7 +19,6 @@ module.exports = { plugins: [ "@babel/plugin-proposal-export-default-from", "@babel/plugin-transform-numeric-separator", - "@babel/plugin-transform-class-properties", "@babel/plugin-transform-object-rest-spread", "@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-runtime", From b71d044d899b99693fcb345ff24a9973431fdab6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Aug 2024 09:59:29 +0100 Subject: [PATCH 06/42] Fix babel config Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- babel.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/babel.config.js b/babel.config.js index 9c56c45d158..b63a90e5ff7 100644 --- a/babel.config.js +++ b/babel.config.js @@ -19,7 +19,6 @@ module.exports = { plugins: [ "@babel/plugin-proposal-export-default-from", "@babel/plugin-transform-numeric-separator", - "@babel/plugin-transform-class-properties", "@babel/plugin-transform-object-rest-spread", "@babel/plugin-transform-optional-chaining", "@babel/plugin-transform-nullish-coalescing-operator", From 2938e5733e81d0148d646d408a8ba7e24fafebea Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Aug 2024 10:56:29 +0100 Subject: [PATCH 07/42] Fix React contexts Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/EmbeddedPage.tsx | 1 + src/components/structures/FilePanel.tsx | 1 + src/components/structures/NotificationPanel.tsx | 5 +++-- src/components/structures/RoomStatusBar.tsx | 1 + src/components/structures/ThreadView.tsx | 4 ++-- src/components/structures/UserView.tsx | 4 ++-- src/components/views/context_menus/MessageContextMenu.tsx | 4 ++-- src/components/views/elements/AppTile.tsx | 2 +- src/components/views/location/LocationPicker.tsx | 4 ++-- src/components/views/messages/EditHistoryMessage.tsx | 2 +- src/components/views/messages/MAudioBody.tsx | 6 ------ src/components/views/messages/MFileBody.tsx | 6 ------ src/components/views/messages/MImageBody.tsx | 4 ++-- src/components/views/messages/MLocationBody.tsx | 4 ++-- src/components/views/messages/MPollBody.tsx | 4 ++-- src/components/views/messages/MVideoBody.tsx | 4 ++-- src/components/views/messages/MessageActionBar.tsx | 1 + src/components/views/messages/TextualBody.tsx | 4 ++-- src/components/views/right_panel/TimelineCard.tsx | 5 +++-- src/components/views/rooms/Autocomplete.tsx | 5 +++-- src/components/views/rooms/EditMessageComposer.tsx | 2 +- src/components/views/rooms/LegacyRoomHeader.tsx | 2 +- src/components/views/rooms/MemberList.tsx | 2 +- src/components/views/rooms/MessageComposer.tsx | 4 ++-- src/components/views/rooms/ReplyPreview.tsx | 1 + src/components/views/rooms/RoomList.tsx | 4 ++-- src/components/views/rooms/VoiceRecordComposerTile.tsx | 4 ++-- .../views/settings/tabs/user/GeneralUserSettingsTab.tsx | 2 +- .../views/settings/tabs/user/HelpUserSettingsTab.tsx | 4 ++-- .../views/settings/tabs/user/VoiceUserSettingsTab.tsx | 4 ++-- src/components/views/spaces/SpaceTreeLevel.tsx | 5 +++-- 31 files changed, 51 insertions(+), 54 deletions(-) diff --git a/src/components/structures/EmbeddedPage.tsx b/src/components/structures/EmbeddedPage.tsx index c0d7835747f..2c6a731d822 100644 --- a/src/components/structures/EmbeddedPage.tsx +++ b/src/components/structures/EmbeddedPage.tsx @@ -45,6 +45,7 @@ interface IState { export default class EmbeddedPage extends React.PureComponent { public static contextType = MatrixClientContext; + public declare context: React.ContextType; private unmounted = false; private dispatcherRef: string | null = null; diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index 9c3550804f6..86a3e1cf833 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -59,6 +59,7 @@ interface IState { */ class FilePanel extends React.Component { public static contextType = RoomContext; + public declare context: React.ContextType; // This is used to track if a decrypted event was a live event and should be // added to the timeline. diff --git a/src/components/structures/NotificationPanel.tsx b/src/components/structures/NotificationPanel.tsx index dff2716c19b..7c8fd71b791 100644 --- a/src/components/structures/NotificationPanel.tsx +++ b/src/components/structures/NotificationPanel.tsx @@ -42,11 +42,12 @@ interface IState { */ export default class NotificationPanel extends React.PureComponent { public static contextType = RoomContext; + public declare context: React.ContextType; private card = React.createRef(); - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); this.state = { narrow: false, diff --git a/src/components/structures/RoomStatusBar.tsx b/src/components/structures/RoomStatusBar.tsx index 311f6b89b55..75323091ac8 100644 --- a/src/components/structures/RoomStatusBar.tsx +++ b/src/components/structures/RoomStatusBar.tsx @@ -88,6 +88,7 @@ interface IState { export default class RoomStatusBar extends React.PureComponent { private unmounted = false; public static contextType = MatrixClientContext; + public declare context: React.ContextType; public constructor(props: IProps, context: typeof MatrixClientContext) { super(props, context); diff --git a/src/components/structures/ThreadView.tsx b/src/components/structures/ThreadView.tsx index a1c1df1e011..f2d775464ed 100644 --- a/src/components/structures/ThreadView.tsx +++ b/src/components/structures/ThreadView.tsx @@ -93,8 +93,8 @@ export default class ThreadView extends React.Component { // Set by setEventId in ctor. private eventId!: string; - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); this.setEventId(this.props.mxEvent); const thread = this.props.room.getThread(this.eventId) ?? undefined; diff --git a/src/components/structures/UserView.tsx b/src/components/structures/UserView.tsx index 27be0e095aa..7aa2d92d0ca 100644 --- a/src/components/structures/UserView.tsx +++ b/src/components/structures/UserView.tsx @@ -43,8 +43,8 @@ export default class UserView extends React.Component { public static contextType = MatrixClientContext; public declare context: React.ContextType; - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); this.state = { loading: true, }; diff --git a/src/components/views/context_menus/MessageContextMenu.tsx b/src/components/views/context_menus/MessageContextMenu.tsx index c56ac746cb9..801ab0b023e 100644 --- a/src/components/views/context_menus/MessageContextMenu.tsx +++ b/src/components/views/context_menus/MessageContextMenu.tsx @@ -137,8 +137,8 @@ export default class MessageContextMenu extends React.Component private reactButtonRef = createRef(); // XXX Ref to a functional component - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); this.state = { canRedact: false, diff --git a/src/components/views/elements/AppTile.tsx b/src/components/views/elements/AppTile.tsx index 5a617b97327..6d326b09007 100644 --- a/src/components/views/elements/AppTile.tsx +++ b/src/components/views/elements/AppTile.tsx @@ -143,7 +143,7 @@ export default class AppTile extends React.Component { private unmounted = false; public constructor(props: IProps, context: ContextType) { - super(props); + super(props, context); // Tiles in miniMode are floating, and therefore not docked if (!this.props.miniMode) { diff --git a/src/components/views/location/LocationPicker.tsx b/src/components/views/location/LocationPicker.tsx index 44e97e5abdf..d4739935c76 100644 --- a/src/components/views/location/LocationPicker.tsx +++ b/src/components/views/location/LocationPicker.tsx @@ -55,8 +55,8 @@ class LocationPicker extends React.Component { private geolocate?: maplibregl.GeolocateControl; private marker?: maplibregl.Marker; - public constructor(props: ILocationPickerProps) { - super(props); + public constructor(props: ILocationPickerProps, context: React.ContextType) { + super(props, context); this.state = { position: undefined, diff --git a/src/components/views/messages/EditHistoryMessage.tsx b/src/components/views/messages/EditHistoryMessage.tsx index cef00b38ee4..17071a41f61 100644 --- a/src/components/views/messages/EditHistoryMessage.tsx +++ b/src/components/views/messages/EditHistoryMessage.tsx @@ -59,7 +59,7 @@ export default class EditHistoryMessage extends React.PureComponent) { - super(props); + super(props, context); const cli = this.context; const userId = cli.getSafeUserId(); diff --git a/src/components/views/messages/MAudioBody.tsx b/src/components/views/messages/MAudioBody.tsx index 9edfa629147..a028439470a 100644 --- a/src/components/views/messages/MAudioBody.tsx +++ b/src/components/views/messages/MAudioBody.tsx @@ -40,12 +40,6 @@ export default class MAudioBody extends React.PureComponent public static contextType = RoomContext; public declare context: React.ContextType; - public constructor(props: IBodyProps) { - super(props); - - this.state = {}; - } - public async componentDidMount(): Promise { let buffer: ArrayBuffer; diff --git a/src/components/views/messages/MFileBody.tsx b/src/components/views/messages/MFileBody.tsx index 84293fec3d3..3b380750b1a 100644 --- a/src/components/views/messages/MFileBody.tsx +++ b/src/components/views/messages/MFileBody.tsx @@ -117,12 +117,6 @@ export default class MFileBody extends React.Component { private userDidClick = false; private fileDownloader: FileDownloader = new FileDownloader(() => this.iframe.current); - public constructor(props: IProps) { - super(props); - - this.state = {}; - } - private getContentUrl(): string | null { if (this.props.forExport) return null; const media = mediaFromContent(this.props.mxEvent.getContent()); diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index c0d407d5b99..832275be21a 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -73,8 +73,8 @@ export default class MImageBody extends React.Component { private sizeWatcher?: string; private reconnectedListener: ClientEventHandlerMap[ClientEvent.Sync]; - public constructor(props: IBodyProps) { - super(props); + public constructor(props: IBodyProps, context: React.ContextType) { + super(props, context); this.reconnectedListener = createReconnectedListener(this.clearError); diff --git a/src/components/views/messages/MLocationBody.tsx b/src/components/views/messages/MLocationBody.tsx index fea4a2bae24..f3f1a3d9d3a 100644 --- a/src/components/views/messages/MLocationBody.tsx +++ b/src/components/views/messages/MLocationBody.tsx @@ -44,8 +44,8 @@ export default class MLocationBody extends React.Component { private mapId: string; private reconnectedListener: ClientEventHandlerMap[ClientEvent.Sync]; - public constructor(props: IBodyProps) { - super(props); + public constructor(props: IBodyProps, context: React.ContextType) { + super(props, context); // multiple instances of same map might be in document // eg thread and main timeline, reply diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx index 2e59ee18479..5fad5acd5fc 100644 --- a/src/components/views/messages/MPollBody.tsx +++ b/src/components/views/messages/MPollBody.tsx @@ -150,8 +150,8 @@ export default class MPollBody extends React.Component { public declare context: React.ContextType; private seenEventIds: string[] = []; // Events we have already seen - public constructor(props: IBodyProps) { - super(props); + public constructor(props: IBodyProps, context: React.ContextType) { + super(props, context); this.state = { selected: null, diff --git a/src/components/views/messages/MVideoBody.tsx b/src/components/views/messages/MVideoBody.tsx index 8b0a70ab98c..b844f79404d 100644 --- a/src/components/views/messages/MVideoBody.tsx +++ b/src/components/views/messages/MVideoBody.tsx @@ -47,8 +47,8 @@ export default class MVideoBody extends React.PureComponent private videoRef = React.createRef(); private sizeWatcher?: string; - public constructor(props: IBodyProps) { - super(props); + public constructor(props: IBodyProps, context: React.ContextType) { + super(props, context); this.state = { fetchingData: false, diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index 3cfc252b8c0..25547c78363 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -261,6 +261,7 @@ interface IMessageActionBarProps { export default class MessageActionBar extends React.PureComponent { public static contextType = RoomContext; + public declare context: React.ContextType; public componentDidMount(): void { if (this.props.mxEvent.status && this.props.mxEvent.status !== EventStatus.SENT) { diff --git a/src/components/views/messages/TextualBody.tsx b/src/components/views/messages/TextualBody.tsx index fc84a6b0413..3a232359a1e 100644 --- a/src/components/views/messages/TextualBody.tsx +++ b/src/components/views/messages/TextualBody.tsx @@ -68,8 +68,8 @@ export default class TextualBody extends React.Component { public static contextType = RoomContext; public declare context: React.ContextType; - public constructor(props: IBodyProps) { - super(props); + public constructor(props: IBodyProps, context: React.ContextType) { + super(props, context); this.state = { links: [], diff --git a/src/components/views/right_panel/TimelineCard.tsx b/src/components/views/right_panel/TimelineCard.tsx index 7dfcd633070..97f5aabc320 100644 --- a/src/components/views/right_panel/TimelineCard.tsx +++ b/src/components/views/right_panel/TimelineCard.tsx @@ -77,6 +77,7 @@ interface IState { export default class TimelineCard extends React.Component { public static contextType = RoomContext; + public declare context: React.ContextType; private dispatcherRef?: string; private layoutWatcherRef?: string; @@ -84,8 +85,8 @@ export default class TimelineCard extends React.Component { private card = React.createRef(); private readReceiptsSettingWatcher: string | undefined; - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); this.state = { showReadReceipts: SettingsStore.getValue("showReadReceipts", props.room.roomId), layout: SettingsStore.getValue("layout"), diff --git a/src/components/views/rooms/Autocomplete.tsx b/src/components/views/rooms/Autocomplete.tsx index 8eedf0867ea..eb7c42ee7c8 100644 --- a/src/components/views/rooms/Autocomplete.tsx +++ b/src/components/views/rooms/Autocomplete.tsx @@ -56,9 +56,10 @@ export default class Autocomplete extends React.PureComponent { private containerRef = createRef(); public static contextType = RoomContext; + public declare context: React.ContextType; - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); this.state = { // list of completionResults, each containing completions diff --git a/src/components/views/rooms/EditMessageComposer.tsx b/src/components/views/rooms/EditMessageComposer.tsx index 468a9147ac4..9b33f42914e 100644 --- a/src/components/views/rooms/EditMessageComposer.tsx +++ b/src/components/views/rooms/EditMessageComposer.tsx @@ -137,7 +137,7 @@ class EditMessageComposer extends React.Component) { - super(props); + super(props, context); const isRestored = this.createEditorModel(); const ev = this.props.editState.getEvent(); diff --git a/src/components/views/rooms/LegacyRoomHeader.tsx b/src/components/views/rooms/LegacyRoomHeader.tsx index d3540269ab9..20c8357473b 100644 --- a/src/components/views/rooms/LegacyRoomHeader.tsx +++ b/src/components/views/rooms/LegacyRoomHeader.tsx @@ -497,7 +497,7 @@ export default class RoomHeader extends React.Component { private readonly client = this.props.room.client; private readonly featureAskToJoinWatcher: string; - public constructor(props: IProps, context: IState) { + public constructor(props: IProps, context: React.ContextType) { super(props, context); const notiStore = RoomNotificationStateStore.instance.getRoomState(props.room); notiStore.on(NotificationStateEvents.Update, this.onNotificationUpdate); diff --git a/src/components/views/rooms/MemberList.tsx b/src/components/views/rooms/MemberList.tsx index 4681e4cd41a..cb671035359 100644 --- a/src/components/views/rooms/MemberList.tsx +++ b/src/components/views/rooms/MemberList.tsx @@ -86,7 +86,7 @@ export default class MemberList extends React.Component { private tiles: Map = new Map(); public constructor(props: IProps, context: React.ContextType) { - super(props); + super(props, context); this.state = this.getMembersState([], []); this.showPresence = context?.memberListStore.isPresenceEnabled() ?? true; this.mounted = true; diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index 5261f4da103..a4a73b495f1 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -127,8 +127,8 @@ export class MessageComposer extends React.Component { isRichTextEnabled: true, }; - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); VoiceRecordingStore.instance.on(UPDATE_EVENT, this.onVoiceStoreUpdate); this.state = { diff --git a/src/components/views/rooms/ReplyPreview.tsx b/src/components/views/rooms/ReplyPreview.tsx index 50c625c4286..431af5ce6ff 100644 --- a/src/components/views/rooms/ReplyPreview.tsx +++ b/src/components/views/rooms/ReplyPreview.tsx @@ -39,6 +39,7 @@ interface IProps { export default class ReplyPreview extends React.Component { public static contextType = RoomContext; + public declare context: React.ContextType; public render(): JSX.Element | null { if (!this.props.replyToEvent) return null; diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index 93179859635..7d47748de80 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -434,8 +434,8 @@ export default class RoomList extends React.PureComponent { public static contextType = MatrixClientContext; public declare context: React.ContextType; - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); this.state = { sublists: {}, diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index ac633d2d144..4010adf283f 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -66,8 +66,8 @@ export default class VoiceRecordComposerTile extends React.PureComponent; private voiceRecordingId: string; - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); this.state = {}; diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx index ebf4da56fe6..8f51a71e72f 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx @@ -53,7 +53,7 @@ export default class GeneralUserSettingsTab extends React.Component; public constructor(props: IProps, context: React.ContextType) { - super(props); + super(props, context); this.state = { canChangePassword: false, diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx index 716aa0aff20..867b986c820 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx @@ -42,8 +42,8 @@ export default class HelpUserSettingsTab extends React.Component public static contextType = MatrixClientContext; public declare context: React.ContextType; - public constructor(props: IProps) { - super(props); + public constructor(props: IProps, context: React.ContextType) { + super(props, context); this.state = { appVersion: null, diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx index f925cfd728d..c3d21205ff0 100644 --- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx @@ -61,8 +61,8 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> { public static contextType = MatrixClientContext; public declare context: React.ContextType; - public constructor(props: {}) { - super(props); + public constructor(props: {}, context: React.ContextType) { + super(props, context); this.state = { mediaDevices: null, diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index 253e7bf8816..2351f23aa8c 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -199,11 +199,12 @@ interface IItemState { export class SpaceItem extends React.PureComponent { public static contextType = MatrixClientContext; + public declare context: React.ContextType; private buttonRef = createRef(); - public constructor(props: IItemProps) { - super(props); + public constructor(props: IItemProps, context: React.ContextType) { + super(props, context); const collapsed = SpaceTreeLevelLayoutStore.instance.getSpaceCollapsedState( props.space.roomId, From a1c6ba3782a2e39523b18d78bd90ff129e0a46fb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Aug 2024 11:12:44 +0100 Subject: [PATCH 08/42] Fix types Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomStatusBar.tsx | 27 ++++++++++----- src/components/views/messages/MImageBody.tsx | 33 ++++++++----------- src/components/views/messages/MVideoBody.tsx | 22 +++++-------- src/components/views/messages/TextualBody.tsx | 12 +++---- .../context_menus/MessageContextMenu-test.tsx | 4 +-- .../views/messages/MLocationBody-test.tsx | 4 +-- .../views/messages/MVideoBody-test.tsx | 4 +-- test/components/views/rooms/RoomList-test.tsx | 4 +-- 8 files changed, 52 insertions(+), 58 deletions(-) diff --git a/src/components/structures/RoomStatusBar.tsx b/src/components/structures/RoomStatusBar.tsx index 75323091ac8..c663ab3e319 100644 --- a/src/components/structures/RoomStatusBar.tsx +++ b/src/components/structures/RoomStatusBar.tsx @@ -15,7 +15,16 @@ limitations under the License. */ import React, { ReactNode } from "react"; -import { EventStatus, MatrixEvent, Room, MatrixError, SyncState, SyncStateData } from "matrix-js-sdk/src/matrix"; +import { + ClientEvent, + EventStatus, + MatrixError, + MatrixEvent, + Room, + RoomEvent, + SyncState, + SyncStateData, +} from "matrix-js-sdk/src/matrix"; import { Icon as WarningIcon } from "../../../res/img/feather-customised/warning-triangle.svg"; import { _t, _td } from "../../languageHandler"; @@ -79,8 +88,8 @@ interface IProps { } interface IState { - syncState: SyncState; - syncStateData: SyncStateData; + syncState: SyncState | null; + syncStateData: SyncStateData | null; unsentMessages: MatrixEvent[]; isResending: boolean; } @@ -103,8 +112,8 @@ export default class RoomStatusBar extends React.PureComponent { public componentDidMount(): void { const client = this.context; - client.on("sync", this.onSyncStateChange); - client.on("Room.localEchoUpdated", this.onRoomLocalEchoUpdated); + client.on(ClientEvent.Sync, this.onSyncStateChange); + client.on(RoomEvent.LocalEchoUpdated, this.onRoomLocalEchoUpdated); this.checkSize(); } @@ -118,19 +127,19 @@ export default class RoomStatusBar extends React.PureComponent { // we may have entirely lost our client as we're logging out before clicking login on the guest bar... const client = this.context; if (client) { - client.removeListener("sync", this.onSyncStateChange); - client.removeListener("Room.localEchoUpdated", this.onRoomLocalEchoUpdated); + client.removeListener(ClientEvent.Sync, this.onSyncStateChange); + client.removeListener(RoomEvent.LocalEchoUpdated, this.onRoomLocalEchoUpdated); } } - private onSyncStateChange = (state: SyncState, prevState: SyncState, data: SyncStateData): void => { + private onSyncStateChange = (state: SyncState, prevState: SyncState | null, data?: SyncStateData): void => { if (state === "SYNCING" && prevState === "SYNCING") { return; } if (this.unmounted) return; this.setState({ syncState: state, - syncStateData: data, + syncStateData: data ?? null, }); }; diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 832275be21a..82f03519087 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -20,7 +20,7 @@ import { Blurhash } from "react-blurhash"; import classNames from "classnames"; import { CSSTransition, SwitchTransition } from "react-transition-group"; import { logger } from "matrix-js-sdk/src/logger"; -import { ClientEvent, ClientEventHandlerMap } from "matrix-js-sdk/src/matrix"; +import { ClientEvent } from "matrix-js-sdk/src/matrix"; import { ImageContent } from "matrix-js-sdk/src/types"; import { Tooltip } from "@vector-im/compound-web"; @@ -71,23 +71,16 @@ export default class MImageBody extends React.Component { private image = createRef(); private timeout?: number; private sizeWatcher?: string; - private reconnectedListener: ClientEventHandlerMap[ClientEvent.Sync]; - - public constructor(props: IBodyProps, context: React.ContextType) { - super(props, context); - - this.reconnectedListener = createReconnectedListener(this.clearError); - - this.state = { - contentUrl: null, - thumbUrl: null, - imgError: false, - imgLoaded: false, - hover: false, - showImage: SettingsStore.getValue("showImages"), - placeholder: Placeholder.NoImage, - }; - } + + public state: IState = { + contentUrl: null, + thumbUrl: null, + imgError: false, + imgLoaded: false, + hover: false, + showImage: SettingsStore.getValue("showImages"), + placeholder: Placeholder.NoImage, + }; protected showImage(): void { localStorage.setItem("mx_ShowImage_" + this.props.mxEvent.getId(), "true"); @@ -160,10 +153,10 @@ export default class MImageBody extends React.Component { imgElement.src = url; }; - private clearError = (): void => { + private reconnectedListener = createReconnectedListener((): void => { MatrixClientPeg.get()?.off(ClientEvent.Sync, this.reconnectedListener); this.setState({ imgError: false }); - }; + }); private onImageError = (): void => { // If the thumbnail failed to load then try again using the contentUrl diff --git a/src/components/views/messages/MVideoBody.tsx b/src/components/views/messages/MVideoBody.tsx index b844f79404d..1309a034ad2 100644 --- a/src/components/views/messages/MVideoBody.tsx +++ b/src/components/views/messages/MVideoBody.tsx @@ -47,19 +47,15 @@ export default class MVideoBody extends React.PureComponent private videoRef = React.createRef(); private sizeWatcher?: string; - public constructor(props: IBodyProps, context: React.ContextType) { - super(props, context); - - this.state = { - fetchingData: false, - decryptedUrl: null, - decryptedThumbnailUrl: null, - decryptedBlob: null, - error: null, - posterLoading: false, - blurhashUrl: null, - }; - } + public state = { + fetchingData: false, + decryptedUrl: null, + decryptedThumbnailUrl: null, + decryptedBlob: null, + error: null, + posterLoading: false, + blurhashUrl: null, + }; private getContentUrl(): string | undefined { const content = this.props.mxEvent.getContent(); diff --git a/src/components/views/messages/TextualBody.tsx b/src/components/views/messages/TextualBody.tsx index 3a232359a1e..429dd595284 100644 --- a/src/components/views/messages/TextualBody.tsx +++ b/src/components/views/messages/TextualBody.tsx @@ -68,14 +68,10 @@ export default class TextualBody extends React.Component { public static contextType = RoomContext; public declare context: React.ContextType; - public constructor(props: IBodyProps, context: React.ContextType) { - super(props, context); - - this.state = { - links: [], - widgetHidden: false, - }; - } + public state = { + links: [], + widgetHidden: false, + }; public componentDidMount(): void { if (!this.props.editState) { diff --git a/test/components/views/context_menus/MessageContextMenu-test.tsx b/test/components/views/context_menus/MessageContextMenu-test.tsx index 8fd2f9f4163..2be71e39cbe 100644 --- a/test/components/views/context_menus/MessageContextMenu-test.tsx +++ b/test/components/views/context_menus/MessageContextMenu-test.tsx @@ -535,7 +535,7 @@ function createRightClickMenu(mxEvent: MatrixEvent, context?: Partial>, + props?: Partial, context?: Partial, ): RenderResult { // XXX: We probably shouldn't be assuming all events are going to be message events, but considering this @@ -552,7 +552,7 @@ function makeDefaultRoom(): Room { function createMenu( mxEvent: MatrixEvent, - props?: Partial>, + props?: Partial, context: Partial = {}, beacons: Map = new Map(), room: Room = makeDefaultRoom(), diff --git a/test/components/views/messages/MLocationBody-test.tsx b/test/components/views/messages/MLocationBody-test.tsx index 1cdcb657676..9f156eac94f 100644 --- a/test/components/views/messages/MLocationBody-test.tsx +++ b/test/components/views/messages/MLocationBody-test.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ComponentProps } from "react"; +import React from "react"; import { fireEvent, render, waitFor } from "@testing-library/react"; import { LocationAssetType, ClientEvent, RoomMember, SyncState } from "matrix-js-sdk/src/matrix"; import * as maplibregl from "maplibre-gl"; @@ -42,7 +42,7 @@ describe("MLocationBody", () => { isGuest: jest.fn().mockReturnValue(false), }); const defaultEvent = makeLocationEvent("geo:51.5076,-0.1276", LocationAssetType.Pin); - const defaultProps: ComponentProps = { + const defaultProps: MLocationBody["props"] = { mxEvent: defaultEvent, highlights: [], highlightLink: "", diff --git a/test/components/views/messages/MVideoBody-test.tsx b/test/components/views/messages/MVideoBody-test.tsx index f9bf4d81018..4e526fb802b 100644 --- a/test/components/views/messages/MVideoBody-test.tsx +++ b/test/components/views/messages/MVideoBody-test.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ComponentProps } from "react"; +import React from "react"; import { EventType, getHttpUriForMxc, IContent, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { render, RenderResult } from "@testing-library/react"; import fetchMock from "fetch-mock-jest"; @@ -117,7 +117,7 @@ function makeMVideoBody(w: number, h: number): RenderResult { content, }); - const defaultProps: ComponentProps = { + const defaultProps: MVideoBody["props"] = { mxEvent: event, highlights: [], highlightLink: "", diff --git a/test/components/views/rooms/RoomList-test.tsx b/test/components/views/rooms/RoomList-test.tsx index d92b25e347c..9d7650b2a96 100644 --- a/test/components/views/rooms/RoomList-test.tsx +++ b/test/components/views/rooms/RoomList-test.tsx @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ComponentProps } from "react"; +import React from "react"; import { cleanup, queryByRole, render, screen, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { mocked } from "jest-mock"; @@ -53,7 +53,7 @@ describe("RoomList", () => { const client = MatrixClientPeg.safeGet(); const store = SpaceStore.instance; - function getComponent(props: Partial> = {}): JSX.Element { + function getComponent(props: Partial = {}): JSX.Element { return ( Date: Thu, 1 Aug 2024 11:35:46 +0100 Subject: [PATCH 09/42] Fix React state Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/messages/MAudioBody.tsx | 2 ++ src/components/views/messages/MFileBody.tsx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/components/views/messages/MAudioBody.tsx b/src/components/views/messages/MAudioBody.tsx index a028439470a..13c97d32020 100644 --- a/src/components/views/messages/MAudioBody.tsx +++ b/src/components/views/messages/MAudioBody.tsx @@ -40,6 +40,8 @@ export default class MAudioBody extends React.PureComponent public static contextType = RoomContext; public declare context: React.ContextType; + public state: IState = {}; + public async componentDidMount(): Promise { let buffer: ArrayBuffer; diff --git a/src/components/views/messages/MFileBody.tsx b/src/components/views/messages/MFileBody.tsx index 3b380750b1a..d7542b97407 100644 --- a/src/components/views/messages/MFileBody.tsx +++ b/src/components/views/messages/MFileBody.tsx @@ -108,6 +108,8 @@ export default class MFileBody extends React.Component { public static contextType = RoomContext; public declare context: React.ContextType; + public state: IState = {}; + public static defaultProps = { showGenericPlaceholder: true, }; From 17506f76bfe314508f14445de5e4fdccef409463 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 1 Aug 2024 13:14:47 +0100 Subject: [PATCH 10/42] Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/messages/MFileBody.tsx | 2 -- src/models/Call.ts | 4 ++-- test/test-utils/call.ts | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/views/messages/MFileBody.tsx b/src/components/views/messages/MFileBody.tsx index f5dfec155e3..d7542b97407 100644 --- a/src/components/views/messages/MFileBody.tsx +++ b/src/components/views/messages/MFileBody.tsx @@ -110,8 +110,6 @@ export default class MFileBody extends React.Component { public state: IState = {}; - public state: IState = {}; - public static defaultProps = { showGenericPlaceholder: true, }; diff --git a/src/models/Call.ts b/src/models/Call.ts index fc23ef9d573..658cb780487 100644 --- a/src/models/Call.ts +++ b/src/models/Call.ts @@ -126,8 +126,8 @@ interface CallEventHandlerMap { * A group call accessed through a widget. */ export abstract class Call extends TypedEventEmitter { - protected readonly widgetUid; - protected readonly room; + protected readonly widgetUid: string; + protected readonly room: Room; /** * The time after which device member state should be considered expired. diff --git a/test/test-utils/call.ts b/test/test-utils/call.ts index 5aeb466244f..21672b98867 100644 --- a/test/test-utils/call.ts +++ b/test/test-utils/call.ts @@ -68,7 +68,7 @@ export class MockedCall extends Call { CallStore.instance.updateRoom(room); } - public readonly groupCall; + public readonly groupCall: GroupCall; public get participants(): Map> { return super.participants; From 317ffcf1acee056e71df2a2868d67a4738c098cf Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 7 Mar 2023 17:50:02 +0000 Subject: [PATCH 11/42] Update to React 18 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 19 ++-- src/@types/react.d.ts | 3 + src/NodeAnimator.tsx | 9 +- .../structures/GenericDropdownMenu.tsx | 12 +- src/components/structures/ThreadPanel.tsx | 2 +- src/components/views/avatars/BaseAvatar.tsx | 4 +- .../views/dialogs/spotlight/Option.tsx | 1 + .../views/directory/NetworkDropdown.tsx | 8 +- .../views/elements/PersistentApp.tsx | 3 +- .../views/messages/RoomPredecessorTile.tsx | 10 +- .../views/messages/TextualEvent.tsx | 1 + .../views/messages/TimelineSeparator.tsx | 3 +- src/components/views/pips/WidgetPip.tsx | 5 +- src/components/views/right_panel/UserInfo.tsx | 3 +- src/components/views/rooms/RoomHeader.tsx | 5 +- .../views/settings/UserProfileSettings.tsx | 4 +- .../views/spaces/QuickSettingsButton.tsx | 2 +- src/hooks/useAccountData.ts | 4 +- src/languageHandler.tsx | 18 +-- .../views/dialogs/InviteDialog-test.tsx | 2 +- .../hooks/usePlainTextListeners-test.tsx | 3 +- .../spaces/useUnreadThreadRooms-test.tsx | 3 +- .../room/useRoomThreadNotifications-test.tsx | 2 +- test/hooks/useDebouncedCallback-test.tsx | 2 +- test/hooks/useLatestResult-test.tsx | 4 +- test/hooks/useNotificationSettings-test.tsx | 16 +-- test/hooks/useProfileInfo-test.tsx | 3 +- test/hooks/usePublicRoomDirectory-test.tsx | 3 +- test/hooks/useRoomMembers-test.tsx | 3 +- test/hooks/useSlidingSyncRoomSearch-test.tsx | 3 +- test/hooks/useUnreadNotifications-test.ts | 2 +- test/hooks/useUserDirectory-test.tsx | 3 +- test/hooks/useUserOnboardingTasks-test.tsx | 3 +- test/hooks/useWindowWidth-test.ts | 3 +- test/languageHandler-test.tsx | 10 +- test/modules/ProxiedModuleApi-test.tsx | 12 ++ yarn.lock | 104 ++++++------------ 37 files changed, 132 insertions(+), 165 deletions(-) diff --git a/package.json b/package.json index 2a2dd4bf003..489f7890892 100644 --- a/package.json +++ b/package.json @@ -63,8 +63,8 @@ "lint:workflows": "find .github/workflows -type f \\( -iname '*.yaml' -o -iname '*.yml' \\) | xargs -I {} sh -c 'echo \"Linting {}\"; action-validator \"{}\"'" }, "resolutions": { - "@types/react-dom": "17.0.25", - "@types/react": "17.0.80", + "@types/react-dom": "18.3.0", + "@types/react": "18.3.3", "@types/seedrandom": "3.0.8", "oidc-client-ts": "3.0.1", "jwt-decode": "4.0.0", @@ -81,7 +81,6 @@ "@matrix-org/react-sdk-module-api": "^2.4.0", "@matrix-org/spec": "^1.7.0", "@sentry/browser": "^8.0.0", - "@testing-library/react-hooks": "^8.0.1", "@vector-im/compound-design-tokens": "^1.6.1", "@vector-im/compound-web": "^5.5.0", "@zxcvbn-ts/core": "^3.0.4", @@ -129,10 +128,10 @@ "posthog-js": "1.149.1", "qrcode": "1.5.3", "re-resizable": "^6.9.0", - "react": "17.0.2", + "react": "^18.3.1", "react-beautiful-dnd": "^13.1.0", "react-blurhash": "^0.3.0", - "react-dom": "17.0.2", + "react-dom": "^18.3.1", "react-focus-lock": "^2.5.1", "react-transition-group": "^4.4.1", "rfc4648": "^1.4.0", @@ -167,7 +166,7 @@ "@playwright/test": "^1.40.1", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^12.1.5", + "@testing-library/react": "^14", "@testing-library/user-event": "^14.4.3", "@types/commonmark": "^0.27.4", "@types/content-type": "^1.1.5", @@ -187,9 +186,9 @@ "@types/node-fetch": "^2.6.2", "@types/pako": "^2.0.0", "@types/qrcode": "^1.3.5", - "@types/react": "17.0.80", + "@types/react": "18.3.3", "@types/react-beautiful-dnd": "^13.0.0", - "@types/react-dom": "17.0.25", + "@types/react-dom": "18.3.0", "@types/react-transition-group": "^4.4.0", "@types/sanitize-html": "2.11.0", "@types/sdp-transform": "^2.4.6", @@ -246,6 +245,10 @@ "postcss": "^8.4.19", "webpack": "^4.0.0 || ^5.0.0" }, + "peerDependencies": { + "postcss": "^8.4.19", + "webpack": "^4.0.0 || ^5.0.0" + }, "@casualbot/jest-sonar-reporter": { "outputDirectory": "coverage", "outputName": "jest-sonar-report.xml", diff --git a/src/@types/react.d.ts b/src/@types/react.d.ts index f1f57c5400a..c3b49fb1f8c 100644 --- a/src/@types/react.d.ts +++ b/src/@types/react.d.ts @@ -21,4 +21,7 @@ declare module "react" { function forwardRef( render: (props: PropsWithChildren

, ref: React.ForwardedRef) => React.ReactElement | null, ): (props: P & React.RefAttributes) => React.ReactElement | null; + + // Fix lazy types - https://stackoverflow.com/a/71017028 + function lazy>(factory: () => Promise<{ default: T }>): T; } diff --git a/src/NodeAnimator.tsx b/src/NodeAnimator.tsx index 85151bf3b06..897c58ab2f8 100644 --- a/src/NodeAnimator.tsx +++ b/src/NodeAnimator.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { Key, MutableRefObject, ReactElement, ReactFragment, ReactInstance, ReactPortal } from "react"; +import React, { Key, MutableRefObject, ReactElement, ReactInstance } from "react"; import ReactDom from "react-dom"; interface IChildProps { @@ -35,7 +35,7 @@ interface IProps { innerRef?: MutableRefObject; } -function isReactElement(c: ReactElement | ReactFragment | ReactPortal): c is ReactElement { +function isReactElement(c: ReturnType<(typeof React.Children)["toArray"]>[number]): c is ReactElement { return typeof c === "object" && "type" in c; } @@ -110,7 +110,8 @@ export default class NodeAnimator extends React.Component { } private collectNode(k: Key, node: React.ReactInstance, restingStyle: React.CSSProperties): void { - if (node && this.nodes[k] === undefined && this.props.startStyles.length > 0) { + const key = typeof k === "bigint" ? Number(k) : k; + if (node && this.nodes[key] === undefined && this.props.startStyles.length > 0) { const startStyles = this.props.startStyles; const domNode = ReactDom.findDOMNode(node); // start from startStyle 1: 0 is the one we gave it @@ -124,7 +125,7 @@ export default class NodeAnimator extends React.Component { this.applyStyles(domNode as HTMLElement, restingStyle); }, 0); } - this.nodes[k] = node; + this.nodes[key] = node; if (this.props.innerRef) { this.props.innerRef.current = node; diff --git a/src/components/structures/GenericDropdownMenu.tsx b/src/components/structures/GenericDropdownMenu.tsx index e0fd3b7f9b6..06854768dba 100644 --- a/src/components/structures/GenericDropdownMenu.tsx +++ b/src/components/structures/GenericDropdownMenu.tsx @@ -97,6 +97,12 @@ type WithKeyFunction = T extends Key toKey: (key: T) => Key; }; +export interface AdditionalOptionsProps { + menuDisplayed: boolean; + closeMenu: () => void; + openMenu: () => void; +} + type IProps = WithKeyFunction & { value: T; options: readonly GenericDropdownMenuOption[] | readonly GenericDropdownMenuGroup[]; @@ -105,11 +111,7 @@ type IProps = WithKeyFunction & { onOpen?: (ev: ButtonEvent) => void; onClose?: (ev: ButtonEvent) => void; className?: string; - AdditionalOptions?: FunctionComponent<{ - menuDisplayed: boolean; - closeMenu: () => void; - openMenu: () => void; - }>; + AdditionalOptions?: FunctionComponent; }; export function GenericDropdownMenu({ diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index 8951cfcb910..792c97bc52e 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -117,7 +117,7 @@ export const ThreadPanelHeader: React.FC<{ ) : null; const onMarkAllThreadsReadClick = React.useCallback( - (e) => { + (e: React.MouseEvent) => { PosthogTrackers.trackInteraction("WebThreadsMarkAllReadButton", e); if (!roomContext.room) { logger.error("No room in context to mark all threads read"); diff --git a/src/components/views/avatars/BaseAvatar.tsx b/src/components/views/avatars/BaseAvatar.tsx index d956c26da28..b35109f5d71 100644 --- a/src/components/views/avatars/BaseAvatar.tsx +++ b/src/components/views/avatars/BaseAvatar.tsx @@ -19,7 +19,7 @@ limitations under the License. import React, { forwardRef, useCallback, useContext, useEffect, useState } from "react"; import classNames from "classnames"; -import { ClientEvent } from "matrix-js-sdk/src/matrix"; +import { ClientEvent, SyncState } from "matrix-js-sdk/src/matrix"; import { Avatar } from "@vector-im/compound-web"; import SettingsStore from "../../../settings/SettingsStore"; @@ -80,7 +80,7 @@ const useImageUrl = ({ url, urls }: { url?: string | null; urls?: string[] }): [ }, [url, JSON.stringify(urls)]); // eslint-disable-line react-hooks/exhaustive-deps const cli = useContext(MatrixClientContext); - const onClientSync = useCallback((syncState, prevState) => { + const onClientSync = useCallback((syncState: SyncState, prevState: SyncState | null) => { // Consider the client reconnected if there is no error with syncing. // This means the state could be RECONNECTING, SYNCING, PREPARED or CATCHUP. const reconnected = syncState !== "ERROR" && prevState !== syncState; diff --git a/src/components/views/dialogs/spotlight/Option.tsx b/src/components/views/dialogs/spotlight/Option.tsx index c7d504aa0b4..d15b781fcff 100644 --- a/src/components/views/dialogs/spotlight/Option.tsx +++ b/src/components/views/dialogs/spotlight/Option.tsx @@ -26,6 +26,7 @@ interface OptionProps { id?: string; className?: string; onClick: ((ev: ButtonEvent) => void) | null; + children?: ReactNode; } export const Option: React.FC = ({ inputRef, children, endAdornment, className, ...props }) => { diff --git a/src/components/views/directory/NetworkDropdown.tsx b/src/components/views/directory/NetworkDropdown.tsx index 8736e974e83..deb92858538 100644 --- a/src/components/views/directory/NetworkDropdown.tsx +++ b/src/components/views/directory/NetworkDropdown.tsx @@ -26,7 +26,11 @@ import SdkConfig from "../../../SdkConfig"; import { SettingLevel } from "../../../settings/SettingLevel"; import SettingsStore from "../../../settings/SettingsStore"; import { Protocols } from "../../../utils/DirectoryUtils"; -import { GenericDropdownMenu, GenericDropdownMenuItem } from "../../structures/GenericDropdownMenu"; +import { + AdditionalOptionsProps, + GenericDropdownMenu, + GenericDropdownMenuItem, +} from "../../structures/GenericDropdownMenu"; import TextInputDialog from "../dialogs/TextInputDialog"; import AccessibleButton from "../elements/AccessibleButton"; import withValidation from "../elements/Validation"; @@ -181,7 +185,7 @@ export const NetworkDropdown: React.FC = ({ protocols, config, setConfig })); const addNewServer = useCallback( - ({ closeMenu }) => ( + ({ closeMenu }: AdditionalOptionsProps) => ( <> void) | undefined>; + children?: ReactNode; } export default class PersistentApp extends React.Component { diff --git a/src/components/views/messages/RoomPredecessorTile.tsx b/src/components/views/messages/RoomPredecessorTile.tsx index 3166373fe04..36679d906d6 100644 --- a/src/components/views/messages/RoomPredecessorTile.tsx +++ b/src/components/views/messages/RoomPredecessorTile.tsx @@ -17,7 +17,7 @@ limitations under the License. import React, { useCallback, useContext } from "react"; import { logger } from "matrix-js-sdk/src/logger"; -import { MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; +import { MatrixEvent, Room, RoomState } from "matrix-js-sdk/src/matrix"; import dis from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; @@ -52,7 +52,7 @@ export const RoomPredecessorTile: React.FC = ({ mxEvent, timestamp }) => const predecessor = useRoomState( roomContext.room, useCallback( - (state) => state.findPredecessor(msc3946ProcessDynamicPredecessor), + (state: RoomState) => state.findPredecessor(msc3946ProcessDynamicPredecessor), [msc3946ProcessDynamicPredecessor], ), ); @@ -63,9 +63,9 @@ export const RoomPredecessorTile: React.FC = ({ mxEvent, timestamp }) => dis.dispatch({ action: Action.ViewRoom, - event_id: predecessor.eventId, + event_id: predecessor?.eventId, highlighted: true, - room_id: predecessor.roomId, + room_id: predecessor?.roomId, metricsTrigger: "Predecessor", metricsViaKeyboard: e.type !== "click", }); @@ -126,7 +126,7 @@ export const RoomPredecessorTile: React.FC = ({ mxEvent, timestamp }) => const predecessorPermalink = prevRoom ? createLinkWithRoom(prevRoom, predecessor.roomId, predecessor.eventId) - : createLinkWithoutRoom(predecessor.roomId, predecessor.viaServers, predecessor.eventId); + : createLinkWithoutRoom(predecessor.roomId, predecessor?.viaServers ?? [], predecessor.eventId); const link = ( diff --git a/src/components/views/messages/TextualEvent.tsx b/src/components/views/messages/TextualEvent.tsx index ae94fd31f9e..35351ce531c 100644 --- a/src/components/views/messages/TextualEvent.tsx +++ b/src/components/views/messages/TextualEvent.tsx @@ -27,6 +27,7 @@ interface IProps { export default class TextualEvent extends React.Component { public static contextType = RoomContext; + public declare context: React.ContextType; public render(): React.ReactNode { const text = TextForEvent.textForEvent( diff --git a/src/components/views/messages/TimelineSeparator.tsx b/src/components/views/messages/TimelineSeparator.tsx index 78e0d1fd655..b3a2b9ccfb0 100644 --- a/src/components/views/messages/TimelineSeparator.tsx +++ b/src/components/views/messages/TimelineSeparator.tsx @@ -14,10 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from "react"; +import React, { ReactNode } from "react"; interface Props { label: string; + children?: ReactNode; } export const enum SeparatorKind { diff --git a/src/components/views/pips/WidgetPip.tsx b/src/components/views/pips/WidgetPip.tsx index 9bba2ccc534..a1710d16ccc 100644 --- a/src/components/views/pips/WidgetPip.tsx +++ b/src/components/views/pips/WidgetPip.tsx @@ -34,6 +34,7 @@ import { WidgetType } from "../../../widgets/WidgetType"; import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore"; import WidgetUtils from "../../../utils/WidgetUtils"; import { ElementWidgetActions } from "../../../stores/widgets/ElementWidgetActions"; +import { ButtonEvent } from "../elements/AccessibleButton"; interface Props { widgetId: string; @@ -62,7 +63,7 @@ export const WidgetPip: FC = ({ widgetId, room, viewingRoom, onStartMovin const call = useCallForWidget(widgetId, room.roomId); const onBackClick = useCallback( - (ev) => { + (ev: ButtonEvent) => { ev.preventDefault(); ev.stopPropagation(); @@ -87,7 +88,7 @@ export const WidgetPip: FC = ({ widgetId, room, viewingRoom, onStartMovin ); const onLeaveClick = useCallback( - (ev) => { + (ev: ButtonEvent) => { ev.preventDefault(); ev.stopPropagation(); diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 6f8fd9790b0..159bc9dbf12 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -424,6 +424,7 @@ export const UserOptionsSection: React.FC<{ member: Member; canInvite: boolean; isSpace?: boolean; + children?: ReactNode; }> = ({ member, canInvite, isSpace, children }) => { const cli = useContext(MatrixClientContext); @@ -1036,7 +1037,7 @@ const IgnoreToggleButton: React.FC<{ }, [cli, member.userId]); // Recheck also if we receive new accountData m.ignored_user_list const accountDataHandler = useCallback( - (ev) => { + (ev: MatrixEvent) => { if (ev.getType() === "m.ignored_user_list") { setIsIgnored(cli.isUserIgnored(member.userId)); } diff --git a/src/components/views/rooms/RoomHeader.tsx b/src/components/views/rooms/RoomHeader.tsx index 9cf63e474d6..11873ee129e 100644 --- a/src/components/views/rooms/RoomHeader.tsx +++ b/src/components/views/rooms/RoomHeader.tsx @@ -116,7 +116,10 @@ export default function RoomHeader({ const askToJoinEnabled = useFeatureEnabled("feature_ask_to_join"); - const videoClick = useCallback((ev) => videoCallClick(ev, callOptions[0]), [callOptions, videoCallClick]); + const videoClick = useCallback( + (ev: React.MouseEvent) => videoCallClick(ev, callOptions[0]), + [callOptions, videoCallClick], + ); const toggleCallButton = ( diff --git a/src/components/views/settings/UserProfileSettings.tsx b/src/components/views/settings/UserProfileSettings.tsx index a104aabb1d7..b793f27dd64 100644 --- a/src/components/views/settings/UserProfileSettings.tsx +++ b/src/components/views/settings/UserProfileSettings.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ChangeEvent, useCallback, useEffect, useMemo, useState } from "react"; +import React, { ChangeEvent, ReactNode, useCallback, useEffect, useMemo, useState } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { EditInPlace, Alert, ErrorMessage } from "@vector-im/compound-web"; import { Icon as PopOutIcon } from "@vector-im/compound-design-tokens/icons/pop-out.svg"; @@ -37,7 +37,7 @@ import Modal from "../../../Modal"; import defaultDispatcher from "../../../dispatcher/dispatcher"; import { Flex } from "../../utils/Flex"; -const SpinnerToast: React.FC = ({ children }) => ( +const SpinnerToast: React.FC<{ children?: ReactNode }> = ({ children }) => ( <> {children} diff --git a/src/components/views/spaces/QuickSettingsButton.tsx b/src/components/views/spaces/QuickSettingsButton.tsx index cf031e4ff16..a118a13bbc3 100644 --- a/src/components/views/spaces/QuickSettingsButton.tsx +++ b/src/components/views/spaces/QuickSettingsButton.tsx @@ -45,7 +45,7 @@ const QuickSettingsButton: React.FC<{ useSettingValue>("Spaces.enabledMetaSpaces"); const currentRoomId = SdkContextClass.instance.roomViewStore.getRoomId(); - const developerModeEnabled = useSettingValue("developerMode"); + const developerModeEnabled = useSettingValue("developerMode"); let contextMenu: JSX.Element | undefined; if (menuDisplayed && handle.current) { diff --git a/src/hooks/useAccountData.ts b/src/hooks/useAccountData.ts index d59910d5033..ad25f61465e 100644 --- a/src/hooks/useAccountData.ts +++ b/src/hooks/useAccountData.ts @@ -26,9 +26,9 @@ export const useAccountData = (cli: MatrixClient, eventType: strin const [value, setValue] = useState(() => tryGetContent(cli.getAccountData(eventType))); const handler = useCallback( - (event) => { + (event: MatrixEvent) => { if (event.getType() !== eventType) return; - setValue(event.getContent()); + setValue(event.getContent()); }, [eventType], ); diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx index 0a80be89f48..dd8a2452f22 100644 --- a/src/languageHandler.tsx +++ b/src/languageHandler.tsx @@ -52,13 +52,6 @@ counterpart.setSeparator(KEY_SEPARATOR); const FALLBACK_LOCALE = "en"; counterpart.setFallbackLocale(FALLBACK_LOCALE); -export interface ErrorOptions { - // Because we're mixing the subsitution variables and `cause` into the same object - // below, we want them to always explicitly say whether there is an underlying error - // or not to avoid typos of "cause" slipping through unnoticed. - cause: unknown | undefined; -} - /** * Used to rethrow an error with a user-friendly translatable message while maintaining * access to that original underlying error. Downstream consumers can display the @@ -78,13 +71,8 @@ export interface ErrorOptions { export class UserFriendlyError extends Error { public readonly translatedMessage: string; - public constructor(message: TranslationKey, substitutionVariablesAndCause?: IVariables & ErrorOptions) { - const errorOptions = { - cause: substitutionVariablesAndCause?.cause, - }; - // Prevent "Could not find /%\(cause\)s/g in x" logs to the console by removing it from the list - const substitutionVariables = { ...substitutionVariablesAndCause }; - delete substitutionVariables["cause"]; + public constructor(message: TranslationKey, cause?: Error | unknown, substitutionVariables?: IVariables) { + const errorOptions = { cause }; // Create the error with the English version of the message that we want to show // up in the logs @@ -445,7 +433,7 @@ export function replaceByRegexes(text: string, mapping: IVariables | Tags): stri } if (shouldWrapInSpan) { - return React.createElement("span", null, ...output); + return React.createElement("span", null, ...(output as Array)); } else { return output.join(""); } diff --git a/test/components/views/dialogs/InviteDialog-test.tsx b/test/components/views/dialogs/InviteDialog-test.tsx index 4e1dca41936..e55dbf050ab 100644 --- a/test/components/views/dialogs/InviteDialog-test.tsx +++ b/test/components/views/dialogs/InviteDialog-test.tsx @@ -429,7 +429,7 @@ describe("InviteDialog", () => { describe("when clicking »Start DM anyway«", () => { beforeEach(async () => { - await userEvent.click(screen.getByRole("button", { name: "Start DM anyway", exact: true })); + await userEvent.click(screen.getByRole("button", { name: "Start DM anyway" })); }); it("should start the DM", () => { diff --git a/test/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners-test.tsx b/test/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners-test.tsx index 779cca73334..e282c53a67b 100644 --- a/test/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners-test.tsx +++ b/test/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners-test.tsx @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { renderHook } from "@testing-library/react-hooks"; -import { act } from "@testing-library/react"; +import { renderHook, act } from "@testing-library/react"; import { usePlainTextListeners } from "../../../../../../src/components/views/rooms/wysiwyg_composer/hooks/usePlainTextListeners"; diff --git a/test/components/views/spaces/useUnreadThreadRooms-test.tsx b/test/components/views/spaces/useUnreadThreadRooms-test.tsx index d4dc04da96e..d7ff360fb3a 100644 --- a/test/components/views/spaces/useUnreadThreadRooms-test.tsx +++ b/test/components/views/spaces/useUnreadThreadRooms-test.tsx @@ -15,7 +15,6 @@ */ import React from "react"; -import { renderHook } from "@testing-library/react-hooks"; import { MatrixClient, MatrixEventEvent, @@ -23,7 +22,7 @@ import { PendingEventOrdering, Room, } from "matrix-js-sdk/src/matrix"; -import { act } from "@testing-library/react"; +import { renderHook, act } from "@testing-library/react"; import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; import { stubClient } from "../../../test-utils"; diff --git a/test/hooks/room/useRoomThreadNotifications-test.tsx b/test/hooks/room/useRoomThreadNotifications-test.tsx index 8946a1f2ec4..4424e4e5d24 100644 --- a/test/hooks/room/useRoomThreadNotifications-test.tsx +++ b/test/hooks/room/useRoomThreadNotifications-test.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { renderHook } from "@testing-library/react-hooks/dom"; +import { renderHook } from "@testing-library/react"; import { MatrixClient, NotificationCountType, Room } from "matrix-js-sdk/src/matrix"; import { useRoomThreadNotifications } from "../../../src/hooks/room/useRoomThreadNotifications"; diff --git a/test/hooks/useDebouncedCallback-test.tsx b/test/hooks/useDebouncedCallback-test.tsx index 2d3b32e7f5f..d8187a564f4 100644 --- a/test/hooks/useDebouncedCallback-test.tsx +++ b/test/hooks/useDebouncedCallback-test.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { renderHook } from "@testing-library/react-hooks"; +import { renderHook } from "@testing-library/react"; import { useDebouncedCallback } from "../../src/hooks/spotlight/useDebouncedCallback"; diff --git a/test/hooks/useLatestResult-test.tsx b/test/hooks/useLatestResult-test.tsx index a561a82c097..053a5f3126e 100644 --- a/test/hooks/useLatestResult-test.tsx +++ b/test/hooks/useLatestResult-test.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { renderHook, RenderHookResult } from "@testing-library/react-hooks/dom"; +import { renderHook, RenderHookResult } from "@testing-library/react"; import { useLatestResult } from "../../src/hooks/useLatestResult"; @@ -28,7 +28,7 @@ beforeEach(() => { }); function simulateRequest( - hookResult: RenderHookResult>["result"], + hookResult: RenderHookResult, typeof useLatestResult>["result"], { id, delayInMs, result }: { id: string; delayInMs: number; result: string }, ) { const [setQuery, setResult] = hookResult.current; diff --git a/test/hooks/useNotificationSettings-test.tsx b/test/hooks/useNotificationSettings-test.tsx index 5b0e4904265..48b3472eaa5 100644 --- a/test/hooks/useNotificationSettings-test.tsx +++ b/test/hooks/useNotificationSettings-test.tsx @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { act } from "@testing-library/react"; -import { renderHook } from "@testing-library/react-hooks/dom"; +import { act, renderHook, waitFor } from "@testing-library/react"; import { IPushRules, MatrixClient, PushRuleKind, RuleId } from "matrix-js-sdk/src/matrix"; import { useNotificationSettings } from "../../src/hooks/useNotificationSettings"; @@ -69,10 +68,9 @@ describe("useNotificationSettings", () => { it("correctly parses model", async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useNotificationSettings(cli)); + const { result } = renderHook(() => useNotificationSettings(cli)); expect(result.current.model).toEqual(null); - await waitForNextUpdate(); - expect(result.current.model).toEqual(expectedModel); + await waitFor(() => expect(result.current.model).toEqual(expectedModel)); expect(result.current.hasPendingChanges).toBeFalsy(); }); }); @@ -88,14 +86,12 @@ describe("useNotificationSettings", () => { const setPushRuleActions = jest.fn(cli.setPushRuleActions); cli.setPushRuleActions = setPushRuleActions; - const { result, waitForNextUpdate } = renderHook(() => useNotificationSettings(cli)); + const { result } = renderHook(() => useNotificationSettings(cli)); expect(result.current.model).toEqual(null); - await waitForNextUpdate(); - expect(result.current.model).toEqual(expectedModel); + await waitFor(() => expect(result.current.model).toEqual(expectedModel)); expect(result.current.hasPendingChanges).toBeFalsy(); await result.current.reconcile(DefaultNotificationSettings); - await waitForNextUpdate(); - expect(result.current.hasPendingChanges).toBeFalsy(); + await waitFor(() => expect(result.current.hasPendingChanges).toBeFalsy()); expect(addPushRule).toHaveBeenCalledTimes(0); expect(deletePushRule).toHaveBeenCalledTimes(9); expect(deletePushRule).toHaveBeenCalledWith("global", PushRuleKind.ContentSpecific, "justjann3"); diff --git a/test/hooks/useProfileInfo-test.tsx b/test/hooks/useProfileInfo-test.tsx index 63b78f78b17..3a895355e6d 100644 --- a/test/hooks/useProfileInfo-test.tsx +++ b/test/hooks/useProfileInfo-test.tsx @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { waitFor } from "@testing-library/react"; -import { renderHook, act } from "@testing-library/react-hooks/dom"; +import { waitFor, renderHook, act } from "@testing-library/react"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; import { useProfileInfo } from "../../src/hooks/useProfileInfo"; diff --git a/test/hooks/usePublicRoomDirectory-test.tsx b/test/hooks/usePublicRoomDirectory-test.tsx index fe814162085..e729c38cf5b 100644 --- a/test/hooks/usePublicRoomDirectory-test.tsx +++ b/test/hooks/usePublicRoomDirectory-test.tsx @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { waitFor } from "@testing-library/react"; -import { renderHook, act } from "@testing-library/react-hooks/dom"; +import { waitFor, renderHook, act } from "@testing-library/react"; import { IRoomDirectoryOptions, MatrixClient } from "matrix-js-sdk/src/matrix"; import { usePublicRoomDirectory } from "../../src/hooks/usePublicRoomDirectory"; diff --git a/test/hooks/useRoomMembers-test.tsx b/test/hooks/useRoomMembers-test.tsx index 1db551acdad..c3709f54280 100644 --- a/test/hooks/useRoomMembers-test.tsx +++ b/test/hooks/useRoomMembers-test.tsx @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { waitFor } from "@testing-library/react"; -import { renderHook, act } from "@testing-library/react-hooks/dom"; +import { waitFor, renderHook, act } from "@testing-library/react"; import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; diff --git a/test/hooks/useSlidingSyncRoomSearch-test.tsx b/test/hooks/useSlidingSyncRoomSearch-test.tsx index 0b21b585759..108afee3db9 100644 --- a/test/hooks/useSlidingSyncRoomSearch-test.tsx +++ b/test/hooks/useSlidingSyncRoomSearch-test.tsx @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { waitFor } from "@testing-library/react"; -import { renderHook, act } from "@testing-library/react-hooks/dom"; +import { waitFor, renderHook, act } from "@testing-library/react"; import { mocked } from "jest-mock"; import { SlidingSync } from "matrix-js-sdk/src/sliding-sync"; import { Room } from "matrix-js-sdk/src/matrix"; diff --git a/test/hooks/useUnreadNotifications-test.ts b/test/hooks/useUnreadNotifications-test.ts index 5a71bee9a57..570506a28e9 100644 --- a/test/hooks/useUnreadNotifications-test.ts +++ b/test/hooks/useUnreadNotifications-test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { renderHook } from "@testing-library/react-hooks"; +import { renderHook } from "@testing-library/react"; import { EventStatus, NotificationCountType, PendingEventOrdering, Room } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; diff --git a/test/hooks/useUserDirectory-test.tsx b/test/hooks/useUserDirectory-test.tsx index 7bda5cfe0b3..72da549d0f7 100644 --- a/test/hooks/useUserDirectory-test.tsx +++ b/test/hooks/useUserDirectory-test.tsx @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { waitFor } from "@testing-library/react"; -import { renderHook, act } from "@testing-library/react-hooks/dom"; +import { waitFor, renderHook, act } from "@testing-library/react"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; import { useUserDirectory } from "../../src/hooks/useUserDirectory"; diff --git a/test/hooks/useUserOnboardingTasks-test.tsx b/test/hooks/useUserOnboardingTasks-test.tsx index 26a2ba4b756..61b2f465d32 100644 --- a/test/hooks/useUserOnboardingTasks-test.tsx +++ b/test/hooks/useUserOnboardingTasks-test.tsx @@ -15,8 +15,7 @@ limitations under the License. */ import React from "react"; -import { renderHook } from "@testing-library/react-hooks"; -import { waitFor } from "@testing-library/react"; +import { renderHook, waitFor } from "@testing-library/react"; import { useUserOnboardingTasks } from "../../src/hooks/useUserOnboardingTasks"; import { useUserOnboardingContext } from "../../src/hooks/useUserOnboardingContext"; diff --git a/test/hooks/useWindowWidth-test.ts b/test/hooks/useWindowWidth-test.ts index bde91c2acb7..2a7f3052833 100644 --- a/test/hooks/useWindowWidth-test.ts +++ b/test/hooks/useWindowWidth-test.ts @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { renderHook } from "@testing-library/react-hooks"; -import { act } from "@testing-library/react"; +import { renderHook, act } from "@testing-library/react"; import UIStore, { UI_EVENTS } from "../../src/stores/UIStore"; import { useWindowWidth } from "../../src/hooks/useWindowWidth"; diff --git a/test/languageHandler-test.tsx b/test/languageHandler-test.tsx index a9ad673a706..aeecaa0e187 100644 --- a/test/languageHandler-test.tsx +++ b/test/languageHandler-test.tsx @@ -32,6 +32,8 @@ import { TranslatedString, UserFriendlyError, TranslationKey, + IVariables, + Tags, } from "../src/languageHandler"; import { stubClient } from "./test-utils"; import { setupLanguageMock } from "./setup/setupLanguage"; @@ -214,13 +216,7 @@ describe("languageHandler JSX", function () { const plurals = "common|and_n_others"; const variableSub = "slash_command|ignore_dialog_description"; - type TestCase = [ - string, - TranslationKey, - Record, - Record | undefined, - TranslatedString, - ]; + type TestCase = [string, TranslationKey, IVariables, Tags | undefined, TranslatedString]; const testCasesEn: TestCase[] = [ // description of the test case, translationString, variables, tags, expected result ["translates a basic string", basicString, {}, undefined, "Rooms"], diff --git a/test/modules/ProxiedModuleApi-test.tsx b/test/modules/ProxiedModuleApi-test.tsx index bec6215232d..1e98e69508d 100644 --- a/test/modules/ProxiedModuleApi-test.tsx +++ b/test/modules/ProxiedModuleApi-test.tsx @@ -118,6 +118,9 @@ describe("ProxiedApiModule", () => { describe("openDialog", () => { it("should open dialog with a custom title and default options", async () => { class MyDialogContent extends DialogContent { + public constructor(props: DialogProps) { + super(props); + } trySubmit = async () => ({ result: true }); render = () =>

This is my example content.

; } @@ -147,6 +150,9 @@ describe("ProxiedApiModule", () => { it("should open dialog with custom options", async () => { class MyDialogContent extends DialogContent { + public constructor(props: DialogProps) { + super(props); + } trySubmit = async () => ({ result: true }); render = () =>

This is my example content.

; } @@ -178,6 +184,9 @@ describe("ProxiedApiModule", () => { it("should update the options from the opened dialog", async () => { class MyDialogContent extends DialogContent { + public constructor(props: DialogProps) { + super(props); + } trySubmit = async () => ({ result: true }); render = () => { const onClick = () => { @@ -231,6 +240,9 @@ describe("ProxiedApiModule", () => { it("should cancel the dialog from within the dialog", async () => { class MyDialogContent extends DialogContent { + public constructor(props: DialogProps) { + super(props); + } trySubmit = async () => ({ result: true }); render = () => (
+