Auto-deploy: 2026-06-02 18:54:31

This commit is contained in:
Hamza-Ayed
2026-06-02 18:54:31 +03:00
parent 4bab69d2b1
commit 2f71793499

127
popup.js
View File

@@ -296,7 +296,12 @@ function initDictation() {
// Listen to messages from the injected script // Listen to messages from the injected script
chrome.runtime.onMessage.addListener((message) => { chrome.runtime.onMessage.addListener((message) => {
if (message.type === 'SPEECH_RESULT') { if (message.type === 'SPEECH_START_SUCCESS') {
isRecording = true;
micBtn.style.background = 'linear-gradient(135deg, #ff4d6d, #c9184a)';
micBtn.innerHTML = '🔴';
statusEl.textContent = 'جارٍ الاستماع... اضغط للإيقاف';
} else if (message.type === 'SPEECH_RESULT') {
interimTranscript = message.payload.interimText || ''; interimTranscript = message.payload.interimText || '';
finalTranscript = message.payload.finalText || ''; finalTranscript = message.payload.finalText || '';
resultArea.value = (finalTranscript + interimTranscript).trim(); resultArea.value = (finalTranscript + interimTranscript).trim();
@@ -330,67 +335,95 @@ function initDictation() {
return; return;
} }
isRecording = true; // Show a loading state until SPEECH_START_SUCCESS is received
micBtn.style.background = 'linear-gradient(135deg, #ff4d6d, #c9184a)'; micBtn.style.background = 'linear-gradient(135deg, #ffb3c1, #ff758f)';
micBtn.innerHTML = '🔴'; micBtn.innerHTML = '';
statusEl.textContent = 'جارٍ الاستماع... اضغط للإيقاف'; statusEl.textContent = 'جاري تهيئة الميكروفون...';
finalTranscript = ''; finalTranscript = '';
interimTranscript = ''; interimTranscript = '';
resultArea.value = ''; resultArea.value = '';
copyBtn.style.display = 'none'; copyBtn.style.display = 'none';
const extensionUrl = chrome.runtime.getURL('speech.html');
chrome.scripting.executeScript({ chrome.scripting.executeScript({
target: { tabId: activeTab.id }, target: { tabId: activeTab.id },
func: (url) => { func: (lang) => {
let iframe = document.getElementById('lja-dictation-frame'); // Prevent multiple instances
if (!iframe) { if (window.__ljaDictationActive) {
iframe = document.createElement('iframe'); return;
iframe.id = 'lja-dictation-frame'; }
iframe.src = url; window.__ljaDictationActive = true;
// Avoid display:none because Chrome blocks SpeechRecognition in hidden cross-origin iframes
iframe.style.position = 'fixed';
iframe.style.top = '0';
iframe.style.left = '0';
iframe.style.width = '1px';
iframe.style.height = '1px';
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 const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
window.addEventListener('message', (event) => { if (!SpeechRecognition) {
if (event.data && event.data.type && event.data.type.startsWith('SPEECH_')) { chrome.runtime.sendMessage({ type: 'SPEECH_ERROR', payload: { error: 'not-supported' } });
chrome.runtime.sendMessage(event.data); window.__ljaDictationActive = false;
} return;
}); }
// Listen for messages from popup to iframe const recognition = new SpeechRecognition();
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { recognition.lang = lang;
if (msg.type === 'START_RECORDING_FROM_POPUP' || msg.type === 'STOP_RECORDING_FROM_POPUP') { recognition.continuous = true;
iframe.contentWindow.postMessage(msg, '*'); recognition.interimResults = true;
sendResponse({ success: true }); recognition.maxAlternatives = 1;
recognition.onstart = () => {
chrome.runtime.sendMessage({ type: 'SPEECH_START_SUCCESS' });
};
recognition.onresult = (event) => {
let interimText = '';
let finalText = '';
for (let i = 0; i < event.results.length; i++) {
const result = event.results[i];
if (result.isFinal) {
finalText += result[0].transcript + ' ';
} else {
interimText += result[0].transcript;
} }
}
chrome.runtime.sendMessage({
type: 'SPEECH_RESULT',
payload: { interimText, finalText }
}); });
};
recognition.onerror = (event) => {
console.error('[LJA Dictation] Error:', event.error);
chrome.runtime.sendMessage({ type: 'SPEECH_ERROR', payload: { error: event.error } });
window.__ljaDictationActive = false;
};
recognition.onend = () => {
chrome.runtime.sendMessage({ type: 'SPEECH_END' });
window.__ljaDictationActive = false;
};
// Listen for STOP message from popup
const stopListener = (msg, sender, sendResponse) => {
if (msg.type === 'STOP_RECORDING_FROM_POPUP') {
try { recognition.stop(); } catch(e) {}
window.__ljaDictationActive = false;
chrome.runtime.onMessage.removeListener(stopListener);
sendResponse({ success: true });
}
};
chrome.runtime.onMessage.addListener(stopListener);
try {
recognition.start();
} catch (e) {
chrome.runtime.sendMessage({ type: 'SPEECH_ERROR', payload: { error: e.message } });
window.__ljaDictationActive = false;
} }
}, },
args: [extensionUrl] args: ['ar-SA']
}).then(() => {
// Small delay to ensure iframe has loaded and registered listener
setTimeout(() => {
chrome.tabs.sendMessage(activeTab.id, {
type: 'START_RECORDING_FROM_POPUP',
payload: { language: 'ar-SA' }
});
}, 500);
}).catch(err => { }).catch(err => {
console.error('Failed to inject iframe:', err); console.error('Failed to inject speech recognition:', err);
statusEl.textContent = '❌ فشل الاتصال بالصفحة الحالية'; statusEl.textContent = '❌ فشل الاتصال بالصفحة الحالية';
stopRecording(false); micBtn.style.background = 'linear-gradient(135deg, var(--accent), #9b5de5)';
micBtn.innerHTML = '🎤';
}); });
}); });
} }