From 06f70d1d7c9e3933c655d1a46443d987b218c14c Mon Sep 17 00:00:00 2001 From: Will Hunt <2072976+Half-Shot@users.noreply.github.com> Date: Fri, 9 Jan 2026 13:33:47 +0000 Subject: [PATCH] Ensure we react to RTC transport changes in useRoomCall (#31691) --- src/hooks/room/useRoomCall.tsx | 9 ++++++--- src/stores/CallStore.ts | 4 ++++ test/unit-tests/hooks/useRoomCall-test.tsx | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/hooks/room/useRoomCall.tsx b/src/hooks/room/useRoomCall.tsx index dca383e074..5d7784ed84 100644 --- a/src/hooks/room/useRoomCall.tsx +++ b/src/hooks/room/useRoomCall.tsx @@ -116,9 +116,12 @@ export const useRoomCall = ( return SdkConfig.get("element_call").use_exclusively; }, []); - const serverIsConfiguredForElementCall = CallStore.instance - .getConfiguredRTCTransports() - .some((s) => s.type === "livekit" && s.livekit_service_url); + const serverIsConfiguredForElementCall = useEventEmitterState( + CallStore.instance, + CallStoreEvent.TransportsUpdated, + () => + CallStore.instance.getConfiguredRTCTransports().some((s) => s.type === "livekit" && s.livekit_service_url), + ); useEffect(() => { if (useElementCallExclusively && !serverIsConfiguredForElementCall) { diff --git a/src/stores/CallStore.ts b/src/stores/CallStore.ts index 5997365fc0..d025b0a014 100644 --- a/src/stores/CallStore.ts +++ b/src/stores/CallStore.ts @@ -23,6 +23,8 @@ export enum CallStoreEvent { Call = "call", // Signals a change in the active calls ConnectedCalls = "connected_calls", + // Signals a change in the configured RTC transports. + TransportsUpdated = "transports_updated", } export class CallStore extends AsyncStoreWithClient { @@ -53,6 +55,7 @@ export class CallStore extends AsyncStoreWithClient { */ protected async fetchTransports(): Promise { if (!this.matrixClient) return; + this.configuredMatrixRTCTransports.clear(); // Prefer checking the proper endpoint for transports. try { const transports = await this.matrixClient._unstable_getRTCTransports(); @@ -70,6 +73,7 @@ export class CallStore extends AsyncStoreWithClient { if (Array.isArray(foci)) { foci.forEach((foci) => this.configuredMatrixRTCTransports.add(foci)); } + this.emit(CallStoreEvent.TransportsUpdated); } protected async onReady(): Promise { diff --git a/test/unit-tests/hooks/useRoomCall-test.tsx b/test/unit-tests/hooks/useRoomCall-test.tsx index 9d429f938c..53c7e5980f 100644 --- a/test/unit-tests/hooks/useRoomCall-test.tsx +++ b/test/unit-tests/hooks/useRoomCall-test.tsx @@ -129,5 +129,25 @@ describe("useRoomCall", () => { expect(result.current.callOptions).toEqual([PlatformCallType.ElementCall, PlatformCallType.LegacyCall]), ); }); + it("Ensure handler reacts to transport changes", async () => { + // Clear all transports + client._unstable_getRTCTransports.mockResolvedValue([]); + client.getClientWellKnown.mockReturnValue({}); + + await setupAsyncStoreWithClient(CallStore.instance, client); + const { result } = render(); + + // Ensure Element Call is not a call option. + expect(result.current.callOptions).toEqual([PlatformCallType.LegacyCall]); + + // Now enable a transport and ensure that useRoomCall picks it up reactively. + client._unstable_getRTCTransports.mockResolvedValue([ + { type: "livekit", livekit_service_url: "https://example.org" }, + ]); + await setupAsyncStoreWithClient(CallStore.instance, client); + await waitFor(() => + expect(result.current.callOptions).toEqual([PlatformCallType.ElementCall, PlatformCallType.LegacyCall]), + ); + }); }); });