forked from coracle/flotilla
fix: resync voice state after LiveKit reconnect
This commit is contained in:
@@ -92,6 +92,27 @@ const syncParticipantMedia = (participant: Participant) => {
|
||||
})
|
||||
}
|
||||
|
||||
// LiveKit does not emit ParticipantConnected/Disconnected during reconnect.
|
||||
const resyncAfterReconnect = (room: LiveKitRoom) => {
|
||||
const next = new Map<string, {muted: boolean; cameraOn: boolean}>()
|
||||
for (const p of [room.localParticipant, ...room.remoteParticipants.values()]) {
|
||||
next.set(p.identity, {muted: !p.isMicrophoneEnabled, cameraOn: p.isCameraEnabled})
|
||||
}
|
||||
participantMediaState.set(next)
|
||||
|
||||
const session = get(currentVoiceSession)
|
||||
if (session?.room !== room) return
|
||||
|
||||
const {localParticipant} = room
|
||||
voiceMicMuted.set(!localParticipant.isMicrophoneEnabled)
|
||||
currentVoiceSession.set({
|
||||
...session,
|
||||
cameraOn: localParticipant.isCameraEnabled,
|
||||
screenShareOn: localParticipant.isScreenShareEnabled,
|
||||
})
|
||||
triggerVideoFeedCount()
|
||||
}
|
||||
|
||||
const onParticipantMediaChanged = (_publication: TrackPublication, participant: Participant) => {
|
||||
syncParticipantMedia(participant)
|
||||
}
|
||||
@@ -191,6 +212,11 @@ const setUpMicrophone = async (
|
||||
// (after switching calls or an engine reconnect give-up) must not clobber it.
|
||||
let activeRoom: LiveKitRoom | undefined
|
||||
|
||||
const makeOnRoomReconnected = (room: LiveKitRoom) => () => {
|
||||
if (room !== activeRoom) return
|
||||
resyncAfterReconnect(room)
|
||||
}
|
||||
|
||||
const makeOnRoomDisconnected = (room: LiveKitRoom) => (reason?: DisconnectReason) => {
|
||||
// Ignore disconnects from rooms that are no longer the active session.
|
||||
if (room !== activeRoom) return
|
||||
@@ -320,6 +346,7 @@ export const joinVoiceRoom = async (
|
||||
activeRoom = liveKitRoom
|
||||
|
||||
liveKitRoom.on(RoomEvent.Disconnected, makeOnRoomDisconnected(liveKitRoom))
|
||||
liveKitRoom.on(RoomEvent.Reconnected, makeOnRoomReconnected(liveKitRoom))
|
||||
liveKitRoom.on(RoomEvent.ParticipantConnected, onParticipantConnected)
|
||||
liveKitRoom.on(RoomEvent.ParticipantDisconnected, onParticipantDisconnected)
|
||||
liveKitRoom.on(RoomEvent.TrackSubscribed, onTrackSubscribed)
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
voiceMicMuted,
|
||||
voiceState,
|
||||
} from "@app/call/stores"
|
||||
import {cancelJoinVoiceRoom, leaveVoiceRoom, toggleMute} from "@app/call/voice"
|
||||
import {cancelJoinVoiceRoom, joinVoiceRoom, leaveVoiceRoom, toggleMute} from "@app/call/voice"
|
||||
|
||||
const {relay, h} = $derived($page.params)
|
||||
const url = $derived(relay ? decodeRelay(relay) : undefined)
|
||||
@@ -86,6 +86,11 @@
|
||||
pushModal(VoiceRoomJoinDialog, {url: targetRoom.url, h: targetRoom.h})
|
||||
}
|
||||
|
||||
const onReconnect = () => {
|
||||
if (!targetRoom) return
|
||||
void joinVoiceRoom(targetRoom.url, targetRoom.h)
|
||||
}
|
||||
|
||||
const goToRoom = () => {
|
||||
if (!targetRoom) return
|
||||
const path = makeRoomPath(targetRoom.url, targetRoom.h)
|
||||
@@ -237,6 +242,13 @@
|
||||
onclick={leaveVoiceRoom}>
|
||||
<Icon icon={PhoneRounded} size={4} />
|
||||
</Button>
|
||||
{:else if $currentVoiceRoom}
|
||||
<Button
|
||||
data-tip="Reconnect"
|
||||
class="center tooltip tooltip-top btn btn-sm btn-square btn-success"
|
||||
onclick={onReconnect}>
|
||||
<Icon icon={PhoneCallingRounded} size={4} />
|
||||
</Button>
|
||||
{:else}
|
||||
<Button
|
||||
data-tip="Join Voice"
|
||||
|
||||
Reference in New Issue
Block a user