Vocab Practice — speaker button to hear the Spanish word

Both vocab session reveal panes now show a speaker button next to the
Spanish infinitive. Tapping it speaks the word via the existing
SpeechService (Spanish voice), same TTS the Course flashcards use.

Flashcard mode: button beside the infinitive in the reveal pane.
Multiple choice: button beside the infinitive in the answer feedback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey T
2026-05-15 15:15:12 -05:00
parent 900a927f95
commit d61f9e50b1
2 changed files with 32 additions and 6 deletions
@@ -20,6 +20,7 @@ struct VocabFlashcardPracticeView: View {
@State private var revealed: Bool = false
@State private var exampleByVerbId: [Int: VerbExample] = [:]
@State private var generatingExampleForVerbId: Int? = nil
@State private var speech = SpeechService()
private var cloudContext: ModelContext { cloudModelContextProvider() }
@@ -100,9 +101,21 @@ struct VocabFlashcardPracticeView: View {
private func revealedContent(_ verb: Verb) -> some View {
VStack(spacing: 18) {
Text(verb.infinitive)
.font(.title.weight(.semibold))
.multilineTextAlignment(.center)
HStack(spacing: 12) {
Text(verb.infinitive)
.font(.title.weight(.semibold))
.multilineTextAlignment(.center)
Button {
speech.speak(verb.infinitive)
} label: {
Image(systemName: "speaker.wave.2.fill")
.font(.title3)
.padding(10)
}
.glassEffect(in: .circle)
.accessibilityLabel("Say it out loud")
}
exampleBlock(for: verb)
@@ -19,6 +19,7 @@ struct VocabMultipleChoicePracticeView: View {
@State private var selectedOption: Verb? = nil
@State private var exampleByVerbId: [Int: VerbExample] = [:]
@State private var generatingExampleForVerbId: Int? = nil
@State private var speech = SpeechService()
private var cloudContext: ModelContext { cloudModelContextProvider() }
@@ -109,9 +110,21 @@ struct VocabMultipleChoicePracticeView: View {
Text(correct ? "Correct!" : "Not quite")
.font(.headline)
.foregroundStyle(correct ? .green : .red)
Text(verb.infinitive)
.font(.title2.weight(.semibold))
.padding(.top, 4)
HStack(spacing: 10) {
Text(verb.infinitive)
.font(.title2.weight(.semibold))
Button {
speech.speak(verb.infinitive)
} label: {
Image(systemName: "speaker.wave.2.fill")
.font(.body)
.padding(8)
}
.glassEffect(in: .circle)
.accessibilityLabel("Say it out loud")
}
.padding(.top, 4)
}
}