fix(voice): simplify RemoteAudioTrack — remove stale listener race

This commit is contained in:
2026-07-09 13:01:49 -04:00
parent 33c9dc4f15
commit 67a5a54244
+10 -25
View File
@@ -1,6 +1,6 @@
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from 'react';
import { useVoiceStore } from '../stores/voice.ts'; import { useVoiceStore } from '../stores/voice.ts';
import { Track } from 'livekit-client'; import { Track, RoomEvent } from 'livekit-client';
import type { Participant, TrackPublication, Room } from 'livekit-client'; import type { Participant, TrackPublication, Room } from 'livekit-client';
function RemoteAudioTrack({ participant, room }: { participant: Participant; room: Room }) { function RemoteAudioTrack({ participant, room }: { participant: Participant; room: Room }) {
@@ -12,7 +12,7 @@ function RemoteAudioTrack({ participant, room }: { participant: Participant; roo
let pub: TrackPublication | undefined; let pub: TrackPublication | undefined;
const attachTrack = () => { const attachIfReady = () => {
pub = participant.getTrackPublication(Track.Source.Microphone); pub = participant.getTrackPublication(Track.Source.Microphone);
if (pub?.track && el) { if (pub?.track && el) {
pub.track.attach(el); pub.track.attach(el);
@@ -20,36 +20,21 @@ function RemoteAudioTrack({ participant, room }: { participant: Participant; roo
} }
}; };
const detachTrack = () => { // ponytail: check immediately — track may already be subscribed
if (pub?.track && el) { attachIfReady();
pub.track.detach(el);
}
};
attachTrack(); // ponytail: also listen for delayed subscription
const handleSubscribed = (track: Track, _pub: TrackPublication, p: Participant) => {
const handlePublished = (publication: TrackPublication) => { if (p.identity === participant.identity && _pub.source === Track.Source.Microphone) {
if (publication.source === Track.Source.Microphone && publication.track) {
publication.track.attach(el);
el.play().catch(() => {});
}
};
room.on('trackPublished' as any, handlePublished);
// If a track is subscribed later
const handleSubscribed = (track: Track, publication: TrackPublication, trackParticipant: Participant) => {
if (trackParticipant.identity === participant.identity && publication.source === Track.Source.Microphone) {
track.attach(el); track.attach(el);
el.play().catch(() => {}); el.play().catch(() => {});
} }
}; };
room.on('trackSubscribed' as any, handleSubscribed); room.on(RoomEvent.TrackSubscribed, handleSubscribed);
return () => { return () => {
detachTrack(); if (pub?.track) pub.track.detach(el);
room.off('trackPublished' as any, handlePublished); room.off(RoomEvent.TrackSubscribed, handleSubscribed);
room.off('trackSubscribed' as any, handleSubscribed);
}; };
}, [participant, room]); }, [participant, room]);