Add 6 new practice features, offline dictionary, and feature reference
New features: - Offline Dictionary: reverse index of 175K verb forms + 200 common words, cached to disk, powers instant word lookups in Stories - Vocab SRS Review: spaced repetition for course vocabulary cards with due count badge and Again/Hard/Good/Easy rating - Cloze Practice: fill-in-the-blank using SentenceQuizEngine with distractor generation from vocabulary pool - Grammar Exercises: interactive quizzes for 5 grammar topics (ser/estar, por/para, preterite/imperfect, subjunctive, personal a) with "Practice This" button on grammar note detail - Listening Practice: listen-and-type + pronunciation check modes using Speech framework with word-by-word match scoring - Conversational Practice: AI chat partner via Foundation Models with 10 scenario types, saved to cloud container Other changes: - Add Conversation model to SharedModels and cloud container - Add Info.plist keys for speech recognition and microphone - Skip speech auth on simulator to prevent crash - Fix preparing data screen to only show during seed/migration - Extract courseDataVersion to static property on DataLoader - Add "How Features Work" reference page in Settings Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import FoundationModels
|
||||
struct StoryReaderView: View {
|
||||
let story: Story
|
||||
|
||||
@Environment(DictionaryService.self) private var dictionary
|
||||
@State private var selectedWord: WordAnnotation?
|
||||
@State private var showTranslation = false
|
||||
@State private var lookupCache: [String: WordAnnotation] = [:]
|
||||
@@ -105,7 +106,20 @@ struct StoryReaderView: View {
|
||||
}
|
||||
|
||||
private func lookupWord(_ word: String, inContext sentence: String) {
|
||||
// Show immediately with loading state
|
||||
// Try offline dictionary first
|
||||
if let entry = dictionary.lookup(word) {
|
||||
let annotation = WordAnnotation(
|
||||
word: word,
|
||||
baseForm: entry.baseForm,
|
||||
english: entry.english,
|
||||
partOfSpeech: entry.partOfSpeech
|
||||
)
|
||||
lookupCache[word] = annotation
|
||||
selectedWord = annotation
|
||||
return
|
||||
}
|
||||
|
||||
// Fall back to on-device AI lookup
|
||||
selectedWord = WordAnnotation(word: word, baseForm: word, english: "Looking up...", partOfSpeech: "")
|
||||
|
||||
Task {
|
||||
|
||||
Reference in New Issue
Block a user