Files
glchat/web/src/pages/settings/VoiceSettingsSection.tsx
T

65 lines
2.3 KiB
TypeScript
Raw Normal View History

import { useTranslation } from 'react-i18next';
import { VolumeSlider, VoiceDeviceList } from '@/components/voice/VoiceControls';
import { useDeviceChoice } from '@/lib/useMediaDevices';
import { useVoiceStore } from '@/stores/voice';
import { SettingsSection } from '@/pages/settings/SettingsSection';
/**
* «Аудио-видео»: выбор устройств ввода/вывода и громкости.
*
* Значения хранятся локально (zustand + localStorage) и применяются на лету:
* выбранное устройство сразу переключается в активной голосовой сессии.
*/
export function VoiceSettingsSection() {
const { t } = useTranslation();
const mic = useDeviceChoice('audioinput');
const camera = useDeviceChoice('videoinput');
const output = useDeviceChoice('audiooutput');
const micVolume = useVoiceStore((state) => state.micVolume);
const outputVolume = useVoiceStore((state) => state.outputVolume);
const setMicVolume = useVoiceStore((state) => state.setMicVolume);
const setOutputVolume = useVoiceStore((state) => state.setOutputVolume);
return (
<SettingsSection
title={t('settings.voice.title')}
description={t('settings.voice.description')}
>
<div className="mt-4 grid gap-4 sm:grid-cols-2">
<VoiceDeviceList
kind="audioinput"
label={t('settings.voice.input')}
value={mic.value}
onChange={mic.select}
/>
<VoiceDeviceList
kind="videoinput"
label={t('settings.voice.camera')}
value={camera.value}
onChange={camera.select}
/>
<VoiceDeviceList
kind="audiooutput"
label={t('settings.voice.output')}
value={output.value}
onChange={output.select}
/>
<div className="flex flex-col justify-end gap-2">
<VolumeSlider
label={t('settings.voice.micVolume')}
value={micVolume}
onChange={setMicVolume}
/>
<VolumeSlider
label={t('settings.voice.outputVolume')}
value={outputVolume}
onChange={setOutputVolume}
/>
</div>
</div>
<p className="mt-4 text-xs text-fg-muted">{t('settings.voice.stub')}</p>
</SettingsSection>
);
}