From 3b8a8a7f1a41f8989e97f4612827a2311b2e4bef Mon Sep 17 00:00:00 2001 From: Trey t Date: Sat, 11 Apr 2026 18:52:08 -0500 Subject: [PATCH] Guard quiz Next/Previous against double taps A rapid second tap on Next (easy to trigger with Apple Pencil) called advance() twice before the view tree re-rendered, skipping a card. Share a single isAdvancing flag between advance() and a new goBack() helper, disable both buttons while the flag is set, and clear it after 350 ms so queued Pencil events are absorbed. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Conjuga/Views/Course/CourseQuizView.swift | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Conjuga/Conjuga/Views/Course/CourseQuizView.swift b/Conjuga/Conjuga/Views/Course/CourseQuizView.swift index 0f4bcb3..830122a 100644 --- a/Conjuga/Conjuga/Views/Course/CourseQuizView.swift +++ b/Conjuga/Conjuga/Views/Course/CourseQuizView.swift @@ -18,6 +18,7 @@ struct CourseQuizView: View { @State private var currentIndex = 0 @State private var correctCount = 0 @State private var missedItems: [MissedCourseItem] = [] + @State private var isAdvancing = false // Per-question state @State private var userAnswer = "" @@ -311,16 +312,13 @@ struct CourseQuizView: View { // Nav arrows HStack { Button { - guard currentIndex > 0 else { return } - currentIndex -= 1 - resetQuestion() - prepareQuestion() + goBack() } label: { Label("Previous", systemImage: "chevron.left") .font(.subheadline) } .tint(.secondary) - .disabled(currentIndex == 0) + .disabled(currentIndex == 0 || isAdvancing) Spacer() @@ -332,6 +330,7 @@ struct CourseQuizView: View { .labelStyle(.titleAndIcon) } .tint(.blue) + .disabled(isAdvancing) } .padding(.horizontal) } @@ -498,6 +497,8 @@ struct CourseQuizView: View { } private func advance() { + guard !isAdvancing else { return } + isAdvancing = true currentIndex += 1 if isComplete { saveResult() @@ -505,6 +506,20 @@ struct CourseQuizView: View { resetQuestion() prepareQuestion() } + DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { + isAdvancing = false + } + } + + private func goBack() { + guard !isAdvancing, currentIndex > 0 else { return } + isAdvancing = true + currentIndex -= 1 + resetQuestion() + prepareQuestion() + DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { + isAdvancing = false + } } private func saveResult() {