09e49bda2c
New "Books" row in the Practice tab opens a library of bundled bilingual books. Each chapter renders Spanish paragraph-by-paragraph; tap any word for a definition sheet (DictionaryService with on-device AI fallback), or toggle the toolbar button to swap to the pre-computed English translation inline. Local-only Book + BookChapter SwiftData models added to the local container schema (reset version bumped to 5). DataLoader.seedBooks walks the bundle for `book_*.json` resources, so future books drop in without touching app code — just bundle a new JSON and bump bookDataVersion. First book: Olly Richards' "Spanish Short Stories For Beginners Vol 2" — 13 chapters, 2,646 paragraphs, bilingual. Scripts/books/ is the repeatable pipeline for future EPUBs: extract_epub.py → translate_chapters.py (per-chapter resumable jobs) → bundle_book.py. Translation is done by parallel Claude Code subagents reading per-job input files and writing output files — no API key required, matching the pattern used for the textbook vocab vision pass. See Scripts/books/README.md for the full how-to. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
33 lines
914 B
Swift
33 lines
914 B
Swift
import Foundation
|
|
import SwiftData
|
|
|
|
/// A long-form bilingual book bundled with the app. Chapter content lives in
|
|
/// `BookChapter` rows; this model carries the per-book metadata.
|
|
@Model
|
|
public final class Book {
|
|
@Attribute(.unique) public var id: String = "" // matches `slug`
|
|
public var slug: String = ""
|
|
public var title: String = ""
|
|
public var author: String = ""
|
|
public var language: String = ""
|
|
public var chapterCount: Int = 0
|
|
public var accentColorHex: String = ""
|
|
|
|
public init(
|
|
slug: String,
|
|
title: String,
|
|
author: String,
|
|
language: String,
|
|
chapterCount: Int,
|
|
accentColorHex: String
|
|
) {
|
|
self.id = slug
|
|
self.slug = slug
|
|
self.title = title
|
|
self.author = author
|
|
self.language = language
|
|
self.chapterCount = chapterCount
|
|
self.accentColorHex = accentColorHex
|
|
}
|
|
}
|