From f97dd2adab0817b6fc182d559723fcd625647f70 Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 13 Oct 2026 12:59:14 +0200 Subject: [PATCH] Show the whole transport in debug UI and logs A transport may soon carry a LiveKit SFU `url` instead of, or as well as, a `livekit_service_url`, so a service URL alone no longer identifies it. Pass the whole transport to the tiles' debug stats and print it as JSON in log lines instead of picking out the service URL. Element Call's media view models carry the member's raw transport from the SDK's TransportMetadata to the tiles. --- src/RTCConnectionStats.tsx | 4 ++-- src/state/CallViewModel/CallViewModel.ts | 4 ++-- src/state/media/MemberMediaViewModel.ts | 9 +++++---- src/state/media/RemoteUserMediaViewModel.ts | 4 ++-- src/tile/GridTile.tsx | 4 ++-- src/tile/MediaView.tsx | 6 +++--- src/tile/SpotlightTile.tsx | 4 ++-- src/utils/test.ts | 8 ++++---- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/RTCConnectionStats.tsx b/src/RTCConnectionStats.tsx index a19cdd977..f135c6ec7 100644 --- a/src/RTCConnectionStats.tsx +++ b/src/RTCConnectionStats.tsx @@ -16,12 +16,12 @@ import classNames from "classnames"; import { Modal } from "./Modal"; import styles from "./RTCConnectionStats.module.css"; import mediaViewStyles from "../src/tile/MediaView.module.css"; -import { type UnstableLivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; +import { type Transport } from "matrix-js-sdk/lib/matrixrtc"; interface Props { audio?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats; video?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats; - transport?: UnstableLivekitTransport; + transport?: Transport; rtcBackendIdentity?: string; } diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 9b77dc5af..5bb71d6fc 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -674,8 +674,8 @@ export function createCallViewModel$( rtcBackendIdentity: member.rtcBackendIdentity, member, encryptionSystem: options.encryptionSystem, - focusUrl$: scope.behavior( - member.transport$.pipe(map((transport) => transport?.id)), + transport$: scope.behavior( + member.transport$.pipe(map((transport) => transport?.raw)), ), mediaDevices, pretendToBeDisconnected$: reconnecting$, diff --git a/src/state/media/MemberMediaViewModel.ts b/src/state/media/MemberMediaViewModel.ts index 51864878b..54500ae4e 100644 --- a/src/state/media/MemberMediaViewModel.ts +++ b/src/state/media/MemberMediaViewModel.ts @@ -18,6 +18,7 @@ import { trackBySource$, type VideoMediaTrack, } from "@element-hq/matrixrtc-sdk"; +import { type Transport } from "matrix-js-sdk/lib/matrixrtc"; import { combineLatest, distinctUntilChanged, @@ -56,10 +57,10 @@ export interface BaseMemberMediaViewModel extends BaseMediaViewModel { */ video$: Behavior; /** - * The URL of the transport on which this member should be publishing. - * Exposed for debugging. + * The transport on which this member should be publishing, as it appears + * in the membership. Exposed for debugging. */ - transport$: Behavior; + transport$: Behavior; /** * Whether there should be a warning that this media is unencrypted. */ @@ -74,7 +75,7 @@ export interface MemberMediaInputs extends BaseMediaViewModel { member: MediaMember; audioSource: "microphone" | "screenShareAudio"; videoSource: "camera" | "screenShare"; - focusUrl$: Behavior; + transport$: Behavior; encryptionSystem: EncryptionSystem; } diff --git a/src/state/media/RemoteUserMediaViewModel.ts b/src/state/media/RemoteUserMediaViewModel.ts index 79a4bd391..92a1dfa2b 100644 --- a/src/state/media/RemoteUserMediaViewModel.ts +++ b/src/state/media/RemoteUserMediaViewModel.ts @@ -43,11 +43,11 @@ export function createRemoteUserMedia( const waitingForMedia$ = scope.behavior( combineLatest( - [inputs.focusUrl$, inputs.member.tracks$], + [inputs.transport$, inputs.member.tracks$], // Without a transport the user is not attempting to publish anywhere // and so we shouldn't expect media. (They might be a subscribe-only bot // for example.) - (focusUrl, tracks) => focusUrl !== undefined && tracks === null, + (transport, tracks) => transport !== undefined && tracks === null, ), ); waitingForMedia$.pipe(scope.bind()).subscribe((waiting) => { diff --git a/src/tile/GridTile.tsx b/src/tile/GridTile.tsx index b0625a4d7..91e83936b 100644 --- a/src/tile/GridTile.tsx +++ b/src/tile/GridTile.tsx @@ -51,7 +51,7 @@ import { type RemoteUserMediaViewModel } from "../state/media/RemoteUserMediaVie import { type UserMediaViewModel } from "../state/media/UserMediaViewModel"; import { type RingingMediaViewModel } from "../state/media/RingingMediaViewModel"; import { RingingStatus } from "./RingingStatus"; -import { type UnstableLivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; +import { type Transport } from "matrix-js-sdk/lib/matrixrtc"; interface TileProps { ref?: Ref; @@ -104,7 +104,7 @@ interface UserMediaTileProps extends TileProps { playbackMuted: boolean; waitingForMedia?: boolean; primaryButton?: ReactNode; - transport: UnstableLivekitTransport | undefined; + transport: Transport | undefined; } /** diff --git a/src/tile/MediaView.tsx b/src/tile/MediaView.tsx index dc477007c..5294dce55 100644 --- a/src/tile/MediaView.tsx +++ b/src/tile/MediaView.tsx @@ -34,7 +34,7 @@ import { ReactionIndicator } from "../reactions/ReactionIndicator"; import { RTCConnectionStats } from "../RTCConnectionStats"; import videoPlaceholder from "../graphics/video-placeholder.gif"; import { autoVideoFit } from "../utils/videoFit"; -import { type UnstableLivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; +import { type Transport } from "matrix-js-sdk/lib/matrixrtc"; interface Props extends ComponentProps { className?: string; @@ -69,9 +69,9 @@ interface Props extends ComponentProps { videoStreamStats?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats; rtcBackendIdentity?: string; /** - * The LiveKit transport, mainly for debugging purposes. + * The member's transport, mainly for debugging purposes. */ - transport?: UnstableLivekitTransport; + transport?: Transport; /** * Called whenever the aspect ratio of the video content becomes known or * otherwise changes. diff --git a/src/tile/SpotlightTile.tsx b/src/tile/SpotlightTile.tsx index ce2c4e662..33b00f6e4 100644 --- a/src/tile/SpotlightTile.tsx +++ b/src/tile/SpotlightTile.tsx @@ -54,7 +54,7 @@ import { platform } from "../Platform"; import { type RingingMediaViewModel } from "../state/media/RingingMediaViewModel"; import { RingingStatus } from "./RingingStatus"; import { useRootElement } from "../RootElementContext"; -import { type UnstableLivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; +import { type Transport } from "matrix-js-sdk/lib/matrixrtc"; interface SpotlightItemBaseProps { ref?: Ref; @@ -75,7 +75,7 @@ interface SpotlightItemBaseProps { interface SpotlightMemberMediaItemBaseProps extends SpotlightItemBaseProps { video: VideoMediaTrack | undefined; unencryptedWarning: boolean; - transport: UnstableLivekitTransport | undefined; + transport: Transport | undefined; } interface SpotlightUserMediaItemBaseProps extends SpotlightMemberMediaItemBaseProps { diff --git a/src/utils/test.ts b/src/utils/test.ts index 9bb92b3ba..8f9f7c39e 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -372,7 +372,7 @@ export function mockLocalMedia( tracks$: constant(tracks), }), encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, - focusUrl$: constant("https://rtc-example.org"), + transport$: constant(exampleTransport), mediaDevices, displayName$: constant(member.rawDisplayName ?? "nodisplayname"), mxcAvatarUrl$: constant(member.getMxcAvatarUrl()), @@ -386,7 +386,7 @@ export function mockRemoteMedia( roomMember: Partial, /** The tracks, or a behavior of them for a test that has them arrive. */ tracks: MockTracks | Behavior, - { focusUrl }: { focusUrl?: string } = { focusUrl: "https://rtc-example.org" }, + { transport }: { transport?: Transport } = { transport: exampleTransport }, ): RemoteUserMediaViewModel { const member = mockMatrixRoomMember(rtcMember, roomMember); return createRemoteUserMedia(testScope(), { @@ -400,7 +400,7 @@ export function mockRemoteMedia( tracks === null || Array.isArray(tracks) ? constant(tracks) : tracks, }), encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, - focusUrl$: constant(focusUrl), + transport$: constant(transport), pretendToBeDisconnected$: constant(false), displayName$: constant(member.rawDisplayName ?? "nodisplayname"), mxcAvatarUrl$: constant(member.getMxcAvatarUrl()), @@ -424,7 +424,7 @@ export function mockRemoteScreenShare( tracks$: constant(tracks), }), encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, - focusUrl$: constant("https://rtc-example.org"), + transport$: constant(exampleTransport), pretendToBeDisconnected$: constant(false), displayName$: constant(member.rawDisplayName ?? "nodisplayname"), mxcAvatarUrl$: constant(member.getMxcAvatarUrl()),