Files
Spanish/Conjuga/Conjuga/Views/Settings/FeatureReferenceView.swift
Trey t a663bc03cd 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>
2026-04-13 16:12:36 -05:00

253 lines
10 KiB
Swift

import SwiftUI
struct FeatureReferenceView: View {
var body: some View {
List {
Section("Verb Conjugation Practice") {
featureRow(
icon: "rectangle.stack", color: .blue,
title: "Flashcard / Typing / MC / Handwriting / Sentence Builder",
details: [
"Pulls from verb conjugation database (1,750 verbs)",
"Filtered by your Level setting",
"Filtered by your Enabled Tenses",
"Respects Include Vosotros setting",
"Due cards (SRS) shown first, then random",
]
)
featureRow(
icon: "tablecells", color: .blue,
title: "Full Table",
details: [
"Shows all 6 person forms for one verb + tense",
"Random verb from your Level",
"Random tense from your Enabled Tenses",
]
)
}
Section("Quick Actions") {
featureRow(
icon: "star.fill", color: .orange,
title: "Common Tenses",
details: [
"Restricts to 6 essential tenses: Present, Preterite, Imperfect, Future, Present Subjunctive, Imperative",
"Still filtered by your Level",
]
)
featureRow(
icon: "exclamationmark.triangle", color: .red,
title: "Weak Verbs",
details: [
"Shows verbs you've struggled with (ease factor < 2.0)",
"Only includes verbs you've reviewed at least once",
"Weakest verbs shown first",
]
)
featureRow(
icon: "wand.and.stars", color: .purple,
title: "Irregularity Drills",
details: [
"Spelling Changes: c->qu, g->gu, z->c patterns",
"Stem Changes: e->ie, o->ue, e->i patterns",
"Unique Irregulars: ser, ir, haber, etc.",
"Filtered by your Level and Enabled Tenses",
]
)
featureRow(
icon: "rectangle.stack.fill", color: .teal,
title: "Vocab Review",
details: [
"Reviews vocabulary cards that are due (SRS scheduled)",
"Cards become due after you study them in Course quizzes",
"Rate Again/Hard/Good/Easy to schedule next review",
"Uses all course vocabulary, not filtered by level",
]
)
}
Section("Practice Activities") {
featureRow(
icon: "bubble.left.and.bubble.right.fill", color: .green,
title: "Conversation",
details: [
"AI chat partner using Apple Intelligence (on-device)",
"10 scenario types (restaurant, directions, etc.)",
"AI adapts vocabulary to your Level setting",
"Corrections provided inline when you make mistakes",
"Conversations saved to iCloud for revisiting",
"Requires Apple Intelligence-capable device",
]
)
featureRow(
icon: "ear.fill", color: .blue,
title: "Listening",
details: [
"Listen & Type: hear a sentence, type what you heard",
"Pronunciation: read a sentence aloud, get scored on accuracy",
"Sentences pulled from course vocabulary examples",
"Uses all course vocab (not filtered by level)",
"Pronunciation requires microphone permission",
]
)
featureRow(
icon: "text.badge.minus", color: .indigo,
title: "Cloze Practice",
details: [
"Fill in the missing word in a Spanish sentence",
"Sentences from course vocabulary examples",
"4 multiple-choice options (1 correct + 3 distractors)",
"Distractors are other vocabulary words from same pool",
"Uses all course vocab (not filtered by level)",
]
)
featureRow(
icon: "music.note.list", color: .pink,
title: "Lyrics",
details: [
"Search and save Spanish song lyrics",
"Side-by-side Spanish and English translations",
"User-curated library, not filtered by level",
"Saved to iCloud for sync across devices",
]
)
featureRow(
icon: "book.fill", color: .teal,
title: "Stories",
details: [
"AI-generated one-paragraph Spanish stories",
"Matched to your Level and Enabled Tenses",
"Every word is tappable for definition",
"Known words use offline dictionary (175K+ verb forms)",
"Unknown words looked up via on-device AI",
"English translation hidden by default (toggle to reveal)",
"3-question comprehension quiz at the end",
"Saved to iCloud for revisiting",
"Requires Apple Intelligence-capable device",
]
)
}
Section("Guide") {
featureRow(
icon: "book", color: .brown,
title: "Tense Guides",
details: [
"Detailed explanation of each of the 20 verb tenses",
"Conjugation ending tables for -ar, -er, -ir verbs",
"Usage patterns with example sentences",
"Essential tenses marked with orange badge",
]
)
featureRow(
icon: "doc.text", color: .brown,
title: "Grammar Notes",
details: [
"23 grammar topics (ser vs estar, por vs para, etc.)",
"Interactive exercises available for 5 topics",
"Tap 'Practice This' on notes that have exercises",
"Content grouped by category with card-based layout",
]
)
}
Section("Course") {
featureRow(
icon: "list.clipboard", color: .orange,
title: "Course Quizzes",
details: [
"Vocabulary from specific course weeks",
"Multiple quiz types: MC, typing, handwriting, cloze",
"Focus Area mode for missed words",
"Not filtered by Level (uses course structure)",
]
)
featureRow(
icon: "checkmark.seal", color: .orange,
title: "Checkpoint Exams",
details: [
"Cumulative review across multiple weeks",
"Cards sampled evenly across all covered weeks",
"Choose 25, 50, or 100 questions",
]
)
}
Section("Dashboard") {
featureRow(
icon: "clock.fill", color: .mint,
title: "Study Time",
details: [
"Tracks time the app is in the foreground",
"Starts when app becomes active, stops on background",
"Shows today's time and all-time total",
"7-day bar chart of daily study time",
]
)
}
Section("Settings That Affect Practice") {
settingRow(name: "Level", affects: "Verb practice, Full Table, Quick Actions, Stories, Conversation")
settingRow(name: "Enabled Tenses", affects: "Verb practice, Full Table, Irregularity Drills, Stories")
settingRow(name: "Include Vosotros", affects: "Verb practice, Full Table, Quick Actions")
settingRow(name: "Daily Goal", affects: "Dashboard progress tracking only")
}
}
.navigationTitle("How Features Work")
.navigationBarTitleDisplayMode(.inline)
}
// MARK: - Components
@ViewBuilder
private func featureRow(icon: String, color: Color, title: String, details: [String]) -> some View {
VStack(alignment: .leading, spacing: 8) {
HStack(spacing: 10) {
Image(systemName: icon)
.font(.body)
.foregroundStyle(color)
.frame(width: 24)
Text(title)
.font(.subheadline.weight(.semibold))
}
VStack(alignment: .leading, spacing: 4) {
ForEach(details, id: \.self) { detail in
HStack(alignment: .top, spacing: 6) {
Text("")
.font(.caption)
.foregroundStyle(.secondary)
Text(detail)
.font(.caption)
.foregroundStyle(.secondary)
}
}
}
.padding(.leading, 34)
}
.padding(.vertical, 4)
}
@ViewBuilder
private func settingRow(name: String, affects: String) -> some View {
VStack(alignment: .leading, spacing: 2) {
Text(name)
.font(.subheadline.weight(.semibold))
Text(affects)
.font(.caption)
.foregroundStyle(.secondary)
}
.padding(.vertical, 2)
}
}