mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-12 19:56:53 +00:00
🔧(frontend) sync persisted device ids with the actual selected devices
Now that the exact deviceId constraint has been dropped, the browser can pick a different device than the one persisted in localStorage (for example when the persisted device is no longer available). Sync the persisted ids in localStorage with the device id that was actually selected on the started track, so the local cache stays consistent with what the app is really using.
This commit is contained in:
committed by
aleb_the_flash
parent
aaa51a4457
commit
751d029ac9
@@ -16,6 +16,7 @@ and this project adheres to
|
||||
|
||||
- ♻️(frontend) encapsulate error tracking behind a telemetry module
|
||||
- ♻️(frontend) encapsulate PostHog capture calls in the telemetry module
|
||||
- 🔧(frontend) sync persisted device ids with the actual selected devices
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ import {
|
||||
import { saveUsername, userStore } from '@/stores/user'
|
||||
|
||||
import { useCannotUseDevice } from '../livekit/hooks/useCannotUseDevice'
|
||||
import { useSyncTrackDeviceId } from '../livekit/hooks/useSyncTrackDeviceId'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import { useUser } from '@/features/auth/api/useUser'
|
||||
import { useConfig } from '@/api/useConfig'
|
||||
@@ -274,6 +275,8 @@ export const Join = ({
|
||||
const videoTrack = dynamicVideoTrack || previewVideoTrack
|
||||
const audioTrack = dynamicAudioTrack || previewAudioTrack
|
||||
|
||||
useSyncTrackDeviceId(audioTrack, saveAudioInputDeviceId)
|
||||
useSyncTrackDeviceId(videoTrack, saveVideoInputDeviceId)
|
||||
|
||||
const videoEl = useRef(null)
|
||||
const isVideoInitiated = useRef(false)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { useLocalParticipant } from '@livekit/components-react'
|
||||
import type { LocalTrack } from 'livekit-client'
|
||||
import { useSyncTrackDeviceId } from '../hooks/useSyncTrackDeviceId'
|
||||
import {
|
||||
saveAudioInputDeviceId,
|
||||
saveVideoInputDeviceId,
|
||||
} from '@/stores/userChoices'
|
||||
|
||||
export const SyncDevicePreferences = () => {
|
||||
const { cameraTrack, microphoneTrack } = useLocalParticipant()
|
||||
useSyncTrackDeviceId(
|
||||
cameraTrack?.track as LocalTrack | undefined,
|
||||
saveVideoInputDeviceId
|
||||
)
|
||||
useSyncTrackDeviceId(
|
||||
microphoneTrack?.track as LocalTrack | undefined,
|
||||
saveAudioInputDeviceId
|
||||
)
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useEffect } from 'react'
|
||||
import { TrackEvent, type LocalTrack } from 'livekit-client'
|
||||
|
||||
/**
|
||||
* Keeps the persisted preference aligned with the track's actual device.
|
||||
* The track is the source of truth, not the store.
|
||||
*
|
||||
* Syncs on mount and TrackEvent.Restarted, covering acquisition/restart,
|
||||
* setDeviceId switches, unmute re-acquisition, and browser fallback.
|
||||
*
|
||||
* Skip persisting the raw "default" alias: it means "follow the OS default"
|
||||
* and resolving it would pin the preference to a concrete device.
|
||||
*/
|
||||
export const useSyncTrackDeviceId = (
|
||||
track: LocalTrack | undefined,
|
||||
save: (deviceId: string) => void
|
||||
) => {
|
||||
useEffect(() => {
|
||||
if (!track) return
|
||||
let cancelled = false
|
||||
const sync = () => {
|
||||
track
|
||||
.getDeviceId(false)
|
||||
.then((deviceId) => {
|
||||
if (!cancelled && deviceId) {
|
||||
save(deviceId)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// A track without settings (ended, screen share) has no id to sync.
|
||||
})
|
||||
}
|
||||
sync()
|
||||
track.on(TrackEvent.Restarted, sync)
|
||||
return () => {
|
||||
cancelled = true
|
||||
track.off(TrackEvent.Restarted, sync)
|
||||
}
|
||||
}, [track, save])
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import { PipRoomPlaceholder } from '@/features/pip/components/PipRoomPlaceholder
|
||||
import { StageLayout } from '@/features/layout/components/StageLayout'
|
||||
import { PinAnnouncer } from '@/features/layout/components/PinAnnouncer'
|
||||
import { ChatProvider } from '@/features/chat/components/ChatProvider'
|
||||
import { SyncDevicePreferences } from '@/features/rooms/livekit/components/SyncDevicePreferences'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -65,6 +66,7 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
|
||||
<>
|
||||
<RoomMetadataSynchronizer />
|
||||
<ConnectionObserver />
|
||||
<SyncDevicePreferences />
|
||||
<MediaStateObserver />
|
||||
<ChatProvider />
|
||||
<VideoResolutionSubscription />
|
||||
|
||||
Reference in New Issue
Block a user