// ============================================================ // TRANSCRIPTION SETTINGS — Browser Whisper + Web Speech API // ============================================================ (function() { var _inited = false; document.addEventListener('tabChanged', function(e) { if (e.detail.tab !== 'settings' || _inited) return; _inited = true; initTranscriptionSettings(); }); // Also init on direct page load if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { setTimeout(function() { if (!_inited && document.getElementById('browser-whisper-enabled')) { _inited = true; initTranscriptionSettings(); } }, 500); }); } else { setTimeout(function() { if (!_inited && document.getElementById('browser-whisper-enabled')) { _inited = true; initTranscriptionSettings(); } }, 500); } function initTranscriptionSettings() { console.log('[TranscriptionSettings] Initializing...'); // ── Browser Whisper ────────────────────────────────────── var whisperCheckbox = document.getElementById('browser-whisper-enabled'); var whisperStatus = document.getElementById('browser-whisper-status'); var whisperModel = document.getElementById('browser-whisper-model'); var whisperPreload = document.getElementById('btn-whisper-preload'); var whisperProgress = document.getElementById('browser-whisper-progress'); var whisperProgressText = document.getElementById('browser-whisper-progress-text'); if (whisperCheckbox && window.BrowserWhisper) { whisperCheckbox.checked = BrowserWhisper.isEnabled(); whisperStatus.textContent = BrowserWhisper.isEnabled() ? 'On — audio stays on device' : 'Off'; if (whisperModel) { whisperModel.value = BrowserWhisper.getModel(); } whisperCheckbox.addEventListener('change', function() { BrowserWhisper.setEnabled(whisperCheckbox.checked); whisperStatus.textContent = whisperCheckbox.checked ? 'On — audio stays on device' : 'Off'; if (whisperCheckbox.checked) { // Auto-preload on enable BrowserWhisper.preload(function(file, pct) { if (whisperProgress && whisperProgressText) { if (pct >= 100) { whisperProgress.style.display = 'none'; return; } whisperProgress.style.display = 'block'; whisperProgressText.textContent = file + (pct > 0 ? ' ' + pct + '%' : ''); } }); } }); if (whisperModel) { whisperModel.addEventListener('change', function() { BrowserWhisper.setModel(whisperModel.value); }); } if (whisperPreload) { whisperPreload.addEventListener('click', function() { if (!BrowserWhisper || !BrowserWhisper.isSupported()) { showToast('Browser Whisper not supported', 'error'); return; } whisperPreload.disabled = true; whisperPreload.innerHTML = ' Downloading...'; whisperProgress.style.display = 'block'; whisperProgressText.textContent = 'Initializing...'; BrowserWhisper.setEnabled(true); whisperCheckbox.checked = true; whisperStatus.textContent = 'On — audio stays on device'; BrowserWhisper.preload(function(file, pct) { if (pct >= 100) { whisperProgress.style.display = 'none'; whisperPreload.disabled = false; whisperPreload.innerHTML = ' Pre-download model'; showToast('Whisper model ready!', 'success'); return; } whisperProgress.style.display = 'block'; whisperProgressText.textContent = file + (pct > 0 ? ' ' + pct + '%' : ''); }); }); } } // ── Web Speech Recognition ─────────────────────────────── var speechCheckbox = document.getElementById('web-speech-enabled'); var speechStatus = document.getElementById('web-speech-status'); var speechBrowserInfo = document.getElementById('web-speech-browser-info'); if (speechCheckbox && window.WebSpeechRecognition) { speechCheckbox.checked = WebSpeechRecognition.isEnabled(); speechStatus.textContent = WebSpeechRecognition.isEnabled() ? 'On — real-time streaming' : 'Off'; // Show privacy info if (speechBrowserInfo) { var privacyInfo = WebSpeechRecognition.getPrivacyInfo(); speechBrowserInfo.innerHTML = 'Provider: ' + privacyInfo.provider + '
' + 'Privacy: ' + privacyInfo.privacy + '
' + '⚠️ ' + privacyInfo.warning + ''; } speechCheckbox.addEventListener('change', function() { if (speechCheckbox.checked) { // Show confirmation for privacy warning showConfirm( 'WARNING: Real-time streaming uses your browser\'s speech recognition, ' + 'which may send audio to cloud servers (e.g., Google). ' + 'This is NOT HIPAA-compliant. ' + 'Only enable if you understand and accept this privacy trade-off.', function() { // Disable Browser Whisper if enabling Web Speech if (whisperCheckbox && whisperCheckbox.checked) { whisperCheckbox.checked = false; BrowserWhisper.setEnabled(false); whisperStatus.textContent = 'Off'; showToast('Browser Whisper disabled (Web Speech takes priority)', 'info'); } WebSpeechRecognition.setEnabled(true); speechStatus.textContent = 'On — real-time streaming'; }, { danger: true, confirmText: 'Enable' } ); // Revert checkbox until confirmed speechCheckbox.checked = false; return; } WebSpeechRecognition.setEnabled(false); speechStatus.textContent = 'Off'; }); // If not supported, disable and show message if (!WebSpeechRecognition.isSupported()) { speechCheckbox.disabled = true; speechStatus.textContent = 'Not supported in this browser'; if (speechBrowserInfo) { speechBrowserInfo.innerHTML = 'Not supported - Web Speech API not available in this browser.'; } } } console.log('✅ Transcription settings initialized'); } })();