diff --git a/code_style.md b/code_style.md index 2481c22e1e..6e7289d22e 100644 --- a/code_style.md +++ b/code_style.md @@ -79,7 +79,7 @@ Unless otherwise specified, the following applies to all code: 11. If a variable is not receiving a value on declaration, its type must be defined. ```typescript - let errorMessage: Optional; + let errorMessage: string; ``` 12. Objects can use shorthand declarations, including mixing of types. diff --git a/package.json b/package.json index 55e9b23186..390d707a51 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,6 @@ "lodash": "^4.17.21", "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", - "matrix-events-sdk": "0.0.1", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^1.14.0", "memoize-one": "^6.0.0", diff --git a/src/DateUtils.ts b/src/DateUtils.ts index e3c7c348fa..82e7bfa880 100644 --- a/src/DateUtils.ts +++ b/src/DateUtils.ts @@ -8,8 +8,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import { type Optional } from "matrix-events-sdk"; - import { _t, getUserLanguage } from "./languageHandler"; import { getUserTimezone } from "./TimezoneHandler"; @@ -219,7 +217,7 @@ function withinCurrentYear(prevDate: Date, nextDate: Date): boolean { return prevDate.getFullYear() === nextDate.getFullYear(); } -export function wantsDateSeparator(prevEventDate: Optional, nextEventDate: Optional): boolean { +export function wantsDateSeparator(prevEventDate: Date | undefined, nextEventDate: Date | undefined): boolean { if (!nextEventDate || !prevEventDate) { return false; } diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx index 027a51ea72..5112e3f7ce 100644 --- a/src/HtmlUtils.tsx +++ b/src/HtmlUtils.tsx @@ -15,7 +15,6 @@ import classNames from "classnames"; import katex from "katex"; import { decode } from "html-entities"; import { type IContent } from "matrix-js-sdk/src/matrix"; -import { type Optional } from "matrix-events-sdk"; import escapeHtml from "escape-html"; import { getEmojiFromUnicode } from "@matrix-org/emojibase-bindings"; @@ -301,7 +300,7 @@ export interface EventRenderOpts { linkify?: boolean; } -function analyseEvent(content: IContent, highlights: Optional, opts: EventRenderOpts = {}): EventAnalysis { +function analyseEvent(content: IContent, highlights?: string[], opts: EventRenderOpts = {}): EventAnalysis { let sanitizeParams = sanitizeHtmlParams; if (opts.forComposerQuote) { sanitizeParams = composerSanitizeHtmlParams; @@ -413,11 +412,7 @@ interface BodyToNodeReturn { className: string; } -export function bodyToNode( - content: IContent, - highlights: Optional, - opts: EventRenderOpts = {}, -): BodyToNodeReturn { +export function bodyToNode(content: IContent, highlights?: string[], opts: EventRenderOpts = {}): BodyToNodeReturn { const eventInfo = analyseEvent(content, highlights, opts); let emojiBody = false; @@ -478,7 +473,7 @@ export function bodyToNode( * opts.forComposerQuote: optional param to lessen the url rewriting done by sanitization, for quoting into composer * opts.ref: React ref to attach to any React components returned (not compatible with opts.returnString) */ -export function bodyToHtml(content: IContent, highlights: Optional, opts: EventRenderOpts = {}): string { +export function bodyToHtml(content: IContent, highlights?: string[], opts: EventRenderOpts = {}): string { const eventInfo = analyseEvent(content, highlights, opts); let formattedBody = eventInfo.safeBody; diff --git a/src/SdkConfig.ts b/src/SdkConfig.ts index 9576aa209e..71ac6736c9 100644 --- a/src/SdkConfig.ts +++ b/src/SdkConfig.ts @@ -7,7 +7,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import { type Optional } from "matrix-events-sdk"; import { mergeWith } from "lodash"; import { SnakedObject } from "./utils/SnakedObject"; @@ -90,7 +89,7 @@ function mergeConfig( type ObjectType = IConfigOptions[K] extends object ? SnakedObject> - : Optional>>; + : SnakedObject> | null | undefined; export default class SdkConfig { private static instance: DeepReadonly; diff --git a/src/components/structures/PipContainer.tsx b/src/components/structures/PipContainer.tsx index 18e8c526db..9dbb6daef7 100644 --- a/src/components/structures/PipContainer.tsx +++ b/src/components/structures/PipContainer.tsx @@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details. import React, { type RefObject, type ReactNode, useRef } from "react"; import { CallEvent, CallState, type MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import { logger } from "matrix-js-sdk/src/logger"; -import { type Optional } from "matrix-events-sdk"; import LegacyCallView from "../views/voip/LegacyCallView"; import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../LegacyCallHandler"; @@ -57,7 +56,7 @@ interface IState { // (which should be a single element) of other calls. // The primary will be the one not on hold, or an arbitrary one // if they're all on hold) -function getPrimarySecondaryCallsForPip(roomId: Optional): [MatrixCall | null, MatrixCall[]] { +function getPrimarySecondaryCallsForPip(roomId: string | null): [MatrixCall | null, MatrixCall[]] { if (!roomId) return [null, []]; const calls = LegacyCallHandler.instance.getAllActiveCallsForPip(roomId); diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index 8937e7960e..0657ab64c0 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -6,7 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import { type Optional } from "matrix-events-sdk"; import React, { useContext, useEffect, useRef, useState } from "react"; import { type EventTimelineSet, type Room, Thread } from "matrix-js-sdk/src/matrix"; import { IconButton, Tooltip } from "@vector-im/compound-web"; @@ -163,7 +162,7 @@ const ThreadPanel: React.FC = ({ roomId, onClose, permalinkCreator }) => const [room, setRoom] = useState(null); const [narrow, setNarrow] = useState(false); - const timelineSet: Optional = + const timelineSet: EventTimelineSet | undefined = filterOption === ThreadFilterType.My ? room?.threadsTimelineSets[1] : room?.threadsTimelineSets[0]; const hasThreads = Boolean(room?.threadsTimelineSets?.[0]?.getLiveTimeline()?.getEvents()?.length); diff --git a/src/components/structures/UploadBar.tsx b/src/components/structures/UploadBar.tsx index a28ff2ba44..6dbbd4997d 100644 --- a/src/components/structures/UploadBar.tsx +++ b/src/components/structures/UploadBar.tsx @@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details. import React from "react"; import { type Room, type IEventRelation } from "matrix-js-sdk/src/matrix"; -import { type Optional } from "matrix-events-sdk"; import ContentMessages from "../../ContentMessages"; import dis from "../../dispatcher/dispatcher"; @@ -45,7 +44,7 @@ function isUploadPayload(payload: ActionPayload): payload is UploadPayload { } export default class UploadBar extends React.PureComponent { - private dispatcherRef: Optional; + private dispatcherRef?: string; private unmounted = false; public constructor(props: IProps) { diff --git a/src/components/structures/auth/SoftLogout.tsx b/src/components/structures/auth/SoftLogout.tsx index 34fabe46c7..a307078658 100644 --- a/src/components/structures/auth/SoftLogout.tsx +++ b/src/components/structures/auth/SoftLogout.tsx @@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details. import React, { type JSX, type ChangeEvent, type SyntheticEvent } from "react"; import { logger } from "matrix-js-sdk/src/logger"; -import { type Optional } from "matrix-events-sdk"; import { type LoginFlow, MatrixError, SSOAction, type SSOFlow } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../languageHandler"; @@ -217,7 +216,7 @@ export default class SoftLogout extends React.Component { }); } - private renderPasswordForm(introText: Optional): JSX.Element { + private renderPasswordForm(introText?: string): JSX.Element { let error: JSX.Element | undefined; if (this.state.errorText) { error = {this.state.errorText}; @@ -244,7 +243,7 @@ export default class SoftLogout extends React.Component { ); } - private renderSsoForm(introText: Optional): JSX.Element { + private renderSsoForm(introText?: string): JSX.Element { const loginType = this.state.loginView === LoginView.CAS ? "cas" : "sso"; const flow = this.state.flows.find((flow) => flow.type === "m.login." + loginType) as SSOFlow; @@ -284,14 +283,14 @@ export default class SoftLogout extends React.Component { return ( <>

{_t("auth|soft_logout_intro_sso")}

- {this.renderSsoForm(null)} + {this.renderSsoForm()}

{_t("auth|sso_or_username_password", { ssoButtons: "", usernamePassword: "", }).trim()}

- {this.renderPasswordForm(null)} + {this.renderPasswordForm()} ); } diff --git a/src/components/viewmodels/right_panel/RoomSummaryCardTopicViewModel.tsx b/src/components/viewmodels/right_panel/RoomSummaryCardTopicViewModel.tsx index 10cbc5b568..fd98a76541 100644 --- a/src/components/viewmodels/right_panel/RoomSummaryCardTopicViewModel.tsx +++ b/src/components/viewmodels/right_panel/RoomSummaryCardTopicViewModel.tsx @@ -6,7 +6,6 @@ Please see LICENSE files in the repository root for full details. import { type SyntheticEvent, useState } from "react"; import { EventType, type Room, type ContentHelpers } from "matrix-js-sdk/src/matrix"; -import { type Optional } from "matrix-events-sdk"; import { useRoomState } from "../../../hooks/useRoomState"; import defaultDispatcher from "../../../dispatcher/dispatcher"; @@ -17,7 +16,7 @@ export interface RoomTopicState { /** * The topic of the room, the value is taken from the room state */ - topic: Optional; + topic: ContentHelpers.TopicState | null; /** * Whether the topic is expanded or not */ diff --git a/src/components/viewmodels/roomlist/useStickyRoomList.tsx b/src/components/viewmodels/roomlist/useStickyRoomList.tsx index ad8a72b8b0..355e09a292 100644 --- a/src/components/viewmodels/roomlist/useStickyRoomList.tsx +++ b/src/components/viewmodels/roomlist/useStickyRoomList.tsx @@ -12,11 +12,10 @@ import { useDispatcher } from "../../../hooks/useDispatcher"; import dispatcher from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; import type { Room } from "matrix-js-sdk/src/matrix"; -import type { Optional } from "matrix-events-sdk"; import SpaceStore from "../../../stores/spaces/SpaceStore"; import { type RoomsResult } from "../../../stores/room-list-v3/RoomListStoreV3"; -function getIndexByRoomId(rooms: Room[], roomId: Optional): number | undefined { +function getIndexByRoomId(rooms: Room[], roomId: string): number | undefined { const index = rooms.findIndex((room) => room.roomId === roomId); return index === -1 ? undefined : index; } @@ -88,7 +87,7 @@ export interface StickyRoomListResult { */ export function useStickyRoomList(roomsResult: RoomsResult): StickyRoomListResult { const [listState, setListState] = useState({ - activeIndex: getIndexByRoomId(roomsResult.rooms, SdkContextClass.instance.roomViewStore.getRoomId()), + activeIndex: getIndexByRoomId(roomsResult.rooms, SdkContextClass.instance.roomViewStore.getRoomId()!), roomsResult: roomsResult, }); @@ -98,7 +97,7 @@ export function useStickyRoomList(roomsResult: RoomsResult): StickyRoomListResul (newRoomId: string | null, isRoomChange: boolean = false) => { setListState((current) => { const activeRoomId = newRoomId ?? SdkContextClass.instance.roomViewStore.getRoomId(); - const newActiveIndex = getIndexByRoomId(roomsResult.rooms, activeRoomId); + const newActiveIndex = getIndexByRoomId(roomsResult.rooms, activeRoomId!); const oldIndex = current.activeIndex; const { newIndex, newRooms } = getRoomsWithStickyRoom( roomsResult.rooms, diff --git a/src/components/views/context_menus/MessageContextMenu.tsx b/src/components/views/context_menus/MessageContextMenu.tsx index 39139be0db..6d13f1b2e8 100644 --- a/src/components/views/context_menus/MessageContextMenu.tsx +++ b/src/components/views/context_menus/MessageContextMenu.tsx @@ -255,7 +255,7 @@ export default class MessageContextMenu extends React.Component dis.dispatch({ action: Action.OpenForwardDialog, event: forwardableEvent, - permalinkCreator: this.props.permalinkCreator, + permalinkCreator: this.props.permalinkCreator ?? null, }); this.closeMenu(); }; diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index d4e617a1f4..80cda285c8 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -16,7 +16,6 @@ import { EventType, THREAD_RELATION_TYPE, } from "matrix-js-sdk/src/matrix"; -import { type Optional } from "matrix-events-sdk"; import { Tooltip } from "@vector-im/compound-web"; import { logger } from "matrix-js-sdk/src/logger"; import { LockOffIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; @@ -115,7 +114,7 @@ export class MessageComposer extends React.Component { private ref = createRef(); private instanceId: number; - private _voiceRecording: Optional; + private _voiceRecording?: VoiceMessageRecording; public static contextType = RoomContext; declare public context: React.ContextType; @@ -202,11 +201,11 @@ export class MessageComposer extends React.Component { localStorage.removeItem(this.editorStateKey); } - private get voiceRecording(): Optional { + private get voiceRecording(): VoiceMessageRecording | undefined { return this._voiceRecording; } - private set voiceRecording(rec: Optional) { + private set voiceRecording(rec: VoiceMessageRecording | undefined) { if (this._voiceRecording) { this._voiceRecording.off(RecordingState.Started, this.onRecordingStarted); this._voiceRecording.off(RecordingState.EndingSoon, this.onRecordingEndingSoon); @@ -328,7 +327,7 @@ export class MessageComposer extends React.Component { window.removeEventListener("beforeunload", this.saveWysiwygEditorState); this.saveWysiwygEditorState(); // clean up our listeners by setting our cached recording to falsy (see internal setter) - this.voiceRecording = null; + this.voiceRecording = undefined; } private onTombstoneClick = (ev: ButtonEvent): void => { diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index 9c13f1c872..4184eec110 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details. import React, { type ReactNode } from "react"; import { type Room, type IEventRelation, type MatrixEvent } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; -import { type Optional } from "matrix-events-sdk"; import { _t } from "../../../languageHandler"; import { RecordingState } from "../../../audio/VoiceRecording"; @@ -216,7 +215,7 @@ export default class VoiceRecordComposerTile extends React.PureComponent): void { + private bindNewRecorder(recorder: VoiceMessageRecording | null): void { if (this.state.recorder) { this.state.recorder.off(UPDATE_EVENT, this.onRecordingUpdate); } diff --git a/src/customisations/Media.ts b/src/customisations/Media.ts index 1763ade3a8..20b6c816db 100644 --- a/src/customisations/Media.ts +++ b/src/customisations/Media.ts @@ -8,7 +8,6 @@ import { type MatrixClient, parseErrorResponse, type ResizeMethod } from "matrix-js-sdk/src/matrix"; import { type MediaEventContent } from "matrix-js-sdk/src/types"; -import { type Optional } from "matrix-events-sdk"; import type { MediaCustomisations, Media } from "@element-hq/element-web-module-api"; import { MatrixClientPeg } from "../MatrixClientPeg"; @@ -58,7 +57,7 @@ class MediaImplementation implements Media { * The MXC URI of the thumbnail media, if a thumbnail is recorded. Null/undefined * otherwise. */ - public get thumbnailMxc(): Optional { + public get thumbnailMxc(): string | undefined { return this.prepared.thumbnail?.mxc; } diff --git a/src/dispatcher/payloads/ActiveRoomChangedPayload.ts b/src/dispatcher/payloads/ActiveRoomChangedPayload.ts index 68d55c3b52..5995d42d70 100644 --- a/src/dispatcher/payloads/ActiveRoomChangedPayload.ts +++ b/src/dispatcher/payloads/ActiveRoomChangedPayload.ts @@ -6,14 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import { type Optional } from "matrix-events-sdk"; - import { type Action } from "../actions"; import { type ActionPayload } from "../payloads"; export interface ActiveRoomChangedPayload extends ActionPayload { action: Action.ActiveRoomChanged; - oldRoomId: Optional; - newRoomId: Optional; + oldRoomId: string | null; + newRoomId: string | null; } diff --git a/src/dispatcher/payloads/OpenForwardDialogPayload.ts b/src/dispatcher/payloads/OpenForwardDialogPayload.ts index a883a8bdc1..2f8688061c 100644 --- a/src/dispatcher/payloads/OpenForwardDialogPayload.ts +++ b/src/dispatcher/payloads/OpenForwardDialogPayload.ts @@ -7,7 +7,6 @@ Please see LICENSE files in the repository root for full details. */ import { type MatrixEvent } from "matrix-js-sdk/src/matrix"; -import { type Optional } from "matrix-events-sdk"; import { type Action } from "../actions"; import { type ActionPayload } from "../payloads"; @@ -17,5 +16,5 @@ export interface OpenForwardDialogPayload extends ActionPayload { action: Action.OpenForwardDialog; event: MatrixEvent; - permalinkCreator: Optional; + permalinkCreator: RoomPermalinkCreator | null; } diff --git a/src/dispatcher/payloads/OpenInviteDialogPayload.ts b/src/dispatcher/payloads/OpenInviteDialogPayload.ts index 77973c239f..0e94465dc5 100644 --- a/src/dispatcher/payloads/OpenInviteDialogPayload.ts +++ b/src/dispatcher/payloads/OpenInviteDialogPayload.ts @@ -6,7 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import { type Optional } from "matrix-events-sdk"; import { type MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import { type ActionPayload } from "../payloads"; @@ -17,7 +16,7 @@ export interface OpenInviteDialogPayload extends ActionPayload { action: Action.OpenInviteDialog; kind: InviteKind; - onFinishedCallback: Optional<(results: boolean[]) => void>; + onFinishedCallback?: (results: boolean[]) => void; call?: MatrixCall; roomId?: string; diff --git a/src/events/EventTileFactory.tsx b/src/events/EventTileFactory.tsx index 316f62fa94..e364723384 100644 --- a/src/events/EventTileFactory.tsx +++ b/src/events/EventTileFactory.tsx @@ -17,7 +17,6 @@ import { M_POLL_END, M_POLL_START, } from "matrix-js-sdk/src/matrix"; -import { type Optional } from "matrix-events-sdk"; import { TextualEventView } from "@element-hq/web-shared-components"; import SettingsStore from "../settings/SettingsStore"; @@ -154,14 +153,14 @@ const SINGULAR_STATE_EVENTS = new Set([ * @param cli The matrix client to reference when needed. * @param showHiddenEvents Whether hidden events should be shown. * @param asHiddenEv When true, treat the event as always hidden. - * @returns The factory, or falsy if not possible. + * @returns The factory, or undefined if not possible. */ export function pickFactory( mxEvent: MatrixEvent, cli: MatrixClient, showHiddenEvents: boolean, asHiddenEv?: boolean, -): Optional { +): Factory | undefined { const evType = mxEvent.getType(); // cache this to reduce call stack execution hits // Note: we avoid calling SettingsStore unless absolutely necessary - this code is on the critical path. @@ -170,7 +169,7 @@ export function pickFactory( return JSONEventFactory; } - const noEventFactoryFactory: () => Optional = () => (showHiddenEvents ? JSONEventFactory : undefined); // just don't render things that we shouldn't render + const noEventFactoryFactory: () => Factory | undefined = () => (showHiddenEvents ? JSONEventFactory : undefined); // just don't render things that we shouldn't render // We run all the event type checks first as they might override the factory entirely. @@ -249,15 +248,14 @@ export function pickFactory( * Render an event as a tile * @param renderType The render type. Used to inform properties given to the eventual component. * @param props The properties to provide to the eventual component. - * @param showHiddenEvents Whether hidden events should be shown. * @param cli Optional client instance to use, otherwise the default MatrixClientPeg will be used. - * @returns The tile as JSX, or falsy if unable to render. + * @returns The tile as JSX, or null if unable to render. */ export function renderTile( renderType: TimelineRenderingType, props: EventTileTypeProps, cli?: MatrixClient, -): Optional { +): JSX.Element | null { cli = cli ?? MatrixClientPeg.safeGet(); // because param defaults don't do the correct thing const factory = pickFactory(props.mxEvent, cli, props.showHiddenEvents); @@ -352,7 +350,7 @@ export function renderReplyTile( props: EventTileTypeProps, showHiddenEvents: boolean, cli?: MatrixClient, -): Optional { +): JSX.Element | null { cli = cli ?? MatrixClientPeg.safeGet(); // because param defaults don't do the correct thing const factory = pickFactory(props.mxEvent, cli, showHiddenEvents); diff --git a/src/hooks/room/useTopic.ts b/src/hooks/room/useTopic.ts index e254e7a4ea..b38c2e9421 100644 --- a/src/hooks/room/useTopic.ts +++ b/src/hooks/room/useTopic.ts @@ -15,11 +15,10 @@ import { ContentHelpers, type MRoomTopicEventContent, } from "matrix-js-sdk/src/matrix"; -import { type Optional } from "matrix-events-sdk"; import { useTypedEventEmitter } from "../useEventEmitter"; -export const getTopic = (room?: Room): Optional => { +export const getTopic = (room?: Room): ContentHelpers.TopicState | null => { const content = room?.currentState?.getStateEvents(EventType.RoomTopic, "")?.getContent(); return !!content ? ContentHelpers.parseTopicContent(content) : null; }; @@ -29,7 +28,7 @@ export const getTopic = (room?: Room): Optional => { * @param room * @returns the raw text and an html parsion version of the room topic */ -export function useTopic(room?: Room): Optional { +export function useTopic(room?: Room): ContentHelpers.TopicState | null { const [topic, setTopic] = useState(getTopic(room)); useTypedEventEmitter(room?.currentState, RoomStateEvent.Events, (ev: MatrixEvent) => { if (ev.getType() !== EventType.RoomTopic) return; diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx index da31ab1811..abd26dda01 100644 --- a/src/languageHandler.tsx +++ b/src/languageHandler.tsx @@ -6,7 +6,6 @@ */ import { logger } from "matrix-js-sdk/src/logger"; -import { type Optional } from "matrix-events-sdk"; import { MapWithDefault } from "matrix-js-sdk/src/utils"; import { type TranslationStringsObject } from "@matrix-org/react-sdk-module-api"; import _ from "lodash"; @@ -236,7 +235,7 @@ async function getLanguage(langPath: string): Promise { return res.json(); } -let cachedCustomTranslations: Optional = null; +let cachedCustomTranslations: TranslationStringsObject | undefined; let cachedCustomTranslationsExpire = 0; // zero to trigger expiration right away // This awkward class exists so the test runner can get at the function. It is @@ -285,7 +284,7 @@ export async function registerCustomTranslations({ if (!lookupUrl) return; // easy - nothing to do try { - let json: Optional; + let json: TranslationStringsObject | undefined; if (testOnlyIgnoreCustomTranslationsCache || Date.now() >= cachedCustomTranslationsExpire) { json = CustomTranslationOptions.lookupFn ? CustomTranslationOptions.lookupFn(lookupUrl) diff --git a/src/modules/ProxiedModuleApi.ts b/src/modules/ProxiedModuleApi.ts index 86db1a9e35..f36b81dec2 100644 --- a/src/modules/ProxiedModuleApi.ts +++ b/src/modules/ProxiedModuleApi.ts @@ -11,7 +11,6 @@ import { type TranslationStringsObject, type PlainSubstitution, } from "@matrix-org/react-sdk-module-api/lib/types/translations"; -import { type Optional } from "matrix-events-sdk"; import { type DialogContent, type DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent"; import { type AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/AccountAuthInfo"; import * as Matrix from "matrix-js-sdk/src/matrix"; @@ -40,7 +39,7 @@ import type { ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload.ts" * to be assigned to a single module. */ export class ProxiedModuleApi implements ModuleApi { - private cachedTranslations: Optional; + private cachedTranslations?: TranslationStringsObject; private overrideLoginResolve?: () => void; @@ -57,7 +56,7 @@ export class ProxiedModuleApi implements ModuleApi { /** * All custom translations used by the associated module. */ - public get translations(): Optional { + public get translations(): TranslationStringsObject | undefined { return this.cachedTranslations; } diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index 489dd775f8..faf54f1a8f 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -15,7 +15,6 @@ import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { type ViewRoom as ViewRoomEvent } from "@matrix-org/analytics-events/types/typescript/ViewRoom"; import { type JoinedRoom as JoinedRoomEvent } from "@matrix-org/analytics-events/types/typescript/JoinedRoom"; -import { type Optional } from "matrix-events-sdk"; import EventEmitter from "events"; import { RoomViewLifecycle, @@ -664,16 +663,16 @@ export class RoomViewStore extends EventEmitter { } // The room ID of the room currently being viewed - public getRoomId(): Optional { + public getRoomId(): string | null { return this.state.roomId; } - public getThreadId(): Optional { + public getThreadId(): string | null { return this.state.threadId; } // The event to scroll to when the room is first viewed - public getInitialEventId(): Optional { + public getInitialEventId(): string | null { return this.state.initialEventId; } @@ -688,7 +687,7 @@ export class RoomViewStore extends EventEmitter { } // The room alias of the room (or null if not originally specified in view_room) - public getRoomAlias(): Optional { + public getRoomAlias(): string | null { return this.state.roomAlias; } @@ -698,7 +697,7 @@ export class RoomViewStore extends EventEmitter { } // Any error that has occurred during loading - public getRoomLoadError(): Optional { + public getRoomLoadError(): MatrixError | null { return this.state.roomLoadError; } @@ -730,7 +729,7 @@ export class RoomViewStore extends EventEmitter { } // Any error that has occurred during joining - public getJoinError(): Optional { + public getJoinError(): Error | null { return this.state.joinError; } diff --git a/src/stores/VoiceRecordingStore.ts b/src/stores/VoiceRecordingStore.ts index 0715394996..20ad092484 100644 --- a/src/stores/VoiceRecordingStore.ts +++ b/src/stores/VoiceRecordingStore.ts @@ -6,7 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import { type Optional } from "matrix-events-sdk"; import { type Room, type IEventRelation, RelationType } from "matrix-js-sdk/src/matrix"; import { AsyncStoreWithClient } from "./AsyncStoreWithClient"; @@ -17,7 +16,7 @@ import { createVoiceMessageRecording, type VoiceMessageRecording } from "../audi const SEPARATOR = "|"; interface IState { - [voiceRecordingId: string]: Optional; + [voiceRecordingId: string]: VoiceMessageRecording; } export class VoiceRecordingStore extends AsyncStoreWithClient { @@ -51,9 +50,9 @@ export class VoiceRecordingStore extends AsyncStoreWithClient { /** * Gets the active recording instance, if any. * @param {string} voiceRecordingId The room ID (with optionally the thread ID if in one) to get the recording in. - * @returns {Optional} The recording, if any. + * @returns {VoiceRecording?} The recording, if any. */ - public getActiveRecording(voiceRecordingId: string): Optional { + public getActiveRecording(voiceRecordingId: string): VoiceMessageRecording | undefined { return this.state[voiceRecordingId]; } diff --git a/src/stores/right-panel/RightPanelStore.ts b/src/stores/right-panel/RightPanelStore.ts index b3f8d93460..f58559a66e 100644 --- a/src/stores/right-panel/RightPanelStore.ts +++ b/src/stores/right-panel/RightPanelStore.ts @@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details. import { logger } from "matrix-js-sdk/src/logger"; import { CryptoEvent } from "matrix-js-sdk/src/crypto-api"; -import { type Optional } from "matrix-events-sdk"; import defaultDispatcher from "../../dispatcher/dispatcher"; import { pendingVerificationRequestForUser } from "../../verification"; @@ -58,7 +57,7 @@ export default class RightPanelStore extends ReadyWatchingStore { private global?: IRightPanelForRoom; private byRoom: { [roomId: string]: IRightPanelForRoom } = {}; - private viewedRoomId: Optional; + private viewedRoomId: string | null = null; private constructor() { super(defaultDispatcher); @@ -419,7 +418,7 @@ export default class RightPanelStore extends ReadyWatchingStore { } }; - private handleViewedRoomChange(oldRoomId: Optional, newRoomId: Optional): void { + private handleViewedRoomChange(oldRoomId: string | null, newRoomId: string | null): void { if (!this.mxClient) return; // not ready, onReady will handle the first room this.viewedRoomId = newRoomId; // load values from byRoomCache with the viewedRoomId. diff --git a/src/stores/widgets/WidgetLayoutStore.ts b/src/stores/widgets/WidgetLayoutStore.ts index 293dc06c03..345db83cfc 100644 --- a/src/stores/widgets/WidgetLayoutStore.ts +++ b/src/stores/widgets/WidgetLayoutStore.ts @@ -7,7 +7,6 @@ */ import { type Room, RoomStateEvent, type MatrixEvent } from "matrix-js-sdk/src/matrix"; -import { type Optional } from "matrix-events-sdk"; import { MapWithDefault, recursiveMapToObject } from "matrix-js-sdk/src/utils"; import { type IWidget } from "matrix-widget-api"; import { clamp, defaultNumber, sum } from "@element-hq/web-shared-components"; @@ -316,7 +315,7 @@ export class WidgetLayoutStore extends ReadyWatchingStore { } } - public getContainerWidgets(room: Optional, container: Container): IWidget[] { + public getContainerWidgets(room: Room | null, container: Container): IWidget[] { return (room && this.byRoom.get(room.roomId)?.get(container)?.ordered) || []; } diff --git a/src/utils/DMRoomMap.ts b/src/utils/DMRoomMap.ts index df1cc2d364..989eea09d0 100644 --- a/src/utils/DMRoomMap.ts +++ b/src/utils/DMRoomMap.ts @@ -10,7 +10,6 @@ import { uniq } from "lodash"; import { type Room, type MatrixEvent, EventType, ClientEvent, type MatrixClient } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; -import { type Optional } from "matrix-events-sdk"; import { filterValidMDirect } from "./dm/filterValidMDirect"; @@ -170,7 +169,7 @@ export default class DMRoomMap { return joinedRooms[0]; } - public getUserIdForRoomId(roomId: string): Optional { + public getUserIdForRoomId(roomId: string): string | undefined { if (this.roomToUser == null) { // we lazily populate roomToUser so you can use // this class just to call getDMRoomsForUserId diff --git a/src/utils/MessageDiffUtils.tsx b/src/utils/MessageDiffUtils.tsx index addb8265be..53d12b2513 100644 --- a/src/utils/MessageDiffUtils.tsx +++ b/src/utils/MessageDiffUtils.tsx @@ -27,7 +27,7 @@ function getSanitizedHtmlBody(content: IContent): string { stripReplyFallback: true, }; if (content.format === "org.matrix.custom.html") { - return bodyToHtml(content, null, opts); + return bodyToHtml(content, undefined, opts); } else { // convert the string to something that can be safely // embedded in an html document, e.g. use html entities where needed @@ -37,7 +37,7 @@ function getSanitizedHtmlBody(content: IContent): string { // as opposed to bodyToHtml, here we also render // text messages with dangerouslySetInnerHTML, to unify // the code paths and because we need html to show differences - return textToHtml(bodyToHtml(content, null, opts)); + return textToHtml(bodyToHtml(content, undefined, opts)); } } diff --git a/src/utils/dm/startDm.ts b/src/utils/dm/startDm.ts index c88ad15c77..4b9ef082e3 100644 --- a/src/utils/dm/startDm.ts +++ b/src/utils/dm/startDm.ts @@ -7,7 +7,6 @@ Please see LICENSE files in the repository root for full details. */ import { type IInvite3PID, type MatrixClient, type Room } from "matrix-js-sdk/src/matrix"; -import { type Optional } from "matrix-events-sdk"; import { Action } from "../../dispatcher/actions"; import { type ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; @@ -28,7 +27,7 @@ export async function startDm(client: MatrixClient, targets: Member[], showSpinn const targetIds = targets.map((t) => t.userId); // Check if there is already a DM with these people and reuse it if possible. - let existingRoom: Optional; + let existingRoom: Room | undefined; if (targetIds.length === 1) { existingRoom = findDMForUser(client, targetIds[0]); } else { diff --git a/test/unit-tests/Avatar-test.ts b/test/unit-tests/Avatar-test.ts index ced974a059..72e313db28 100644 --- a/test/unit-tests/Avatar-test.ts +++ b/test/unit-tests/Avatar-test.ts @@ -68,7 +68,7 @@ describe("avatarUrlForRoom", () => { }); it("should return null if the room is not a DM", () => { - mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue(null); + mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue(undefined); expect(avatarUrlForRoom(room, 128, 128)).toBeNull(); expect(dmRoomMap.getUserIdForRoomId).toHaveBeenCalledWith(roomId); }); diff --git a/test/unit-tests/components/viewmodels/avatars/RoomAvatarViewModel-test.tsx b/test/unit-tests/components/viewmodels/avatars/RoomAvatarViewModel-test.tsx index 5f29f3ff33..d046307d92 100644 --- a/test/unit-tests/components/viewmodels/avatars/RoomAvatarViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/avatars/RoomAvatarViewModel-test.tsx @@ -30,7 +30,7 @@ describe("RoomAvatarViewModel", () => { room = mkStubRoom("roomId", "roomName", matrixClient); DMRoomMap.makeShared(matrixClient); - jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(undefined); jest.spyOn(PresenceIndicatorModule, "useDmMember").mockReturnValue(null); jest.spyOn(PresenceIndicatorModule, "usePresence").mockReturnValue(null); diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListItemMenuViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListItemMenuViewModel-test.tsx index ddb3cba609..d017084db5 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListItemMenuViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListItemMenuViewModel-test.tsx @@ -56,7 +56,7 @@ describe("RoomListItemMenuViewModel", () => { room = mkStubRoom("roomId", "roomName", matrixClient); DMRoomMap.makeShared(matrixClient); - jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(undefined); mocked(useUnreadNotifications).mockReturnValue({ symbol: null, count: 0, level: NotificationLevel.None }); mocked(useNotificationState).mockReturnValue([RoomNotifState.AllMessages, jest.fn()]); diff --git a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx index b6c18a2545..c8ede64320 100644 --- a/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx +++ b/test/unit-tests/components/viewmodels/roomlist/RoomListViewModel-test.tsx @@ -315,7 +315,7 @@ describe("RoomListViewModel", () => { it("active room index becomes undefined when active room is deleted", () => { const { rooms } = mockAndCreateRooms(); // Let's say that the room at index 5 is active - let roomId: string | undefined = rooms[5].roomId; + let roomId: string | null = rooms[5].roomId; jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => roomId); const { result: vm } = renderHook(() => useRoomListViewModel()); @@ -323,7 +323,7 @@ describe("RoomListViewModel", () => { // Let's remove the active room (i.e room at index 5) rooms.splice(5, 1); - roomId = undefined; + roomId = null; act(() => RoomListStoreV3.instance.emit(LISTS_UPDATE_EVENT)); expect(vm.current.activeIndex).toBeUndefined(); }); @@ -332,7 +332,7 @@ describe("RoomListViewModel", () => { mockAndCreateRooms(); // Let's say that there's no active room currently - jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => undefined); + jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockImplementation(() => null); const { result: vm } = renderHook(() => useRoomListViewModel()); expect(vm.current.activeIndex).toEqual(undefined); diff --git a/test/unit-tests/components/viewmodels/roomlist/useRoomListNavigation-test.ts b/test/unit-tests/components/viewmodels/roomlist/useRoomListNavigation-test.ts index c82f9aa87d..1ae8606697 100644 --- a/test/unit-tests/components/viewmodels/roomlist/useRoomListNavigation-test.ts +++ b/test/unit-tests/components/viewmodels/roomlist/useRoomListNavigation-test.ts @@ -30,7 +30,7 @@ describe("useRoomListNavigation", () => { ]; DMRoomMap.makeShared(matrixClient); - jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(undefined); jest.spyOn(dispatcher, "dispatch"); }); diff --git a/test/unit-tests/components/views/avatars/RoomAvatarView-test.tsx b/test/unit-tests/components/views/avatars/RoomAvatarView-test.tsx index 00ab886b4f..fe403af510 100644 --- a/test/unit-tests/components/views/avatars/RoomAvatarView-test.tsx +++ b/test/unit-tests/components/views/avatars/RoomAvatarView-test.tsx @@ -29,7 +29,7 @@ describe("", () => { const room = mkStubRoom("roomId", "roomName", matrixClient); DMRoomMap.makeShared(matrixClient); - jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(undefined); let defaultValue: RoomAvatarViewState; diff --git a/test/unit-tests/components/views/elements/AppTile-test.tsx b/test/unit-tests/components/views/elements/AppTile-test.tsx index e62d1adab9..2c454dc86d 100644 --- a/test/unit-tests/components/views/elements/AppTile-test.tsx +++ b/test/unit-tests/components/views/elements/AppTile-test.tsx @@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details. import React from "react"; import { Room, type MatrixClient } from "matrix-js-sdk/src/matrix"; import { type ClientWidgetApi, type IWidget, MatrixWidgetType } from "matrix-widget-api"; -import { type Optional } from "matrix-events-sdk"; import { act, render, type RenderResult, waitForElementToBeRemoved, waitFor } from "jest-matrix-react"; import userEvent from "@testing-library/user-event"; import { @@ -411,7 +410,7 @@ describe("AppTile", () => { describe("for a maximised (centered) widget", () => { beforeEach(() => { jest.spyOn(WidgetLayoutStore.instance, "isInContainer").mockImplementation( - (room: Optional, widget: IWidget, container: Container) => { + (room: Room | null, widget: IWidget, container: Container) => { return room === r1 && widget === app1 && container === Container.Center; }, ); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx index c38292e89b..04593777f5 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomList-test.tsx @@ -37,7 +37,7 @@ describe("", () => { // Needed to render a room list cell DMRoomMap.makeShared(matrixClient); - jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(undefined); }); it("should render a room list", () => { diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx index d3a8fdfbeb..b6127e1189 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListItemView-test.tsx @@ -49,7 +49,7 @@ describe("", () => { room = mkRoom(matrixClient, "room1"); DMRoomMap.makeShared(matrixClient); - jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null); + jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(undefined); const notificationState = new RoomNotificationState(room, false); jest.spyOn(notificationState, "hasAnyNotificationOrActivity", "get").mockReturnValue(true); diff --git a/test/unit-tests/stores/widgets/StopGapWidget-test.ts b/test/unit-tests/stores/widgets/StopGapWidget-test.ts index 9ce5f10240..501aea7ea1 100644 --- a/test/unit-tests/stores/widgets/StopGapWidget-test.ts +++ b/test/unit-tests/stores/widgets/StopGapWidget-test.ts @@ -20,7 +20,6 @@ import { } from "matrix-js-sdk/src/matrix"; import { ClientWidgetApi, WidgetApiFromWidgetAction } from "matrix-widget-api"; import { waitFor } from "jest-matrix-react"; -import { type Optional } from "matrix-events-sdk"; import { stubClient, mkRoom, mkEvent } from "../../../test-utils"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; @@ -362,13 +361,13 @@ describe("StopGapWidget with stickyPromise", () => { describe("StopGapWidget as an account widget", () => { let widget: StopGapWidget; let messaging: MockedObject; - let getRoomId: MockedFunction<() => Optional>; + let getRoomId: MockedFunction<() => string | null>; beforeEach(() => { stubClient(); // I give up, getting the return type of spyOn right is hopeless getRoomId = jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId") as unknown as MockedFunction< - () => Optional + () => string | null >; getRoomId.mockReturnValue("!1:example.org"); diff --git a/webpack.config.js b/webpack.config.js index 49c98f4365..3a3e7ad292 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -214,8 +214,7 @@ module.exports = (env, argv) => { __dirname, "node_modules/@matrix-org/react-sdk-module-api", ), - // and matrix-events-sdk & matrix-widget-api - "matrix-events-sdk": path.resolve(__dirname, "node_modules/matrix-events-sdk"), + // and matrix-widget-api "matrix-widget-api": path.resolve(__dirname, "node_modules/matrix-widget-api"), "oidc-client-ts": path.resolve(__dirname, "node_modules/oidc-client-ts"),