feat: Add Picture-in-Picture floating video + fix local track visibility

- New PictureInPicture component: draggable floating window that shows
  active stream when navigating away from voice channel, with LIVE badge,
  snap-to-edge, click-to-navigate-back
- Fix VoiceUser to check actual track presence instead of boolean flags
  for video rendering
- Add LocalTrackPublished/LocalTrackUnpublished events to useLiveKit
  so local screen share and camera show immediately in VoiceGrid
- Add pipCollapsed state to uiStore
This commit is contained in:
Jannis Braun
2026-02-19 05:26:06 +01:00
parent d88c72aa62
commit 2e309bf959
10 changed files with 546 additions and 3 deletions
+10
View File
@@ -142,6 +142,9 @@ export function useLiveKit() {
newRoom.on(RoomEvent.ParticipantConnected, guardedUpdate);
newRoom.on(RoomEvent.ParticipantDisconnected, guardedUpdate);
newRoom.on(RoomEvent.TrackSubscribed, guardedUpdate);
newRoom.on(RoomEvent.TrackUnsubscribed, guardedUpdate);
newRoom.on(RoomEvent.LocalTrackPublished, guardedUpdate);
newRoom.on(RoomEvent.LocalTrackUnpublished, guardedUpdate);
newRoom.on(RoomEvent.ConnectionStateChanged, (state) => {
if (roomRef.current === newRoom) {
const connected = state === ConnectionState.Connected;
@@ -174,6 +177,13 @@ export function useLiveKit() {
if (gen !== _connectGeneration) return;
const newRoom = new Room({ adaptiveStream: false, dynacast: false, publishDefaults: { videoCodec: 'h264', simulcast: false } });
roomRef.current = newRoom;
const guardedUpdate = () => { if (roomRef.current === newRoom) updateParticipants(); };
newRoom.on(RoomEvent.ParticipantConnected, guardedUpdate);
newRoom.on(RoomEvent.ParticipantDisconnected, guardedUpdate);
newRoom.on(RoomEvent.TrackSubscribed, guardedUpdate);
newRoom.on(RoomEvent.TrackUnsubscribed, guardedUpdate);
newRoom.on(RoomEvent.LocalTrackPublished, guardedUpdate);
newRoom.on(RoomEvent.LocalTrackUnpublished, guardedUpdate);
newRoom.on(RoomEvent.ConnectionStateChanged, (state) => {
if (roomRef.current === newRoom) {
const connected = state === ConnectionState.Connected;