Fix lyrics wiped on schema reset #8

Merged
admin merged 1 commits from fix/lyrics-data-loss into main 2026-04-13 10:27:40 -05:00
3 changed files with 24 additions and 13 deletions
Showing only changes of commit 282cd1b3a3 - Show all commits

View File

@@ -10,7 +10,7 @@ private enum CloudPreviewContainer {
let configuration = ModelConfiguration(isStoredInMemoryOnly: true)
return try! ModelContainer(
for: ReviewCard.self, CourseReviewCard.self, UserProgress.self,
TestResult.self, DailyLog.self,
TestResult.self, DailyLog.self, SavedSong.self,
configurations: configuration
)
}()
@@ -67,13 +67,13 @@ struct ConjugaApp: App {
"cloud",
schema: Schema([
ReviewCard.self, CourseReviewCard.self, UserProgress.self,
TestResult.self, DailyLog.self,
TestResult.self, DailyLog.self, SavedSong.self,
]),
cloudKitDatabase: .private("iCloud.com.conjuga.app")
)
cloudContainer = try ModelContainer(
for: ReviewCard.self, CourseReviewCard.self, UserProgress.self,
TestResult.self, DailyLog.self,
TestResult.self, DailyLog.self, SavedSong.self,
configurations: cloudConfig
)
} catch {
@@ -200,7 +200,6 @@ struct ConjugaApp: App {
schema: Schema([
Verb.self, VerbForm.self, IrregularSpan.self,
TenseGuide.self, CourseDeck.self, VocabCard.self,
SavedSong.self,
]),
url: url,
cloudKitDatabase: .none
@@ -208,7 +207,6 @@ struct ConjugaApp: App {
return try ModelContainer(
for: Verb.self, VerbForm.self, IrregularSpan.self,
TenseGuide.self, CourseDeck.self, VocabCard.self,
SavedSong.self,
configurations: localConfig
)
}
@@ -237,7 +235,7 @@ struct ConjugaApp: App {
/// Clears accumulated stale schema metadata from previous container configurations.
/// Bump the version number to force another reset if the schema changes again.
private static func performOneTimeLocalStoreResetIfNeeded(at url: URL) {
let resetVersion = 2 // bump: widget schema moved to SharedModels
let resetVersion = 3 // bump: SavedSong moved to cloud container
let key = "localStoreResetVersion"
let defaults = UserDefaults.standard

View File

@@ -7,9 +7,11 @@ struct LyricsConfirmationView: View {
let result: LyricsSearchResult
let onSave: () -> Void
@Environment(\.modelContext) private var modelContext
@Environment(\.cloudModelContextProvider) private var cloudModelContextProvider
@Environment(\.dismiss) private var dismiss
private var cloudModelContext: ModelContext { cloudModelContextProvider() }
@State private var translatedEN = ""
@State private var isTranslating = true
@State private var translationError = false
@@ -207,8 +209,8 @@ struct LyricsConfirmationView: View {
albumArtURL: result.albumArtURL ?? "",
appleMusicURL: result.appleMusicURL ?? ""
)
modelContext.insert(song)
try? modelContext.save()
cloudModelContext.insert(song)
try? cloudModelContext.save()
onSave()
}
}

View File

@@ -3,9 +3,12 @@ import SharedModels
import SwiftData
struct LyricsLibraryView: View {
@Query(sort: \SavedSong.savedDate, order: .reverse) private var songs: [SavedSong]
@Environment(\.cloudModelContextProvider) private var cloudModelContextProvider
@State private var songs: [SavedSong] = []
@State private var showingSearch = false
private var cloudModelContext: ModelContext { cloudModelContextProvider() }
var body: some View {
Group {
if songs.isEmpty {
@@ -42,18 +45,26 @@ struct LyricsLibraryView: View {
NavigationStack {
LyricsSearchView {
showingSearch = false
loadSongs()
}
}
}
.onAppear(perform: loadSongs)
}
@Environment(\.modelContext) private var modelContext
private func loadSongs() {
let descriptor = FetchDescriptor<SavedSong>(
sortBy: [SortDescriptor(\SavedSong.savedDate, order: .reverse)]
)
songs = (try? cloudModelContext.fetch(descriptor)) ?? []
}
private func deleteSongs(at offsets: IndexSet) {
for index in offsets {
modelContext.delete(songs[index])
cloudModelContext.delete(songs[index])
}
try? modelContext.save()
try? cloudModelContext.save()
loadSongs()
}
}