diff --git a/popup.js b/popup.js index c2e7bec..d663dad 100644 --- a/popup.js +++ b/popup.js @@ -294,13 +294,13 @@ function initDictation() { } } - // Listen to messages from the offscreen document via the background + // Listen to messages from the injected script chrome.runtime.onMessage.addListener((message) => { - if (message.type === 'OFFSCREEN_RECORDING_RESULT') { + if (message.type === 'SPEECH_RESULT') { interimTranscript = message.payload.interimText || ''; finalTranscript = message.payload.finalText || ''; resultArea.value = (finalTranscript + interimTranscript).trim(); - } else if (message.type === 'OFFSCREEN_RECORDING_ERROR') { + } else if (message.type === 'SPEECH_ERROR') { console.error('Speech recognition error', message.payload.error); if (message.payload.error === 'not-allowed') { statusEl.textContent = '❌ يرجى السماح للميكروفون من إعدادات المتصفح'; @@ -309,7 +309,7 @@ function initDictation() { statusEl.textContent = '❌ خطأ: ' + message.payload.error; } stopRecording(false); - } else if (message.type === 'OFFSCREEN_RECORDING_END') { + } else if (message.type === 'SPEECH_END') { if (isRecording) { stopRecording(true); } @@ -355,19 +355,34 @@ function initDictation() { iframe.style.left = '0'; iframe.style.width = '1px'; iframe.style.height = '1px'; - iframe.style.opacity = '0'; + iframe.style.opacity = '0.01'; iframe.style.pointerEvents = 'none'; iframe.style.zIndex = '-9999'; iframe.style.border = 'none'; iframe.setAttribute('allow', 'microphone'); document.body.appendChild(iframe); + + // Relay messages from iframe to popup + window.addEventListener('message', (event) => { + if (event.data && event.data.type && event.data.type.startsWith('SPEECH_')) { + chrome.runtime.sendMessage(event.data); + } + }); + + // Listen for messages from popup to iframe + chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { + if (msg.type === 'START_RECORDING_FROM_POPUP' || msg.type === 'STOP_RECORDING_FROM_POPUP') { + iframe.contentWindow.postMessage(msg, '*'); + sendResponse({ success: true }); + } + }); } }, args: [extensionUrl] }).then(() => { // Small delay to ensure iframe has loaded and registered listener setTimeout(() => { - chrome.runtime.sendMessage({ + chrome.tabs.sendMessage(activeTab.id, { type: 'START_RECORDING_FROM_POPUP', payload: { language: 'ar-SA' } }); diff --git a/speech.js b/speech.js index ad098ac..aa66ae0 100644 --- a/speech.js +++ b/speech.js @@ -29,7 +29,7 @@ function initRecognition(language) { let interimText = ''; let finalText = ''; - for (let i = event.resultIndex; i < event.results.length; i++) { + for (let i = 0; i < event.results.length; i++) { const result = event.results[i]; if (result.isFinal) { finalText += result[0].transcript + ' '; @@ -38,10 +38,10 @@ function initRecognition(language) { } } - chrome.runtime.sendMessage({ - type: 'OFFSCREEN_RECORDING_RESULT', + window.parent.postMessage({ + type: 'SPEECH_RESULT', payload: { interimText, finalText } - }); + }, '*'); }; recognition.onerror = (event) => { @@ -52,10 +52,10 @@ function initRecognition(language) { stopMediaTracks(); } - chrome.runtime.sendMessage({ - type: 'OFFSCREEN_RECORDING_ERROR', + window.parent.postMessage({ + type: 'SPEECH_ERROR', payload: { error: event.error } - }); + }, '*'); }; recognition.onend = () => { @@ -67,7 +67,7 @@ function initRecognition(language) { } } else { stopMediaTracks(); - chrome.runtime.sendMessage({ type: 'OFFSCREEN_RECORDING_END' }); + window.parent.postMessage({ type: 'SPEECH_END' }, '*'); } }; @@ -75,7 +75,10 @@ function initRecognition(language) { } // Listen for messages broadcasted across the extension -chrome.runtime.onMessage.addListener((message) => { +window.addEventListener('message', (event) => { + const message = event.data; + if (!message || !message.type) return; + if (message.type === 'START_RECORDING_FROM_POPUP') { const lang = message.payload?.language || 'ar-SA'; @@ -90,16 +93,16 @@ chrome.runtime.onMessage.addListener((message) => { recognition.start(); isRecording = true; // Tell popup it started successfully - chrome.runtime.sendMessage({ type: 'OFFSCREEN_RECORDING_START_SUCCESS' }); + window.parent.postMessage({ type: 'SPEECH_START_SUCCESS' }, '*'); } } catch (e) { console.error('[Speech Iframe] Failed to start:', e); - chrome.runtime.sendMessage({ type: 'OFFSCREEN_RECORDING_ERROR', payload: { error: e.message } }); + window.parent.postMessage({ type: 'SPEECH_ERROR', payload: { error: e.message } }, '*'); } }) .catch((err) => { console.error('[Speech Iframe] getUserMedia failed:', err); - chrome.runtime.sendMessage({ type: 'OFFSCREEN_RECORDING_ERROR', payload: { error: 'not-allowed' } }); + window.parent.postMessage({ type: 'SPEECH_ERROR', payload: { error: 'not-allowed' } }, '*'); }); }