fix: null roomRef before destroyRoom to suppress teardown sounds

During room.disconnect(), LiveKit fires ParticipantDisconnected for
each remote participant BEFORE the final Disconnected event. Because
roomRef was still set, guardedUpdate() called updateParticipants(),
which updated the voiceStore while isLiveKitConnected was still true.
SoundController played user_leave for each departing participant
alongside the disconnect sound.

Fix: set roomRef.current = null before calling destroyRoom(). This
causes guardedUpdate() to return early for all teardown events.
The disconnect function handles cleanup after destroyRoom resolves.
This commit is contained in:
Jannis Braun
2026-04-08 15:39:21 +02:00
parent b03df992dc
commit a1a7c2ff18
+7 -1
View File
@@ -621,9 +621,15 @@ export function useLiveKit() {
connectedChannelRef.current = null; connectedChannelRef.current = null;
setConnectedChannelId(null); setConnectedChannelId(null);
if (roomRef.current) { if (roomRef.current) {
await destroyRoom(roomRef.current); // Null out roomRef BEFORE destroying so that guardedUpdate() skips
// during teardown. Without this, ParticipantDisconnected events fire
// before RoomEvent.Disconnected, calling updateParticipants while
// isLiveKitConnected is still true — SoundController plays user_leave
// for departing participants alongside the disconnect sound.
const roomToDestroy = roomRef.current;
roomRef.current = null; roomRef.current = null;
_activeRoom = null; _activeRoom = null;
await destroyRoom(roomToDestroy);
setRoom(null); setRoom(null);
setIsConnected(false); setIsConnected(false);
setIsConnecting(false); setIsConnecting(false);