/* Contrôles audio depuis un pop-up + raccourci mute haut-parleur. */ (() => { 'use strict'; const panel = document.getElementById('audioSettingsPanel'); const button = document.getElementById('audioSettingsButton'); const close = document.getElementById('closeAudioSettings'); const speaker = document.getElementById('speakerMuteQuick'); const mic = document.getElementById('micMute'); const volume = document.getElementById('volumeSlider'); const volumeValue = document.getElementById('volumeValue'); const gain = document.getElementById('micGainSlider'); const gainValue = document.getElementById('micGainValue'); const message = document.getElementById('audioSettingsMessage'); let settings = { volume:70, mic_gain:null, speaker_muted:false, mic_muted:false }; let volumeTimer, gainTimer; function render() { volume.value = settings.volume; volumeValue.textContent = `${settings.volume} %`; gain.disabled = !Number.isFinite(settings.mic_gain); if (!gain.disabled) gain.value = settings.mic_gain; gainValue.textContent = gain.disabled ? 'N/D' : `${settings.mic_gain} %`; speaker.setAttribute('aria-pressed', String(settings.speaker_muted)); speaker.setAttribute('aria-label', settings.speaker_muted ? 'Réactiver le son' : 'Couper le son'); speaker.title = speaker.getAttribute('aria-label'); mic.setAttribute('aria-pressed', String(settings.mic_muted)); mic.textContent = settings.mic_muted ? 'Coupé' : 'Actif'; mic.title = settings.mic_muted ? 'Réactiver le microphone' : 'Couper le microphone'; } async function update(changes) { message.textContent = ''; try { const response = await fetch('/api/audio/settings', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(changes) }); const data = await response.json(); if (!response.ok) throw new Error(data.error || `HTTP ${response.status}`); settings = { ...settings, ...data }; render(); } catch (err) { message.textContent = `Impossible de modifier le réglage : ${err.message}`; console.warn('[ALFRED AUDIO]', err); await refresh(); } } async function refresh() { try { const response = await fetch('/api/audio/settings', {cache:'no-store'}); if (!response.ok) throw new Error(`HTTP ${response.status}`); settings = { ...settings, ...await response.json() }; render(); } catch (err) { message.textContent = 'Réglages indisponibles.'; console.warn('[ALFRED AUDIO]', err); } } function setOpen(open) { panel.hidden = !open; button.setAttribute('aria-expanded', String(open)); if (open) { refresh(); close.focus(); } else { button.focus(); } } button.addEventListener('click', () => setOpen(panel.hidden)); close.addEventListener('click', () => setOpen(false)); document.addEventListener('pointerdown', e => { if (!panel.hidden && !panel.contains(e.target) && !button.contains(e.target)) { panel.hidden = true; button.setAttribute('aria-expanded', 'false'); } }); document.addEventListener('keydown', e => { if (e.key === 'Escape' && !panel.hidden) setOpen(false); }); volume.addEventListener('input', () => { settings.volume = Number(volume.value); render(); clearTimeout(volumeTimer); volumeTimer = setTimeout(() => update({volume:Number(volume.value)}), 220); }); gain.addEventListener('input', () => { settings.mic_gain = Number(gain.value); render(); clearTimeout(gainTimer); gainTimer = setTimeout(() => update({mic_gain:Number(gain.value)}), 250); }); speaker.addEventListener('click', () => update({speaker_muted:!settings.speaker_muted})); mic.addEventListener('click', () => update({mic_muted:!settings.mic_muted})); if (window.alfredSocket) window.alfredSocket.on('audio_settings', data => { settings = {...settings, ...data}; render(); }); render(); refresh(); })();