diff --git a/src/renderer/src/components/Modules/NethVoice/BaseModule/ProfileDialog/SettingsSettings/SettingsDevicesDialog.tsx b/src/renderer/src/components/Modules/NethVoice/BaseModule/ProfileDialog/SettingsSettings/SettingsDevicesDialog.tsx
index c4fb824f..b41e3672 100644
--- a/src/renderer/src/components/Modules/NethVoice/BaseModule/ProfileDialog/SettingsSettings/SettingsDevicesDialog.tsx
+++ b/src/renderer/src/components/Modules/NethVoice/BaseModule/ProfileDialog/SettingsSettings/SettingsDevicesDialog.tsx
@@ -73,7 +73,7 @@ export function SettingsDeviceDialog() {
videoInput: z.string(),
})
- const { handleSubmit, control, setValue } = useForm({
+ const { handleSubmit, control, setValue, watch } = useForm({
defaultValues: {
audioInput: '',
audioOutput: '',
@@ -82,6 +82,8 @@ export function SettingsDeviceDialog() {
resolver: zodResolver(schema),
})
+ const formValues = watch()
+
useEffect(() => {
initDevices()
}, [])
@@ -101,10 +103,21 @@ export function SettingsDeviceDialog() {
return storeValue || ''
}
- setValue('audioInput', getEffectiveValue('audioInput'))
- setValue('audioOutput', getEffectiveValue('audioOutput'))
- setValue('videoInput', getEffectiveValue('videoInput'))
- }, [account?.preferredDevices])
+ const audioInputValue = getEffectiveValue('audioInput')
+ const audioOutputValue = getEffectiveValue('audioOutput')
+ const videoInputValue = getEffectiveValue('videoInput')
+
+ // Only set values if they are actually different to prevent unnecessary re-renders
+ if (formValues.audioInput !== audioInputValue) {
+ setValue('audioInput', audioInputValue, { shouldDirty: false })
+ }
+ if (formValues.audioOutput !== audioOutputValue) {
+ setValue('audioOutput', audioOutputValue, { shouldDirty: false })
+ }
+ if (formValues.videoInput !== videoInputValue) {
+ setValue('videoInput', videoInputValue, { shouldDirty: false })
+ }
+ }, [account?.preferredDevices, setValue, formValues.audioInput, formValues.audioOutput, formValues.videoInput])
useEffect(() => {
const handleStorageChange = (e: StorageEvent) => {
@@ -116,7 +129,13 @@ export function SettingsDeviceDialog() {
if (changedDeviceType && e.newValue) {
console.log(`localStorage changed for ${changedDeviceType}:`, e.newValue)
- setValue(changedDeviceType, e.newValue)
+ try {
+ const parsed = JSON.parse(e.newValue)
+ const deviceId = parsed.deviceId || e.newValue
+ setValue(changedDeviceType, deviceId, { shouldDirty: false })
+ } catch {
+ setValue(changedDeviceType, e.newValue, { shouldDirty: false })
+ }
}
}
@@ -126,8 +145,8 @@ export function SettingsDeviceDialog() {
const getDeviceById = useCallback(
(type: DeviceType, id: string): MediaDeviceInfo | undefined => {
- if (!devices) return undefined
- return devices[type].find((d) => d.deviceId === id)
+ if (!devices || !devices[type] || !id) return undefined
+ return devices[type].find((d) => d && d.deviceId === id)
},
[devices],
)
@@ -135,21 +154,31 @@ export function SettingsDeviceDialog() {
const initDevices = async () => {
const devices = await getMediaDevices()
Log.info('Available devices:', devices)
- setDevices(devices)
+ if (devices?.audioOutput) {
+ Log.info('Audio output device IDs:', devices.audioOutput.map(d => ({ id: d.deviceId, label: d.label })))
+ }
+ if (devices) {
+ setDevices(devices)
+ }
}
async function getMediaDevices() {
try {
+ if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
+ console.warn('Media devices API not available')
+ return { audioInput: [], audioOutput: [], videoInput: [] }
+ }
+
const devices = await navigator.mediaDevices.enumerateDevices()
- const audioInput = devices.filter((device) => device.kind === 'audioinput')
- const audioOutput = devices.filter((device) => device.kind === 'audiooutput')
- const videoInput = devices.filter((device) => device.kind === 'videoinput')
+ const audioInput = devices.filter((device) => device && device.kind === 'audioinput')
+ const audioOutput = devices.filter((device) => device && device.kind === 'audiooutput')
+ const videoInput = devices.filter((device) => device && device.kind === 'videoinput')
return { audioInput, audioOutput, videoInput }
} catch (err) {
console.error('Error reading audio and video devices:', err)
- return null
+ return { audioInput: [], audioOutput: [], videoInput: [] }
}
}
@@ -197,30 +226,51 @@ export function SettingsDeviceDialog() {