Merge pull request 'Fix lyrics wiped on schema reset' (#8) from fix/lyrics-data-loss into main
This commit was merged in pull request #8.
This commit is contained in:
@@ -10,7 +10,7 @@ private enum CloudPreviewContainer {
|
|||||||
let configuration = ModelConfiguration(isStoredInMemoryOnly: true)
|
let configuration = ModelConfiguration(isStoredInMemoryOnly: true)
|
||||||
return try! ModelContainer(
|
return try! ModelContainer(
|
||||||
for: ReviewCard.self, CourseReviewCard.self, UserProgress.self,
|
for: ReviewCard.self, CourseReviewCard.self, UserProgress.self,
|
||||||
TestResult.self, DailyLog.self,
|
TestResult.self, DailyLog.self, SavedSong.self,
|
||||||
configurations: configuration
|
configurations: configuration
|
||||||
)
|
)
|
||||||
}()
|
}()
|
||||||
@@ -67,13 +67,13 @@ struct ConjugaApp: App {
|
|||||||
"cloud",
|
"cloud",
|
||||||
schema: Schema([
|
schema: Schema([
|
||||||
ReviewCard.self, CourseReviewCard.self, UserProgress.self,
|
ReviewCard.self, CourseReviewCard.self, UserProgress.self,
|
||||||
TestResult.self, DailyLog.self,
|
TestResult.self, DailyLog.self, SavedSong.self,
|
||||||
]),
|
]),
|
||||||
cloudKitDatabase: .private("iCloud.com.conjuga.app")
|
cloudKitDatabase: .private("iCloud.com.conjuga.app")
|
||||||
)
|
)
|
||||||
cloudContainer = try ModelContainer(
|
cloudContainer = try ModelContainer(
|
||||||
for: ReviewCard.self, CourseReviewCard.self, UserProgress.self,
|
for: ReviewCard.self, CourseReviewCard.self, UserProgress.self,
|
||||||
TestResult.self, DailyLog.self,
|
TestResult.self, DailyLog.self, SavedSong.self,
|
||||||
configurations: cloudConfig
|
configurations: cloudConfig
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
@@ -200,7 +200,6 @@ struct ConjugaApp: App {
|
|||||||
schema: Schema([
|
schema: Schema([
|
||||||
Verb.self, VerbForm.self, IrregularSpan.self,
|
Verb.self, VerbForm.self, IrregularSpan.self,
|
||||||
TenseGuide.self, CourseDeck.self, VocabCard.self,
|
TenseGuide.self, CourseDeck.self, VocabCard.self,
|
||||||
SavedSong.self,
|
|
||||||
]),
|
]),
|
||||||
url: url,
|
url: url,
|
||||||
cloudKitDatabase: .none
|
cloudKitDatabase: .none
|
||||||
@@ -208,7 +207,6 @@ struct ConjugaApp: App {
|
|||||||
return try ModelContainer(
|
return try ModelContainer(
|
||||||
for: Verb.self, VerbForm.self, IrregularSpan.self,
|
for: Verb.self, VerbForm.self, IrregularSpan.self,
|
||||||
TenseGuide.self, CourseDeck.self, VocabCard.self,
|
TenseGuide.self, CourseDeck.self, VocabCard.self,
|
||||||
SavedSong.self,
|
|
||||||
configurations: localConfig
|
configurations: localConfig
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -237,7 +235,7 @@ struct ConjugaApp: App {
|
|||||||
/// Clears accumulated stale schema metadata from previous container configurations.
|
/// Clears accumulated stale schema metadata from previous container configurations.
|
||||||
/// Bump the version number to force another reset if the schema changes again.
|
/// Bump the version number to force another reset if the schema changes again.
|
||||||
private static func performOneTimeLocalStoreResetIfNeeded(at url: URL) {
|
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 key = "localStoreResetVersion"
|
||||||
let defaults = UserDefaults.standard
|
let defaults = UserDefaults.standard
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ struct LyricsConfirmationView: View {
|
|||||||
let result: LyricsSearchResult
|
let result: LyricsSearchResult
|
||||||
let onSave: () -> Void
|
let onSave: () -> Void
|
||||||
|
|
||||||
@Environment(\.modelContext) private var modelContext
|
@Environment(\.cloudModelContextProvider) private var cloudModelContextProvider
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
|
private var cloudModelContext: ModelContext { cloudModelContextProvider() }
|
||||||
|
|
||||||
@State private var translatedEN = ""
|
@State private var translatedEN = ""
|
||||||
@State private var isTranslating = true
|
@State private var isTranslating = true
|
||||||
@State private var translationError = false
|
@State private var translationError = false
|
||||||
@@ -207,8 +209,8 @@ struct LyricsConfirmationView: View {
|
|||||||
albumArtURL: result.albumArtURL ?? "",
|
albumArtURL: result.albumArtURL ?? "",
|
||||||
appleMusicURL: result.appleMusicURL ?? ""
|
appleMusicURL: result.appleMusicURL ?? ""
|
||||||
)
|
)
|
||||||
modelContext.insert(song)
|
cloudModelContext.insert(song)
|
||||||
try? modelContext.save()
|
try? cloudModelContext.save()
|
||||||
onSave()
|
onSave()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ import SharedModels
|
|||||||
import SwiftData
|
import SwiftData
|
||||||
|
|
||||||
struct LyricsLibraryView: View {
|
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
|
@State private var showingSearch = false
|
||||||
|
|
||||||
|
private var cloudModelContext: ModelContext { cloudModelContextProvider() }
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if songs.isEmpty {
|
if songs.isEmpty {
|
||||||
@@ -42,18 +45,26 @@ struct LyricsLibraryView: View {
|
|||||||
NavigationStack {
|
NavigationStack {
|
||||||
LyricsSearchView {
|
LyricsSearchView {
|
||||||
showingSearch = false
|
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) {
|
private func deleteSongs(at offsets: IndexSet) {
|
||||||
for index in offsets {
|
for index in offsets {
|
||||||
modelContext.delete(songs[index])
|
cloudModelContext.delete(songs[index])
|
||||||
}
|
}
|
||||||
try? modelContext.save()
|
try? cloudModelContext.save()
|
||||||
|
loadSongs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user