From 4ec8f1edcd5470381b1425bbd67439b6471a24bc Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 7 Jul 2026 13:29:54 +0100 Subject: [PATCH] Remove LegacyCallHandler singleton (#34086) * Remove dead code * Remove LegacyCallHandler singleton Route via SDKContext to cut import cycles * Remove unused setting * Fix tests * Fix tests * Cascade SDKContext through PersistedElement * Improve coverage * Iterate * Improve coverage * Improve coverage --- apps/web/src/@types/global.d.ts | 2 - apps/web/src/LegacyCallHandler.tsx | 71 ++------- apps/web/src/Lifecycle.ts | 5 +- .../structures/LegacyCallEventGrouper.ts | 23 +-- .../components/structures/LoggedInView.tsx | 10 +- .../src/components/structures/MatrixChat.tsx | 3 +- .../components/structures/PipContainer.tsx | 73 +++++---- .../context_menus/LegacyCallContextMenu.tsx | 9 +- .../components/views/dialogs/InviteDialog.tsx | 9 +- .../src/components/views/elements/AppTile.tsx | 37 +++-- .../views/elements/PersistedElement.tsx | 20 ++- .../rooms/RoomListPanel/RoomListSearch.tsx | 8 +- .../components/views/voip/DialPadModal.tsx | 4 +- .../components/views/voip/LegacyCallView.tsx | 44 +++--- .../views/voip/LegacyCallViewForRoom.tsx | 22 +-- .../src/components/views/voip/VideoFeed.tsx | 10 +- apps/web/src/contexts/SDKContextClass.ts | 2 +- apps/web/src/settings/Settings.tsx | 5 - apps/web/src/slash-commands/SlashCommands.tsx | 8 +- apps/web/src/toasts/IncomingCallToast.tsx | 18 ++- .../src/toasts/IncomingLegacyCallToast.tsx | 30 ++-- apps/web/src/utils/leave-behaviour.test.ts | 5 +- apps/web/src/utils/leave-behaviour.ts | 3 +- apps/web/src/utils/room/placeCall.ts | 4 +- .../room-list/RoomListSearchViewModel.ts | 14 +- .../test/unit-tests/LegacyCallHandler-test.ts | 9 +- apps/web/test/unit-tests/TestSDKContext.ts | 2 + .../structures/LegacyCallEventGrouper-test.ts | 82 +++++++++- .../components/structures/MatrixChat-test.tsx | 5 +- .../views/elements/AppTile-test.tsx | 148 ++++++++++++------ .../rooms/RoomHeader/RoomHeader-test.tsx | 12 +- .../RoomListPanel/RoomListPanel-test.tsx | 11 +- .../RoomListPanel/RoomListSearch-test.tsx | 10 +- .../components/views/voip/CallView-test.tsx | 10 +- .../views/voip/LegacyCallView-test.tsx | 116 +++++++++++++- .../views/voip/LegacyCallViewForRoom-test.tsx | 23 +-- .../components/views/voip/VideoFeed-test.tsx | 16 +- .../toasts/IncomingCallToast-test.tsx | 15 +- .../toasts/IncomingLegacyCallToast-test.tsx | 28 +++- .../room-list/RoomListSearchViewModel-test.ts | 61 ++++++-- 40 files changed, 639 insertions(+), 348 deletions(-) diff --git a/apps/web/src/@types/global.d.ts b/apps/web/src/@types/global.d.ts index b65d95d3b5..e3e49fad70 100644 --- a/apps/web/src/@types/global.d.ts +++ b/apps/web/src/@types/global.d.ts @@ -21,7 +21,6 @@ import { type ModalManager } from "../Modal"; import type SettingsStore from "../settings/SettingsStore"; import type RightPanelStore from "../stores/right-panel/RightPanelStore"; import type WidgetStore from "../stores/WidgetStore"; -import type LegacyCallHandler from "../LegacyCallHandler"; import type UserActivity from "../UserActivity"; import { type ModalWidgetStore } from "../stores/ModalWidgetStore"; import { type WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore"; @@ -99,7 +98,6 @@ declare global { mxRightPanelStore: RightPanelStore; mxWidgetStore: WidgetStore; mxWidgetLayoutStore: WidgetLayoutStore; - mxLegacyCallHandler: LegacyCallHandler; mxUserActivity: UserActivity; mxModalWidgetStore: ModalWidgetStore; mxSpaceStore: SpaceStoreClass; diff --git a/apps/web/src/LegacyCallHandler.tsx b/apps/web/src/LegacyCallHandler.tsx index 3ccf500b26..48627d59ad 100644 --- a/apps/web/src/LegacyCallHandler.tsx +++ b/apps/web/src/LegacyCallHandler.tsx @@ -34,7 +34,6 @@ import { WidgetType } from "./widgets/WidgetType"; import { SettingLevel } from "./settings/SettingLevel"; import QuestionDialog from "./components/views/dialogs/QuestionDialog"; import ErrorDialog from "./components/views/dialogs/ErrorDialog"; -import WidgetStore from "./stores/WidgetStore"; import { WidgetMessagingStore } from "./stores/widgets/WidgetMessagingStore"; import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions"; import { UIFeature } from "./settings/UIFeature"; @@ -42,7 +41,6 @@ import { Action } from "./dispatcher/actions"; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from "./widgets/ManagedHybrid"; import SdkConfig from "./SdkConfig"; import { ensureDMExists } from "./createRoom"; -import { WidgetLayoutStore } from "./stores/widgets/WidgetLayoutStore"; import IncomingLegacyCallToast, { getIncomingLegacyCallToastKey } from "./toasts/IncomingLegacyCallToast"; import ToastStore from "./stores/ToastStore"; import { type ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload"; @@ -54,41 +52,13 @@ import { localNotificationsAreSilenced } from "./utils/notifications"; import { isNotNull } from "./Typeguards"; import { BackgroundAudio } from "./audio/BackgroundAudio"; import { Jitsi } from "./widgets/Jitsi.ts"; +import { type SDKContextClass } from "./contexts/SDKContextClass.ts"; export const PROTOCOL_PSTN = "m.protocol.pstn"; export const PROTOCOL_PSTN_PREFIXED = "im.vector.protocol.pstn"; const CHECK_PROTOCOLS_ATTEMPTS = 3; -type MediaEventType = keyof HTMLMediaElementEventMap; -const MEDIA_ERROR_EVENT_TYPES: MediaEventType[] = [ - "error", - // The media has become empty; for example, this event is sent if the media has - // already been loaded (or partially loaded), and the HTMLMediaElement.load method - // is called to reload it. - "emptied", - // The user agent is trying to fetch media data, but data is unexpectedly not - // forthcoming. - "stalled", - // Media data loading has been suspended. - "suspend", - // Playback has stopped because of a temporary lack of data - "waiting", -]; -const MEDIA_DEBUG_EVENT_TYPES: MediaEventType[] = [ - "play", - "pause", - "playing", - "ended", - "loadeddata", - "loadedmetadata", - "canplay", - "canplaythrough", - "volumechange", -]; - -const MEDIA_EVENT_TYPES = [...MEDIA_ERROR_EVENT_TYPES, ...MEDIA_DEBUG_EVENT_TYPES]; - export enum AudioID { Ring = "ringAudio", Ringback = "ringbackAudio", @@ -96,13 +66,6 @@ export enum AudioID { Busy = "busyAudio", } -/* istanbul ignore next */ -const debuglog = (...args: any[]): void => { - if (SettingsStore.getValue("debug_legacy_call_handler")) { - logger.log.call(console, "LegacyCallHandler debuglog:", ...args); - } -}; - interface ThirdpartyLookupResponse { userid: string; protocol: string; @@ -151,12 +114,8 @@ export default class LegacyCallHandler extends TypedEventEmitter = {}; // Record them for stopping - public static get instance(): LegacyCallHandler { - if (!window.mxLegacyCallHandler) { - window.mxLegacyCallHandler = new LegacyCallHandler(); - } - - return window.mxLegacyCallHandler; + public constructor(private readonly sdkContext: SDKContextClass) { + super(); } /* @@ -193,18 +152,6 @@ export default class LegacyCallHandler extends TypedEventEmitter`, e); - } else if (MEDIA_EVENT_TYPES.includes(e.type as MediaEventType)) { - debuglog(`encountered "${e.type}" event with