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) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ struct CourseQuizView: View {
|
|||||||
@State private var currentIndex = 0
|
@State private var currentIndex = 0
|
||||||
@State private var correctCount = 0
|
@State private var correctCount = 0
|
||||||
@State private var missedItems: [MissedCourseItem] = []
|
@State private var missedItems: [MissedCourseItem] = []
|
||||||
|
@State private var isAdvancing = false
|
||||||
|
|
||||||
// Per-question state
|
// Per-question state
|
||||||
@State private var userAnswer = ""
|
@State private var userAnswer = ""
|
||||||
@@ -311,16 +312,13 @@ struct CourseQuizView: View {
|
|||||||
// Nav arrows
|
// Nav arrows
|
||||||
HStack {
|
HStack {
|
||||||
Button {
|
Button {
|
||||||
guard currentIndex > 0 else { return }
|
goBack()
|
||||||
currentIndex -= 1
|
|
||||||
resetQuestion()
|
|
||||||
prepareQuestion()
|
|
||||||
} label: {
|
} label: {
|
||||||
Label("Previous", systemImage: "chevron.left")
|
Label("Previous", systemImage: "chevron.left")
|
||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
}
|
}
|
||||||
.tint(.secondary)
|
.tint(.secondary)
|
||||||
.disabled(currentIndex == 0)
|
.disabled(currentIndex == 0 || isAdvancing)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
@@ -332,6 +330,7 @@ struct CourseQuizView: View {
|
|||||||
.labelStyle(.titleAndIcon)
|
.labelStyle(.titleAndIcon)
|
||||||
}
|
}
|
||||||
.tint(.blue)
|
.tint(.blue)
|
||||||
|
.disabled(isAdvancing)
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
}
|
}
|
||||||
@@ -498,6 +497,8 @@ struct CourseQuizView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func advance() {
|
private func advance() {
|
||||||
|
guard !isAdvancing else { return }
|
||||||
|
isAdvancing = true
|
||||||
currentIndex += 1
|
currentIndex += 1
|
||||||
if isComplete {
|
if isComplete {
|
||||||
saveResult()
|
saveResult()
|
||||||
@@ -505,6 +506,20 @@ struct CourseQuizView: View {
|
|||||||
resetQuestion()
|
resetQuestion()
|
||||||
prepareQuestion()
|
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() {
|
private func saveResult() {
|
||||||
|
|||||||
Reference in New Issue
Block a user