feat(voice): persist A/V device preferences in localStorage
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useVoiceStore } from '../stores/voice.ts';
|
import { useVoiceStore } from '../stores/voice.ts';
|
||||||
|
import { saveDevicePref } from '../stores/voice.ts';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -48,6 +49,7 @@ export function DeviceSettingsModal({ onClose }: Props) {
|
|||||||
if (!room) return;
|
if (!room) return;
|
||||||
try {
|
try {
|
||||||
await room.switchActiveDevice(kind, deviceId);
|
await room.switchActiveDevice(kind, deviceId);
|
||||||
|
saveDevicePref(kind, deviceId);
|
||||||
if (kind === 'audioinput') setActiveAudioInput(deviceId);
|
if (kind === 'audioinput') setActiveAudioInput(deviceId);
|
||||||
if (kind === 'audiooutput') setActiveAudioOutput(deviceId);
|
if (kind === 'audiooutput') setActiveAudioOutput(deviceId);
|
||||||
if (kind === 'videoinput') setActiveVideoInput(deviceId);
|
if (kind === 'videoinput') setActiveVideoInput(deviceId);
|
||||||
|
|||||||
@@ -64,6 +64,42 @@ interface VoiceState {
|
|||||||
dismissWhisper: (timestamp: number) => void;
|
dismissWhisper: (timestamp: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEVICE_PREFS_KEY = 'dc_voice_device_prefs';
|
||||||
|
|
||||||
|
interface DevicePrefs {
|
||||||
|
audioInput?: string;
|
||||||
|
audioOutput?: string;
|
||||||
|
videoInput?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadDevicePrefs(): DevicePrefs {
|
||||||
|
try {
|
||||||
|
return JSON.parse(localStorage.getItem(DEVICE_PREFS_KEY) || '{}');
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveDevicePrefs(prefs: DevicePrefs) {
|
||||||
|
localStorage.setItem(DEVICE_PREFS_KEY, JSON.stringify(prefs));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveDevicePref(kind: MediaDeviceKind, deviceId: string) {
|
||||||
|
const prefs = loadDevicePrefs();
|
||||||
|
if (kind === 'audioinput') prefs.audioInput = deviceId;
|
||||||
|
else if (kind === 'audiooutput') prefs.audioOutput = deviceId;
|
||||||
|
else if (kind === 'videoinput') prefs.videoInput = deviceId;
|
||||||
|
saveDevicePrefs(prefs);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSavedDeviceId(kind: MediaDeviceKind): string | undefined {
|
||||||
|
const prefs = loadDevicePrefs();
|
||||||
|
if (kind === 'audioinput') return prefs.audioInput;
|
||||||
|
if (kind === 'audiooutput') return prefs.audioOutput;
|
||||||
|
if (kind === 'videoinput') return prefs.videoInput;
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
function participantToVoice(p: Participant): VoiceParticipant {
|
function participantToVoice(p: Participant): VoiceParticipant {
|
||||||
const micPub = p.getTrackPublication(Track.Source.Microphone);
|
const micPub = p.getTrackPublication(Track.Source.Microphone);
|
||||||
const camPub = p.getTrackPublication(Track.Source.Camera);
|
const camPub = p.getTrackPublication(Track.Source.Camera);
|
||||||
@@ -215,6 +251,16 @@ export const useVoiceStore = create<VoiceState>((set, get) => ({
|
|||||||
console.warn("[voice] failed to set initial mute state:", micErr);
|
console.warn("[voice] failed to set initial mute state:", micErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore saved device preferences
|
||||||
|
const prefs = loadDevicePrefs();
|
||||||
|
try {
|
||||||
|
if (prefs.audioInput) await room.switchActiveDevice('audioinput', prefs.audioInput);
|
||||||
|
if (prefs.audioOutput) await room.switchActiveDevice('audiooutput', prefs.audioOutput);
|
||||||
|
if (prefs.videoInput) await room.switchActiveDevice('videoinput', prefs.videoInput);
|
||||||
|
} catch (devErr) {
|
||||||
|
console.warn("[voice] failed to restore saved devices:", devErr);
|
||||||
|
}
|
||||||
|
|
||||||
set({ isJoining: false });
|
set({ isJoining: false });
|
||||||
|
|
||||||
// Notify WebSocket peers
|
// Notify WebSocket peers
|
||||||
|
|||||||
Reference in New Issue
Block a user