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:
@@ -20,6 +20,7 @@ struct VocabFlashcardPracticeView: View {
|
|||||||
@State private var revealed: Bool = false
|
@State private var revealed: Bool = false
|
||||||
@State private var exampleByVerbId: [Int: VerbExample] = [:]
|
@State private var exampleByVerbId: [Int: VerbExample] = [:]
|
||||||
@State private var generatingExampleForVerbId: Int? = nil
|
@State private var generatingExampleForVerbId: Int? = nil
|
||||||
|
@State private var speech = SpeechService()
|
||||||
|
|
||||||
private var cloudContext: ModelContext { cloudModelContextProvider() }
|
private var cloudContext: ModelContext { cloudModelContextProvider() }
|
||||||
|
|
||||||
@@ -100,9 +101,21 @@ struct VocabFlashcardPracticeView: View {
|
|||||||
|
|
||||||
private func revealedContent(_ verb: Verb) -> some View {
|
private func revealedContent(_ verb: Verb) -> some View {
|
||||||
VStack(spacing: 18) {
|
VStack(spacing: 18) {
|
||||||
Text(verb.infinitive)
|
HStack(spacing: 12) {
|
||||||
.font(.title.weight(.semibold))
|
Text(verb.infinitive)
|
||||||
.multilineTextAlignment(.center)
|
.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)
|
exampleBlock(for: verb)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ struct VocabMultipleChoicePracticeView: View {
|
|||||||
@State private var selectedOption: Verb? = nil
|
@State private var selectedOption: Verb? = nil
|
||||||
@State private var exampleByVerbId: [Int: VerbExample] = [:]
|
@State private var exampleByVerbId: [Int: VerbExample] = [:]
|
||||||
@State private var generatingExampleForVerbId: Int? = nil
|
@State private var generatingExampleForVerbId: Int? = nil
|
||||||
|
@State private var speech = SpeechService()
|
||||||
|
|
||||||
private var cloudContext: ModelContext { cloudModelContextProvider() }
|
private var cloudContext: ModelContext { cloudModelContextProvider() }
|
||||||
|
|
||||||
@@ -109,9 +110,21 @@ struct VocabMultipleChoicePracticeView: View {
|
|||||||
Text(correct ? "Correct!" : "Not quite")
|
Text(correct ? "Correct!" : "Not quite")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
.foregroundStyle(correct ? .green : .red)
|
.foregroundStyle(correct ? .green : .red)
|
||||||
Text(verb.infinitive)
|
HStack(spacing: 10) {
|
||||||
.font(.title2.weight(.semibold))
|
Text(verb.infinitive)
|
||||||
.padding(.top, 4)
|
.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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user