diff --git a/Conjuga/Conjuga/Services/DataLoader.swift b/Conjuga/Conjuga/Services/DataLoader.swift index cafa1e8..b7808c7 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 = 10 + static let textbookDataVersion = 11 static let textbookDataKey = "textbookDataVersion" /// Quick check: does the DB need seeding or course data refresh? @@ -156,17 +156,26 @@ actor DataLoader { print("Textbook data version outdated — re-seeding...") let context = ModelContext(container) - // Only wipe textbook chapters and our textbook-scoped CourseDecks - // (not the LanGo decks, which live in the same tables). - try? context.delete(model: TextbookChapter.self) + // Fetch + delete individually instead of batch delete. SwiftData's + // context.delete(model:) hits the store directly and doesn't always + // clear the unique-constraint index before the reseed's save runs, + // so re-inserting rows with the same .unique id can throw. let textbookCourseName = "Complete Spanish Step-by-Step" + if let existing = try? context.fetch(FetchDescriptor()) { + for chapter in existing { context.delete(chapter) } + } let deckDescriptor = FetchDescriptor( predicate: #Predicate { $0.courseName == textbookCourseName } ) if let decks = try? context.fetch(deckDescriptor) { for deck in decks { context.delete(deck) } } - try? context.save() + do { + try context.save() + } catch { + print("[DataLoader] ERROR: textbook wipe save failed: \(error)") + return + } if seedTextbookData(context: context) { shared.set(textbookDataVersion, forKey: textbookDataKey) @@ -480,14 +489,27 @@ actor DataLoader { inserted += 1 } - try? context.save() + do { + try context.save() + } catch { + print("[DataLoader] ERROR: textbook chapter save failed: \(error)") + return false + } + + // Verify rows actually hit the store — guards against the case where + // save returned cleanly but no rows were persisted. + let persisted = (try? context.fetchCount(FetchDescriptor())) ?? 0 + guard persisted > 0 else { + print("[DataLoader] ERROR: textbook seeded \(inserted) chapters but persisted count is 0") + return false + } // Seed textbook-derived vocabulary flashcards as CourseDecks so the // existing Course UI can surface them alongside LanGo decks. seedTextbookVocabDecks(context: context, courseName: courseName) - print("Textbook seeding complete: \(inserted) chapters") - return inserted > 0 + print("Textbook seeding complete: \(inserted) chapters inserted, \(persisted) persisted") + return true } private static func seedTextbookVocabDecks(context: ModelContext, courseName: String) {