Auto-deploy: 2026-06-02 18:54:31
This commit is contained in:
127
popup.js
127
popup.js
@@ -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 = '🎤';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user