From 16a446095a0a574d49f2c019c90a25f636e2e5c4 Mon Sep 17 00:00:00 2001 From: Aditya Chaudhary <30+useradityaa@noreply.coracle.social> Date: Mon, 20 Jul 2026 23:34:06 +0000 Subject: [PATCH] fix(video): show avatar tiles for audio-only and camera-off callers (#325) Co-authored-by: Aditya Chaudhary <30+useradityaa@noreply.coracle.social> Co-committed-by: Aditya Chaudhary <30+useradityaa@noreply.coracle.social> --- src/app/call.ts | 4 ++-- src/app/components/VideoCallContent.svelte | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/app/call.ts b/src/app/call.ts index 42edbdda..f5e30c3d 100644 --- a/src/app/call.ts +++ b/src/app/call.ts @@ -131,7 +131,7 @@ export const videoCallLayout = writable(VideoCallLayout.Split) export const videoPrimaryTileKey = writable(undefined) export const videoTileCount = derived( - [currentCallSession, callState, videoTrackRevision], + [currentCallSession, callState, videoTrackRevision, participantMediaState], ([$session, $state]) => { if ($state !== CallState.Connected || !$session) return 0 return countLiveVisualFeeds($session) @@ -478,7 +478,7 @@ const countLiveVisualFeeds = (session: CallSession): number => { for (const rp of livekit.remoteParticipants.values()) { for (const source of VISUAL_SOURCES) { const pub = rp.getTrackPublication(source) - if (pub?.isSubscribed && pub.track) n += 1 + if (pub?.isSubscribed && pub.track && !pub.isMuted) n += 1 } } return n diff --git a/src/app/components/VideoCallContent.svelte b/src/app/components/VideoCallContent.svelte index 45be792f..d4078766 100644 --- a/src/app/components/VideoCallContent.svelte +++ b/src/app/components/VideoCallContent.svelte @@ -21,7 +21,9 @@ currentCallSession, callTargetRoom, mediaStateByIdentity, + participantMediaState, pubkeyFromLiveKitIdentity, + videoTrackRevision, } from "@app/call" type Props = { @@ -74,6 +76,10 @@ const videoTiles = $derived.by(() => { const session = $currentCallSession + // LiveKit mutates remoteParticipants/tracks in place; these stores are what + // actually change on join/leave and track subscribe/unsubscribe. + void $participantMediaState + void $videoTrackRevision if (!session || $callTargetRoom?.url !== url || $callTargetRoom?.h !== h) { return [] } @@ -106,7 +112,8 @@ for (const rp of livekit.remoteParticipants.values()) { const camPub = rp.getTrackPublication(Track.Source.Camera) - if (camPub?.isSubscribed && camPub.track) { + // Camera off mutes the publication rather than unsubscribing; still render avatar. + if (camPub?.isSubscribed && camPub.track && !camPub.isMuted) { videoTiles.push({ liveKitIdentity: rp.identity, isLocal: false, @@ -116,7 +123,7 @@ }) } const screenPub = rp.getTrackPublication(Track.Source.ScreenShare) - if (screenPub?.isSubscribed && screenPub.track) { + if (screenPub?.isSubscribed && screenPub.track && !screenPub.isMuted) { videoTiles.push({ liveKitIdentity: rp.identity, isLocal: false, @@ -290,10 +297,7 @@ {:else}
-

No one is sharing video yet.

-

- Participants appear here when they turn on their camera or share their screen. -

+

Waiting for participants…

{/if} {/snippet}