feat: Voice UI overhaul — fix black tiles, focus mode, track lifecycle
- Fix black screen when streams end by checking track readyState === 'live' - Add track 'ended' event listeners in VoiceUser for immediate fallback to avatar - Add visible "Grid" button to exit focus mode (replaces undiscoverable double-click) - Auto-focus screen sharers, auto-unfocus when they stop sharing - Add LIVE badge, speaking glow shadow, screen share object-contain - Add TrackMuted/TrackUnmuted/ActiveSpeakersChanged Room events - Fix PiP video attachment with shouldShow dependency
This commit is contained in:
@@ -81,12 +81,15 @@ export function useLiveKit() {
|
||||
const track = pub.track;
|
||||
if (!track)
|
||||
return;
|
||||
const mt = track.mediaStreamTrack;
|
||||
if (!mt || mt.readyState !== 'live')
|
||||
return;
|
||||
if (pub.source === Track.Source.Microphone)
|
||||
audioTrack = track.mediaStreamTrack;
|
||||
audioTrack = mt;
|
||||
else if (pub.source === Track.Source.Camera)
|
||||
videoTrack = track.mediaStreamTrack;
|
||||
videoTrack = mt;
|
||||
else if (pub.source === Track.Source.ScreenShare)
|
||||
screenTrack = track.mediaStreamTrack;
|
||||
screenTrack = mt;
|
||||
});
|
||||
allParticipants.push({ identity: p.identity, userId, username, isSpeaking: p.isSpeaking, isMuted: !p.isMicrophoneEnabled, isCameraOn: p.isCameraEnabled, isScreenSharing: p.isScreenShareEnabled, isLocal, audioTrack, videoTrack, screenTrack });
|
||||
};
|
||||
@@ -122,6 +125,9 @@ export function useLiveKit() {
|
||||
newRoom.on(RoomEvent.TrackUnsubscribed, guardedUpdate);
|
||||
newRoom.on(RoomEvent.LocalTrackPublished, guardedUpdate);
|
||||
newRoom.on(RoomEvent.LocalTrackUnpublished, guardedUpdate);
|
||||
newRoom.on(RoomEvent.TrackMuted, guardedUpdate);
|
||||
newRoom.on(RoomEvent.TrackUnmuted, guardedUpdate);
|
||||
newRoom.on(RoomEvent.ActiveSpeakersChanged, guardedUpdate);
|
||||
newRoom.on(RoomEvent.ConnectionStateChanged, (state) => {
|
||||
if (roomRef.current === newRoom) {
|
||||
const connected = state === ConnectionState.Connected;
|
||||
@@ -192,6 +198,9 @@ export function useLiveKit() {
|
||||
newRoom.on(RoomEvent.TrackUnsubscribed, guardedUpdate);
|
||||
newRoom.on(RoomEvent.LocalTrackPublished, guardedUpdate);
|
||||
newRoom.on(RoomEvent.LocalTrackUnpublished, guardedUpdate);
|
||||
newRoom.on(RoomEvent.TrackMuted, guardedUpdate);
|
||||
newRoom.on(RoomEvent.TrackUnmuted, guardedUpdate);
|
||||
newRoom.on(RoomEvent.ActiveSpeakersChanged, guardedUpdate);
|
||||
newRoom.on(RoomEvent.ConnectionStateChanged, (state) => {
|
||||
if (roomRef.current === newRoom) {
|
||||
const connected = state === ConnectionState.Connected;
|
||||
|
||||
@@ -115,9 +115,11 @@ export function useLiveKit() {
|
||||
p.trackPublications.forEach((pub) => {
|
||||
const track = pub.track;
|
||||
if (!track) return;
|
||||
if (pub.source === Track.Source.Microphone) audioTrack = track.mediaStreamTrack;
|
||||
else if (pub.source === Track.Source.Camera) videoTrack = track.mediaStreamTrack;
|
||||
else if (pub.source === Track.Source.ScreenShare) screenTrack = track.mediaStreamTrack;
|
||||
const mt = track.mediaStreamTrack;
|
||||
if (!mt || mt.readyState !== 'live') return;
|
||||
if (pub.source === Track.Source.Microphone) audioTrack = mt;
|
||||
else if (pub.source === Track.Source.Camera) videoTrack = mt;
|
||||
else if (pub.source === Track.Source.ScreenShare) screenTrack = mt;
|
||||
});
|
||||
allParticipants.push({ identity: p.identity, userId, username, isSpeaking: p.isSpeaking, isMuted: !p.isMicrophoneEnabled, isCameraOn: p.isCameraEnabled, isScreenSharing: p.isScreenShareEnabled, isLocal, audioTrack, videoTrack, screenTrack });
|
||||
};
|
||||
@@ -145,6 +147,9 @@ export function useLiveKit() {
|
||||
newRoom.on(RoomEvent.TrackUnsubscribed, guardedUpdate);
|
||||
newRoom.on(RoomEvent.LocalTrackPublished, guardedUpdate);
|
||||
newRoom.on(RoomEvent.LocalTrackUnpublished, guardedUpdate);
|
||||
newRoom.on(RoomEvent.TrackMuted, guardedUpdate);
|
||||
newRoom.on(RoomEvent.TrackUnmuted, guardedUpdate);
|
||||
newRoom.on(RoomEvent.ActiveSpeakersChanged, guardedUpdate);
|
||||
newRoom.on(RoomEvent.ConnectionStateChanged, (state) => {
|
||||
if (roomRef.current === newRoom) {
|
||||
const connected = state === ConnectionState.Connected;
|
||||
@@ -184,6 +189,9 @@ export function useLiveKit() {
|
||||
newRoom.on(RoomEvent.TrackUnsubscribed, guardedUpdate);
|
||||
newRoom.on(RoomEvent.LocalTrackPublished, guardedUpdate);
|
||||
newRoom.on(RoomEvent.LocalTrackUnpublished, guardedUpdate);
|
||||
newRoom.on(RoomEvent.TrackMuted, guardedUpdate);
|
||||
newRoom.on(RoomEvent.TrackUnmuted, guardedUpdate);
|
||||
newRoom.on(RoomEvent.ActiveSpeakersChanged, guardedUpdate);
|
||||
newRoom.on(RoomEvent.ConnectionStateChanged, (state) => {
|
||||
if (roomRef.current === newRoom) {
|
||||
const connected = state === ConnectionState.Connected;
|
||||
|
||||
Reference in New Issue
Block a user