fix(voice): AudioRenderers listens to room events directly, not zustand

This commit is contained in:
2026-07-09 13:08:02 -04:00
parent 8542243745
commit 7d1bd02e31
+20 -5
View File
@@ -1,4 +1,4 @@
import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useVoiceStore } from '../stores/voice.ts';
import { Track, RoomEvent } from 'livekit-client';
import type { Participant, TrackPublication, Room } from 'livekit-client';
@@ -13,7 +13,6 @@ function flushPendingAudio() {
}
}
// ponytail: one-time document listener to flush on any user interaction
let listenerAttached = false;
function ensureInteractionListener() {
if (listenerAttached) return;
@@ -68,9 +67,25 @@ function RemoteAudioTrack({ participant, room }: { participant: Participant; roo
export function AudioRenderers() {
const room = useVoiceStore((s) => s._room);
// @ts-ignore ponytail: subscribe to trigger re-render when remote users join/leave
useVoiceStore((s) => s.participants); // @ts-ignore
// ponytail: use a counter that increments on every participant change
// zustand's Object.is check on the participants array wasn't triggering re-renders
const [, setTick] = useState(0);
useEffect(() => {
if (!room) return;
const bump = () => setTick((t) => t + 1);
room.on(RoomEvent.ParticipantConnected, bump);
room.on(RoomEvent.ParticipantDisconnected, bump);
room.on(RoomEvent.TrackSubscribed, bump);
room.on(RoomEvent.TrackUnsubscribed, bump);
return () => {
room.off(RoomEvent.ParticipantConnected, bump);
room.off(RoomEvent.ParticipantDisconnected, bump);
room.off(RoomEvent.TrackSubscribed, bump);
room.off(RoomEvent.TrackUnsubscribed, bump);
};
}, [room]);
if (!room) return null;
const remoteParticipants = Array.from(room.remoteParticipants.values());