Мини-плеер намеренно вёл себя иначе, чем основное окно: без удержания демонстрации экрана (holdScreenShare), без приоритета говорящего с включённой камерой, без антидребезга говорящего и с собственным чистым useState для закрепления. На практике это читалось как поломка — закрепление, сделанное в основном окне, в мини-окне не действовало, а демонстрация экрана пропадала, стоило кому-то сказать слово. Теперь pickStageFocus получает одинаковые правила в обоих вариантах сцены. Единственное сознательное отличие — localKey («показать себя» последним фолбэком), он остаётся только у мини-плеера: это защита от дефекта 0.0.11, когда мини-окно открывалось на самом пользователе. Закрепление переезжает между окнами тем же мостиком через RoomPage, что и фокус (initialPinnedKey/onPinnedKeyChange). Отдельный общий источник правды не нужен: экземпляр сцены в каждый момент ровно один — пока открыт Document PiP, основное окно показывает заглушку. Заодно в снятии закрепления «участник вышел из комнаты» добавлена охрана tracksKnown. На первом рендере нового экземпляра сцены useTracks отдаёт пустой массив, и пустой набор читался как «все вышли»: приехавшее через initialPinnedKey закрепление обнулялось прямо при монтировании, то есть мини-плеер терял его каждый раз. Надпись на булавке — «Закрепить» вместо «Закрепить в основном окне»: закрепление больше не ограничено основным окном.
16 KiB
16 KiB