Auto-deploy: 2026-06-02 18:15:27
This commit is contained in:
@@ -49,41 +49,80 @@
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Offscreen Document Integration ──────────────────────────────────────
|
||||
chrome.runtime.onMessage.addListener((message) => {
|
||||
if (message.type === 'OFFSCREEN_RECORDING_RESULT') {
|
||||
lastSpeechTime = Date.now();
|
||||
interimText = message.payload.interimText || '';
|
||||
finalText = message.payload.finalText || '';
|
||||
|
||||
updateInputField();
|
||||
// ─── Iframe Integration ──────────────────────────────────────────────────
|
||||
let speechIframe = null;
|
||||
|
||||
clearTimeout(silenceTimer);
|
||||
silenceTimer = setTimeout(() => {
|
||||
if (isListening && Date.now() - lastSpeechTime >= SILENCE_TIMEOUT) {
|
||||
stopListening();
|
||||
function initSpeechIframe() {
|
||||
if (speechIframe) return;
|
||||
|
||||
speechIframe = document.createElement('iframe');
|
||||
speechIframe.id = 'claude-voice-speech-iframe';
|
||||
speechIframe.style.cssText = `
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
left: -9999px;
|
||||
top: -9999px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
border: none;
|
||||
`;
|
||||
speechIframe.src = chrome.runtime.getURL('claude-arabic-voice/speech.html');
|
||||
speechIframe.allow = 'microphone';
|
||||
document.body.appendChild(speechIframe);
|
||||
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.source !== speechIframe.contentWindow) return;
|
||||
|
||||
const message = event.data;
|
||||
if (message.type === 'SPEECH_START_SUCCESS') {
|
||||
isListening = true;
|
||||
lastSpeechTime = Date.now();
|
||||
interimText = '';
|
||||
finalText = '';
|
||||
updateMicButton(true);
|
||||
showStatus('listening', '🎤 جارٍ الاستماع...');
|
||||
|
||||
clearTimeout(autoSendTimer);
|
||||
autoSendTimer = setTimeout(() => {
|
||||
if (isListening) stopListening();
|
||||
}, MAX_RECORDING_TIME);
|
||||
|
||||
clearTimeout(silenceTimer);
|
||||
silenceTimer = setTimeout(checkSilence, SILENCE_TIMEOUT);
|
||||
} else if (message.type === 'SPEECH_RESULT') {
|
||||
lastSpeechTime = Date.now();
|
||||
interimText = message.payload.interimText || '';
|
||||
finalText = message.payload.finalText || '';
|
||||
|
||||
updateInputField();
|
||||
|
||||
clearTimeout(silenceTimer);
|
||||
silenceTimer = setTimeout(checkSilence, SILENCE_TIMEOUT);
|
||||
} else if (message.type === 'SPEECH_ERROR') {
|
||||
console.error('[ClaudeVoice] Recognition error:', message.payload.error);
|
||||
if (message.payload.error === 'no-speech') {
|
||||
return;
|
||||
}
|
||||
}, SILENCE_TIMEOUT);
|
||||
} else if (message.type === 'OFFSCREEN_RECORDING_ERROR') {
|
||||
console.error('[ClaudeVoice] Recognition error:', message.payload.error);
|
||||
if (message.payload.error === 'no-speech') {
|
||||
return; // offscreen script restarts it automatically
|
||||
}
|
||||
stopListening();
|
||||
|
||||
if (message.payload.error === 'not-allowed') {
|
||||
showStatus('error', '❌ الرجاء منح الصلاحية (تم فتح صفحة جديدة)');
|
||||
chrome.runtime.sendMessage({ type: 'OPEN_PERMISSION_PAGE' });
|
||||
} else {
|
||||
showStatus('error', '❌ خطأ: ' + getArabicError(message.payload.error));
|
||||
}
|
||||
} else if (message.type === 'OFFSCREEN_RECORDING_END') {
|
||||
if (isListening) {
|
||||
// Unexpected end from offscreen while we still consider ourselves listening
|
||||
stopListening();
|
||||
|
||||
if (message.payload.error === 'not-allowed') {
|
||||
showStatus('error', '❌ الرجاء منح الصلاحية (تم فتح صفحة جديدة)');
|
||||
chrome.runtime.sendMessage({ type: 'OPEN_PERMISSION_PAGE' });
|
||||
} else {
|
||||
showStatus('error', '❌ خطأ: ' + getArabicError(message.payload.error));
|
||||
}
|
||||
} else if (message.type === 'SPEECH_END') {
|
||||
if (isListening) stopListening();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function checkSilence() {
|
||||
if (isListening && Date.now() - lastSpeechTime >= SILENCE_TIMEOUT) {
|
||||
stopListening();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getArabicError(error) {
|
||||
const errors = {
|
||||
@@ -101,36 +140,13 @@
|
||||
// ─── Start / Stop Listening ─────────────────────────────────────────────
|
||||
async function startListening() {
|
||||
await loadSettings();
|
||||
if (!speechIframe) initSpeechIframe();
|
||||
|
||||
try {
|
||||
chrome.runtime.sendMessage({
|
||||
type: 'START_RECORDING_FROM_CONTENT',
|
||||
speechIframe.contentWindow.postMessage({
|
||||
type: 'START_RECORDING',
|
||||
payload: { language: settings.language }
|
||||
}, (response) => {
|
||||
if (response && response.success) {
|
||||
isListening = true;
|
||||
lastSpeechTime = Date.now();
|
||||
interimText = '';
|
||||
finalText = '';
|
||||
updateMicButton(true);
|
||||
showStatus('listening', '🎤 جارٍ الاستماع...');
|
||||
|
||||
clearTimeout(autoSendTimer);
|
||||
autoSendTimer = setTimeout(() => {
|
||||
if (isListening) stopListening();
|
||||
}, MAX_RECORDING_TIME);
|
||||
|
||||
clearTimeout(silenceTimer);
|
||||
silenceTimer = setTimeout(() => {
|
||||
if (isListening && Date.now() - lastSpeechTime >= SILENCE_TIMEOUT) {
|
||||
stopListening();
|
||||
}
|
||||
}, SILENCE_TIMEOUT);
|
||||
} else {
|
||||
console.error('[ClaudeVoice] Start failed:', response?.error);
|
||||
showStatus('error', '❌ فشل بدء التسجيل');
|
||||
}
|
||||
});
|
||||
}, '*');
|
||||
} catch (e) {
|
||||
console.error('[ClaudeVoice] Start message failed:', e);
|
||||
showStatus('error', '❌ فشل الاتصال بالإضافة');
|
||||
@@ -144,7 +160,9 @@
|
||||
clearTimeout(silenceTimer);
|
||||
clearTimeout(autoSendTimer);
|
||||
|
||||
chrome.runtime.sendMessage({ type: 'STOP_RECORDING_FROM_CONTENT' });
|
||||
if (speechIframe) {
|
||||
speechIframe.contentWindow.postMessage({ type: 'STOP_RECORDING' }, '*');
|
||||
}
|
||||
updateMicButton(false);
|
||||
|
||||
const text = finalText.trim() || interimText.trim();
|
||||
@@ -594,6 +612,7 @@ CORRECTED TEXT:`;
|
||||
async function init() {
|
||||
await loadSettings();
|
||||
injectStyles();
|
||||
initSpeechIframe(); // Inject iframe immediately
|
||||
createMicButton();
|
||||
|
||||
// Re-position on scroll and resize
|
||||
|
||||
Reference in New Issue
Block a user