diff --git a/apps/web/src/utils/leave-behaviour.ts b/apps/web/src/utils/leave-behaviour.ts index 8b7ee02f36..9756fa50cf 100644 --- a/apps/web/src/utils/leave-behaviour.ts +++ b/apps/web/src/utils/leave-behaviour.ts @@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details. import { sleep } from "matrix-js-sdk/src/utils"; import React, { type ReactNode } from "react"; import { EventStatus, MatrixEventEvent, type Room, type MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix"; +import { logger } from "matrix-js-sdk/src/logger"; import Modal, { type IHandle } from "../Modal"; import Spinner from "../components/views/elements/Spinner"; @@ -25,6 +26,8 @@ import { type AfterLeaveRoomPayload } from "../dispatcher/payloads/AfterLeaveRoo import { bulkSpaceBehaviour } from "./space"; import { SdkContextClass } from "../contexts/SDKContext"; import SettingsStore from "../settings/SettingsStore"; +import { CallStore } from "../stores/CallStore"; +import LegacyCallHandler from "../LegacyCallHandler"; export async function leaveRoomBehaviour( matrixClient: MatrixClient, @@ -59,6 +62,23 @@ export async function leaveRoomBehaviour( throw new Error(`Expected to find room for id ${roomId}`); } + // attempt to hang up legacy based calls + try { + LegacyCallHandler.instance.hangupOrReject(roomId); + } catch (e) { + logger.warn("Failed to hangup call before leaving room: ", e); + } + + // hang up widget based calls + const activeCall = CallStore.instance.getActiveCall(roomId); + if (activeCall) { + try { + await activeCall.disconnect(); + } catch (e) { + logger.warn("Failed to disconnect call before leaving room: ", e); + } + } + // await any queued messages being sent so that they do not fail await Promise.all( room diff --git a/apps/web/test/unit-tests/utils/leave-behaviour-test.ts b/apps/web/test/unit-tests/utils/leave-behaviour-test.ts index 9da796a3a5..a6da3a4083 100644 --- a/apps/web/test/unit-tests/utils/leave-behaviour-test.ts +++ b/apps/web/test/unit-tests/utils/leave-behaviour-test.ts @@ -22,6 +22,9 @@ import SpaceStore from "../../../src/stores/spaces/SpaceStore"; import { MetaSpace } from "../../../src/stores/spaces"; import { type ActionPayload } from "../../../src/dispatcher/payloads"; import SettingsStore from "../../../src/settings/SettingsStore"; +import { CallStore } from "../../../src/stores/CallStore"; +import { type Call } from "../../../src/models/Call"; +import LegacyCallHandler from "../../../src/LegacyCallHandler"; describe("leaveRoomBehaviour", () => { SdkContextClass.instance.constructEagerStores(); // Initialize RoomViewStore @@ -76,6 +79,28 @@ describe("leaveRoomBehaviour", () => { defaultDispatcher.unregister(dispatcherRef); }; + it("hangs up legacy calls when leaving a room", async () => { + const hangupSpy = jest.spyOn(LegacyCallHandler.instance, "hangupOrReject").mockImplementation(() => {}); + + viewRoom(room); + await leaveRoomBehaviour(client, room.roomId); + + expect(hangupSpy).toHaveBeenCalledWith(room.roomId); + }); + + it("disconnects widget-based calls when leaving a room", async () => { + const mockCall = { + disconnect: jest.fn().mockResolvedValue(undefined), + } as unknown as Call; + + jest.spyOn(CallStore.instance, "getActiveCall").mockReturnValue(mockCall); + + viewRoom(room); + await leaveRoomBehaviour(client, room.roomId); + + expect(mockCall.disconnect).toHaveBeenCalled(); + }); + it("returns to the home page after leaving a room outside of a space that was being viewed", async () => { viewRoom(room);