Auto-deploy: 2026-06-02 19:04:20
This commit is contained in:
77
popup.js
77
popup.js
@@ -264,8 +264,6 @@ document.getElementById('autofill-btn').addEventListener('click', async () => {
|
|||||||
|
|
||||||
// ─── Voice Dictation ───────────────────────────────────────────────────────────
|
// ─── Voice Dictation ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
// ─── Voice Dictation ───────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function initDictation() {
|
function initDictation() {
|
||||||
const statusEl = document.getElementById('dictation-status');
|
const statusEl = document.getElementById('dictation-status');
|
||||||
const micBtn = document.getElementById('dictation-mic-btn');
|
const micBtn = document.getElementById('dictation-mic-btn');
|
||||||
@@ -276,6 +274,16 @@ function initDictation() {
|
|||||||
let finalTranscript = '';
|
let finalTranscript = '';
|
||||||
let interimTranscript = '';
|
let interimTranscript = '';
|
||||||
|
|
||||||
|
function updateCopyBtnVisibility() {
|
||||||
|
if (resultArea.value.trim()) {
|
||||||
|
copyBtn.style.display = 'inline-flex';
|
||||||
|
} else {
|
||||||
|
copyBtn.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resultArea.addEventListener('input', updateCopyBtnVisibility);
|
||||||
|
|
||||||
function stopRecording(process = true) {
|
function stopRecording(process = true) {
|
||||||
if (!isRecording) return;
|
if (!isRecording) return;
|
||||||
isRecording = false;
|
isRecording = false;
|
||||||
@@ -283,6 +291,8 @@ function initDictation() {
|
|||||||
micBtn.style.background = 'linear-gradient(135deg, var(--accent), #9b5de5)';
|
micBtn.style.background = 'linear-gradient(135deg, var(--accent), #9b5de5)';
|
||||||
micBtn.innerHTML = '🎤';
|
micBtn.innerHTML = '🎤';
|
||||||
|
|
||||||
|
updateCopyBtnVisibility();
|
||||||
|
|
||||||
const textToProcess = resultArea.value.trim();
|
const textToProcess = resultArea.value.trim();
|
||||||
if (textToProcess && process) {
|
if (textToProcess && process) {
|
||||||
statusEl.textContent = '✨ جارٍ التحسين بواسطة الذكاء الاصطناعي...';
|
statusEl.textContent = '✨ جارٍ التحسين بواسطة الذكاء الاصطناعي...';
|
||||||
@@ -305,6 +315,7 @@ function initDictation() {
|
|||||||
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();
|
||||||
|
updateCopyBtnVisibility();
|
||||||
} else if (message.type === 'SPEECH_ERROR') {
|
} else if (message.type === 'SPEECH_ERROR') {
|
||||||
console.error('Speech recognition error', message.payload.error);
|
console.error('Speech recognition error', message.payload.error);
|
||||||
if (message.payload.error === 'not-allowed') {
|
if (message.payload.error === 'not-allowed') {
|
||||||
@@ -352,6 +363,9 @@ function initDictation() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
window.__ljaDictationActive = true;
|
window.__ljaDictationActive = true;
|
||||||
|
window.__ljaSpeechUserStopped = false;
|
||||||
|
window.__ljaSpeechAccumulatedText = '';
|
||||||
|
window.__ljaSpeechCurrentSessionFinalText = '';
|
||||||
|
|
||||||
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||||||
if (!SpeechRecognition) {
|
if (!SpeechRecognition) {
|
||||||
@@ -360,7 +374,12 @@ function initDictation() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const recognition = new SpeechRecognition();
|
let recognition;
|
||||||
|
|
||||||
|
function startRecognition() {
|
||||||
|
if (window.__ljaSpeechUserStopped) return;
|
||||||
|
|
||||||
|
recognition = new SpeechRecognition();
|
||||||
recognition.lang = lang;
|
recognition.lang = lang;
|
||||||
recognition.continuous = true;
|
recognition.continuous = true;
|
||||||
recognition.interimResults = true;
|
recognition.interimResults = true;
|
||||||
@@ -372,37 +391,70 @@ function initDictation() {
|
|||||||
|
|
||||||
recognition.onresult = (event) => {
|
recognition.onresult = (event) => {
|
||||||
let interimText = '';
|
let interimText = '';
|
||||||
let finalText = '';
|
let sessionFinalText = '';
|
||||||
|
|
||||||
for (let i = 0; i < event.results.length; i++) {
|
for (let i = 0; i < event.results.length; i++) {
|
||||||
const result = event.results[i];
|
const result = event.results[i];
|
||||||
if (result.isFinal) {
|
if (result.isFinal) {
|
||||||
finalText += result[0].transcript + ' ';
|
sessionFinalText += result[0].transcript + ' ';
|
||||||
} else {
|
} else {
|
||||||
interimText += result[0].transcript;
|
interimText += result[0].transcript;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.__ljaSpeechCurrentSessionFinalText = sessionFinalText;
|
||||||
|
|
||||||
|
const fullFinalText = window.__ljaSpeechAccumulatedText + sessionFinalText;
|
||||||
|
|
||||||
chrome.runtime.sendMessage({
|
chrome.runtime.sendMessage({
|
||||||
type: 'SPEECH_RESULT',
|
type: 'SPEECH_RESULT',
|
||||||
payload: { interimText, finalText }
|
payload: {
|
||||||
|
interimText: interimText,
|
||||||
|
finalText: fullFinalText
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
recognition.onerror = (event) => {
|
recognition.onerror = (event) => {
|
||||||
console.error('[LJA Dictation] Error:', event.error);
|
console.error('[LJA Dictation] Error:', event.error);
|
||||||
|
if (event.error === 'not-allowed') {
|
||||||
chrome.runtime.sendMessage({ type: 'SPEECH_ERROR', payload: { error: event.error } });
|
chrome.runtime.sendMessage({ type: 'SPEECH_ERROR', payload: { error: event.error } });
|
||||||
window.__ljaDictationActive = false;
|
window.__ljaDictationActive = false;
|
||||||
|
} else {
|
||||||
|
console.warn('[LJA Dictation] Recoverable error:', event.error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
recognition.onend = () => {
|
recognition.onend = () => {
|
||||||
|
if (window.__ljaSpeechUserStopped) {
|
||||||
|
// User explicitly stopped
|
||||||
chrome.runtime.sendMessage({ type: 'SPEECH_END' });
|
chrome.runtime.sendMessage({ type: 'SPEECH_END' });
|
||||||
window.__ljaDictationActive = false;
|
window.__ljaDictationActive = false;
|
||||||
|
} else {
|
||||||
|
// Ended due to browser timeout / silence, restart it
|
||||||
|
window.__ljaSpeechAccumulatedText += window.__ljaSpeechCurrentSessionFinalText;
|
||||||
|
window.__ljaSpeechCurrentSessionFinalText = '';
|
||||||
|
console.log('[LJA Dictation] Silence/timeout. Restarting recognition...');
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!window.__ljaSpeechUserStopped) {
|
||||||
|
startRecognition();
|
||||||
|
}
|
||||||
|
}, 150);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
recognition.start();
|
||||||
|
} catch (e) {
|
||||||
|
chrome.runtime.sendMessage({ type: 'SPEECH_ERROR', payload: { error: e.message } });
|
||||||
|
window.__ljaDictationActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Listen for STOP message from popup
|
// Listen for STOP message from popup
|
||||||
const stopListener = (msg, sender, sendResponse) => {
|
const stopListener = (msg, sender, sendResponse) => {
|
||||||
if (msg.type === 'STOP_RECORDING_FROM_POPUP') {
|
if (msg.type === 'STOP_RECORDING_FROM_POPUP') {
|
||||||
|
window.__ljaSpeechUserStopped = true;
|
||||||
try { recognition.stop(); } catch(e) {}
|
try { recognition.stop(); } catch(e) {}
|
||||||
window.__ljaDictationActive = false;
|
window.__ljaDictationActive = false;
|
||||||
chrome.runtime.onMessage.removeListener(stopListener);
|
chrome.runtime.onMessage.removeListener(stopListener);
|
||||||
@@ -411,12 +463,7 @@ function initDictation() {
|
|||||||
};
|
};
|
||||||
chrome.runtime.onMessage.addListener(stopListener);
|
chrome.runtime.onMessage.addListener(stopListener);
|
||||||
|
|
||||||
try {
|
startRecognition();
|
||||||
recognition.start();
|
|
||||||
} catch (e) {
|
|
||||||
chrome.runtime.sendMessage({ type: 'SPEECH_ERROR', payload: { error: e.message } });
|
|
||||||
window.__ljaDictationActive = false;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
args: ['ar-SA']
|
args: ['ar-SA']
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
@@ -440,7 +487,7 @@ function initDictation() {
|
|||||||
const apiKey = document.getElementById('api-key-input').value.trim();
|
const apiKey = document.getElementById('api-key-input').value.trim();
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
statusEl.textContent = '⚠️ الرجاء إدخال مفتاح Gemini لتحسين النص';
|
statusEl.textContent = '⚠️ الرجاء إدخال مفتاح Gemini لتحسين النص';
|
||||||
copyBtn.style.display = 'inline-flex';
|
updateCopyBtnVisibility();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,13 +528,13 @@ CORRECTED TEXT:`;
|
|||||||
|
|
||||||
resultArea.value = processedText.trim();
|
resultArea.value = processedText.trim();
|
||||||
statusEl.textContent = '✅ تم التحسين بنجاح! يمكنك النسخ الآن.';
|
statusEl.textContent = '✅ تم التحسين بنجاح! يمكنك النسخ الآن.';
|
||||||
copyBtn.style.display = 'inline-flex';
|
updateCopyBtnVisibility();
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Server error');
|
throw new Error('Server error');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
statusEl.textContent = '⚠️ فشل التحسين الذكي، نعرض النص الأصلي.';
|
statusEl.textContent = '⚠️ فشل التحسين الذكي، نعرض النص الأصلي.';
|
||||||
copyBtn.style.display = 'inline-flex';
|
updateCopyBtnVisibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user