From dee4991be7ad744ee6302703f22dfd264ef4756e Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 20 Apr 2026 09:26:02 +0200 Subject: [PATCH] feat(VocabLessonView): implement vocab trainer continue timer management - Added a new timer management feature to the vocab trainer, allowing for better control over the continuation of questions after user answers. - Introduced `clearVocabTrainerContinueTimer` method to prevent multiple timers from running simultaneously, enhancing the stability of the training session. - Updated various methods to utilize the new timer management, ensuring a smoother user experience during vocabulary training. --- frontend/src/views/social/VocabLessonView.vue | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/frontend/src/views/social/VocabLessonView.vue b/frontend/src/views/social/VocabLessonView.vue index 50af475..3272252 100644 --- a/frontend/src/views/social/VocabLessonView.vue +++ b/frontend/src/views/social/VocabLessonView.vue @@ -1084,6 +1084,7 @@ export default { vocabTrainerSelectedChoice: null, vocabTrainerAnswered: false, vocabTrainerLastCorrect: false, + vocabTrainerContinueTimer: null, vocabTrainerDirection: 'L2R', // L2R: learning->reference, R2L: reference->learning isCheckingLessonCompletion: false, // Flag um Endlosschleife zu verhindern isNavigatingToNext: false, // Flag um mehrfache Navigation zu verhindern @@ -3329,6 +3330,7 @@ export default { // Vokabeltrainer-Methoden startVocabTrainer() { debugLog('[VocabLessonView] startVocabTrainer aufgerufen'); + this.clearVocabTrainerContinueTimer(); if (!this.trainableLessonVocab || this.trainableLessonVocab.length === 0) { debugLog('[VocabLessonView] Keine Vokabeln vorhanden'); return; @@ -3361,6 +3363,7 @@ export default { }); }, stopVocabTrainer() { + this.clearVocabTrainerContinueTimer(); this.vocabTrainerActive = false; this.vocabTrainerMode = 'multiple_choice'; this.vocabTrainerAutoSwitchedToTyping = false; @@ -3564,10 +3567,17 @@ export default { return ranked[0]?.vocab || pool[Math.floor(Math.random() * pool.length)]; }, continueAfterVocabAnswer() { + this.clearVocabTrainerContinueTimer(); const completedKey = this.currentVocabQuestion?.key || ''; this.advanceRepeatQueue(completedKey); this.nextVocabQuestion(); }, + clearVocabTrainerContinueTimer() { + if (this.vocabTrainerContinueTimer) { + window.clearTimeout(this.vocabTrainerContinueTimer); + this.vocabTrainerContinueTimer = null; + } + }, checkVocabModeSwitch() { this.updateExerciseUnlockState(); @@ -3731,6 +3741,7 @@ export default { }, nextVocabQuestion() { debugLog('[VocabLessonView] nextVocabQuestion aufgerufen'); + this.clearVocabTrainerContinueTimer(); if (!this.vocabTrainerPool || this.vocabTrainerPool.length === 0) { debugLog('[VocabLessonView] Keine Vokabeln im Pool'); this.currentVocabQuestion = null; @@ -3951,9 +3962,19 @@ export default { // Prüfe ob noch Fragen vorhanden sind if (this.vocabTrainerPool && this.vocabTrainerPool.length > 0) { const delay = this.vocabTrainerMode === 'multiple_choice' ? 1000 : 500; // 1 Sekunde für Multiple Choice, 500ms für Typing - setTimeout(() => { + const answeredQuestionKey = this.currentVocabQuestion?.key || ''; + this.clearVocabTrainerContinueTimer(); + this.vocabTrainerContinueTimer = window.setTimeout(() => { + this.vocabTrainerContinueTimer = null; // Prüfe erneut, ob noch Fragen vorhanden sind (könnte sich geändert haben) - if (this.vocabTrainerPool && this.vocabTrainerPool.length > 0 && this.vocabTrainerActive) { + if ( + this.vocabTrainerPool + && this.vocabTrainerPool.length > 0 + && this.vocabTrainerActive + && this.vocabTrainerAnswered + && this.vocabTrainerLastCorrect + && this.currentVocabQuestion?.key === answeredQuestionKey + ) { this.continueAfterVocabAnswer(); } }, delay); @@ -4089,6 +4110,7 @@ export default { window.clearTimeout(this.lessonStateSaveTimer); this.lessonStateSaveTimer = null; } + this.clearVocabTrainerContinueTimer(); this.stopAssistantWaitTimer(); // Stoppe alle aktiven Recognition-Instanzen Object.keys(this.activeRecognition).forEach(exerciseId => {