fix & feat: resolve user reports #1 through #8 (TTS voice & speed, modals, scrollbar, CEFR hint, SRS grammar exclusion, global word lookup)

This commit is contained in:
Antigravity committed 2026-10-08 12:37:41 +03:00
1 parent 8cffae46fa
commit 7871191c90
12 files changed
+443 -103

No files matched your search

+22 -13
View File
@@ -3,7 +3,7 @@
// =======================================================================
import { api } from './api.js';
import { escapeHtml, escapeRegex, shuffleArray, showToast, openModal, closeModal, playAudio, cleanPromptTranslation } from './ui.js';
import { escapeHtml, escapeRegex, shuffleArray, showToast, openModal, closeModal, playAudio, playTextSpeech, cleanPromptTranslation } from './ui.js';
import { getAllCards } from './dictionary.js';
let srsQueue = [];
@@ -53,6 +53,7 @@ export function initSrs() {
const fcBackContextBox = document.getElementById('fc-back-context-box');
const fcBackContext = document.getElementById('fc-back-context');
const fcBackContextAudioBtn = document.getElementById('fc-back-context-audio-btn');
const fcBackContextAudioSlowBtn = document.getElementById('fc-back-context-audio-slow-btn');
const fcBackNotesBox = document.getElementById('fc-back-notes-box');
const fcBackNotes = document.getElementById('fc-back-notes');
const fcFlipBtnWrap = document.getElementById('fc-flip-btn-wrap');
@@ -352,6 +353,9 @@ export function initSrs() {
if (fcBackContextAudioBtn) {
fcBackContextAudioBtn.style.display = card.context_sentence ? 'inline-flex' : 'none';
}
if (fcBackContextAudioSlowBtn) {
fcBackContextAudioSlowBtn.style.display = card.context_sentence ? 'inline-flex' : 'none';
}
}
if (fcFrontAudioBtn) {
@@ -359,8 +363,7 @@ export function initSrs() {
e.stopPropagation();
const card = srsQueue[srsCurrentIndex];
if (!card) return;
const url = card.audio_url || `/api/tts?text=${encodeURIComponent(card.term)}&lang=en`;
playAudio(url);
playTextSpeech(card.term, 'en', 1.0);
});
}
@@ -369,8 +372,7 @@ export function initSrs() {
e.stopPropagation();
const card = srsQueue[srsCurrentIndex];
if (!card) return;
const url = card.audio_url || `/api/tts?text=${encodeURIComponent(card.term)}&lang=en`;
playAudio(url);
playTextSpeech(card.term, 'en', 1.0);
});
}
@@ -379,8 +381,16 @@ export function initSrs() {
e.stopPropagation();
const card = srsQueue[srsCurrentIndex];
if (!card || !card.context_sentence) return;
const url = card.context_audio_url || `/api/tts?text=${encodeURIComponent(card.context_sentence)}&lang=en`;
playAudio(url);
playTextSpeech(card.context_sentence, 'en', 1.0);
});
}
if (fcBackContextAudioSlowBtn) {
fcBackContextAudioSlowBtn.addEventListener('click', (e) => {
e.stopPropagation();
const card = srsQueue[srsCurrentIndex];
if (!card || !card.context_sentence) return;
playTextSpeech(card.context_sentence, 'en', 0.75);
});
}
@@ -491,7 +501,7 @@ export function initSrs() {
}
});
if (card.audio_url) playAudio(card.audio_url);
playTextSpeech(card.term, 'en');
if (isCorrect) {
quizFeedbackBox.className = 'trainer-feedback-box feedback-correct';
@@ -523,8 +533,7 @@ export function initSrs() {
e.stopPropagation();
const card = srsQueue[srsCurrentIndex];
if (!card) return;
const url = card.audio_url || `/api/tts?text=${encodeURIComponent(card.term)}&lang=en`;
playAudio(url);
playTextSpeech(card.term, 'en', 1.0);
});
}
@@ -565,7 +574,7 @@ export function initSrs() {
const target = card.term.trim().toLowerCase();
const isMatch = userInput === target;
if (card.audio_url) playAudio(card.audio_url);
playTextSpeech(card.term, 'en');
typingInput.disabled = true;
if (isMatch) {
@@ -611,7 +620,7 @@ export function initSrs() {
const target = card.term.trim().toLowerCase();
const isMatch = userInput === target;
if (card.audio_url) playAudio(card.audio_url);
playTextSpeech(card.term, 'en');
clozeInput.disabled = true;
if (isMatch) {
@@ -640,7 +649,7 @@ export function initSrs() {
dictationInput.value = '';
dictationInput.disabled = false;
const play = () => { if (card.audio_url) playAudio(card.audio_url); };
const play = () => { playTextSpeech(card.term, 'en'); };
dictationBigPlayBtn.onclick = play;
dictationReplayBtn.onclick = play;
play();