diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 5ceb30f5..e096dd54 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -435,19 +435,6 @@ export const InCallView: FC = ({ [vm], ); - useEffect(() => { - widget?.api.transport - .send( - gridMode === "grid" - ? ElementWidgetActions.TileLayout - : ElementWidgetActions.SpotlightLayout, - {}, - ) - .catch((e) => { - logger.error("Failed to send layout change to widget API", e); - }); - }, [gridMode]); - useEffect(() => { if (widget) { const onTileLayout = (ev: CustomEvent): void => { diff --git a/src/state/CallViewModel/localMember/LocalMember.test.ts b/src/state/CallViewModel/localMember/LocalMember.test.ts index af12c98b..97bcd952 100644 --- a/src/state/CallViewModel/localMember/LocalMember.test.ts +++ b/src/state/CallViewModel/localMember/LocalMember.test.ts @@ -194,8 +194,8 @@ describe("LocalMembership", () => { matrixRTCMode: MatrixRTCMode.Matrix_2_0, }), matrixRTCSession: { - updateCallIntent: () => {}, - leaveRoomSession: () => {}, + updateCallIntent: vi.fn().mockReturnValue(Promise.resolve()), + leaveRoomSession: vi.fn(), } as unknown as MatrixRTCSession, muteStates: mockMuteStates(), trackProcessorState$: constant({ @@ -244,6 +244,37 @@ describe("LocalMembership", () => { }); }); + it("logs if callIntent cannot be updated", async () => { + const scope = new ObservableScope(); + + const localTransport$ = new BehaviorSubject(aTransport); + const mockConnectionManager = { + transports$: constant(new Epoch([])), + connectionManagerData$: constant(new Epoch(new ConnectionManagerData())), + }; + async function reject(): Promise { + return Promise.reject(new Error("Not connected yet")); + } + const localMembership = createLocalMembership$({ + scope, + ...defaultCreateLocalMemberValues, + matrixRTCSession: { + updateCallIntent: vi.fn().mockImplementation(reject), + leaveRoomSession: vi.fn(), + }, + connectionManager: mockConnectionManager, + localTransport$, + }); + const expextedLog = + "'not connected yet' while updating the call intent (this is expected on startup)"; + const internalLogger = vi.spyOn(localMembership.internalLoggerRef, "debug"); + + await flushPromises(); + defaultCreateLocalMemberValues.muteStates.video.setEnabled$.value?.(true); + expect(internalLogger).toHaveBeenCalledWith(expextedLog); + scope.end(); + }); + const aTransport = { transport: { livekit_service_url: "a", diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 4749e942..5fe781d7 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -200,6 +200,7 @@ export const createLocalMembership$ = ({ * Fully connected */ connected$: Behavior; + internalLoggerRef: Logger; } => { const logger = parentLogger.getChild("[LocalMembership]"); logger.debug(`Creating local membership..`); @@ -520,12 +521,19 @@ export const createLocalMembership$ = ({ } }); - combineLatest([muteStates.video.enabled$, homeserverConnected.combined$]) - .pipe(scope.bind()) - .subscribe(([videoEnabled, connected]) => { - if (!connected) return; - void matrixRTCSession.updateCallIntent(videoEnabled ? "video" : "audio"); - }); + muteStates.video.enabled$.pipe(scope.bind()).subscribe((videoEnabled) => { + void matrixRTCSession + .updateCallIntent(videoEnabled ? "video" : "audio") + .catch((e) => { + if (e instanceof Error && e.message === "Not connected yet") { + logger.debug( + "'not connected yet' while updating the call intent (this is expected on startup)", + ); + } else { + throw e; + } + }); + }); // Keep matrix rtc session in sync with localTransport$, connectRequested$ scope.reconcile( @@ -669,6 +677,7 @@ export const createLocalMembership$ = ({ sharingScreen$, toggleScreenSharing, connection$: localConnection$, + internalLoggerRef: logger, }; }; diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 0625866d..d4a56126 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -335,17 +335,23 @@ async function makeTransport( // MSC4143: Attempt to fetch transports from backend. if ("_unstable_getRTCTransports" in client) { try { - const selectedTransport = await getFirstUsableTransport( - await client._unstable_getRTCTransports(), - ); + const transportList = await client._unstable_getRTCTransports(); + const selectedTransport = await getFirstUsableTransport(transportList); if (selectedTransport) { - logger.info("Using backend-configured SFU", selectedTransport); + logger.info( + "Using backend-configured (client.getRTCTransports) SFU", + selectedTransport, + ); return selectedTransport; } } catch (ex) { if (ex instanceof MatrixError && ex.httpStatus === 404) { // Expected, this is an unstable endpoint and it's not required. - logger.debug("Backend does not provide any RTC transports", ex); + logger.debug( + "Backend does not provide any RTC transports (will retry with well-known.)", + "Your server admin needs to update the matrix homeserver.", + "(The 404 erros in the console above are expectet to check if synapse supports the endpoint.)", + ); } else if (ex instanceof FailToGetOpenIdToken) { throw ex; } else { diff --git a/src/tile/SpotlightTile.tsx b/src/tile/SpotlightTile.tsx index 2042e819..e685327e 100644 --- a/src/tile/SpotlightTile.tsx +++ b/src/tile/SpotlightTile.tsx @@ -63,7 +63,6 @@ interface SpotlightItemBaseProps { mxcAvatarUrl: string | undefined; focusable: boolean; "aria-hidden"?: boolean; - localParticipant: boolean; } interface SpotlightUserMediaItemBaseProps extends SpotlightItemBaseProps { @@ -188,7 +187,6 @@ const SpotlightItem: FC = ({ focusable, encryptionStatus, "aria-hidden": ariaHidden, - localParticipant: vm.local, }; return vm instanceof ScreenShareViewModel ? ( diff --git a/src/utils/test.ts b/src/utils/test.ts index c99eb77d..d78bdf42 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -460,7 +460,9 @@ export class MockRTCSession extends TypedEventEmitter< return this; } - public updateCallIntent = vitest.fn(); + public updateCallIntent = vitest + .fn() + .mockImplementation(async () => Promise.resolve()); private _membershipStatus = Status.Connected; public get membershipStatus(): Status {