From 3c5600f562a71097603cea09dd4c582b768c49ef Mon Sep 17 00:00:00 2001 From: Trey t Date: Tue, 21 Apr 2026 09:39:47 -0500 Subject: [PATCH] Fix textbook section missing on installs that predate bundled JSON MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Earlier launches (before cd491bd bundled textbook_data.json) ran seedTextbookData, got "not bundled — skipping", and still bumped UserDefaults textbookDataVersion to 9. Subsequent launches then short-circuited in refreshTextbookDataIfNeeded and never re-seeded, so ZTEXTBOOKCHAPTER stayed empty and the Course tab hid the section. - seedTextbookData now returns Bool (true only when chapters inserted). - Both call sites only write the version key on success, so a missing or unparseable bundle no longer locks us out of future retries. - Bumped textbookDataVersion to 10 to force existing installs to re-seed on next launch. Co-Authored-By: Claude Opus 4.7 (1M context) --- Conjuga/Conjuga/Services/DataLoader.swift | 30 ++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Conjuga/Conjuga/Services/DataLoader.swift b/Conjuga/Conjuga/Services/DataLoader.swift index f3cd2d2..cafa1e8 100644 --- a/Conjuga/Conjuga/Services/DataLoader.swift +++ b/Conjuga/Conjuga/Services/DataLoader.swift @@ -6,7 +6,7 @@ actor DataLoader { static let courseDataVersion = 7 static let courseDataKey = "courseDataVersion" - static let textbookDataVersion = 9 + static let textbookDataVersion = 10 static let textbookDataKey = "textbookDataVersion" /// Quick check: does the DB need seeding or course data refresh? @@ -140,9 +140,12 @@ actor DataLoader { // Seed course data (uses the same mainContext so @Query sees it) seedCourseData(context: context) - // Seed textbook data - seedTextbookData(context: context) - UserDefaults.standard.set(textbookDataVersion, forKey: textbookDataKey) + // Seed textbook data — only bump the version key if the seed + // actually inserted rows, so a missing/unparseable bundle doesn't + // permanently lock us out of future re-seeds. + if seedTextbookData(context: context) { + UserDefaults.standard.set(textbookDataVersion, forKey: textbookDataKey) + } } /// Re-seed textbook data if the version has changed. @@ -165,9 +168,12 @@ actor DataLoader { } try? context.save() - seedTextbookData(context: context) - shared.set(textbookDataVersion, forKey: textbookDataKey) - print("Textbook data re-seeded to version \(textbookDataVersion)") + if seedTextbookData(context: context) { + shared.set(textbookDataVersion, forKey: textbookDataKey) + print("Textbook data re-seeded to version \(textbookDataVersion)") + } else { + print("Textbook re-seed failed — leaving version key untouched so next launch retries") + } } /// Re-seed course data if the version has changed (e.g. examples were added). @@ -378,21 +384,22 @@ actor DataLoader { // MARK: - Textbook seeding - private static func seedTextbookData(context: ModelContext) { + @discardableResult + private static func seedTextbookData(context: ModelContext) -> Bool { let url = Bundle.main.url(forResource: "textbook_data", withExtension: "json") ?? Bundle.main.bundleURL.appendingPathComponent("textbook_data.json") guard let data = try? Data(contentsOf: url) else { print("[DataLoader] textbook_data.json not bundled — skipping textbook seed") - return + return false } guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { print("[DataLoader] ERROR: Could not parse textbook_data.json") - return + return false } let courseName = (json["courseName"] as? String) ?? "Textbook" guard let chapters = json["chapters"] as? [[String: Any]] else { print("[DataLoader] ERROR: textbook_data.json missing chapters") - return + return false } var inserted = 0 @@ -480,6 +487,7 @@ actor DataLoader { seedTextbookVocabDecks(context: context, courseName: courseName) print("Textbook seeding complete: \(inserted) chapters") + return inserted > 0 } private static func seedTextbookVocabDecks(context: ModelContext, courseName: String) {