This commit is contained in:
2025-07-19 16:42:47 -04:00
parent 6e46775f58
commit e3c3f2c6f0
38 changed files with 556 additions and 367 deletions

View File

@ -1,15 +1,15 @@
import Foundation
import SwiftData
final class WorkoutsContainer {
final class AppContainer {
static let logger = AppLogger(
subsystem: Bundle.main.bundleIdentifier ?? "dev.rzen.indie.Workouts",
category: "WorkoutsContainer"
category: "AppContainer"
)
static func create() -> ModelContainer {
// Using the current models directly without migration plan to avoid reference errors
let schema = Schema(SchemaV1.models)
let schema = Schema(SchemaVersion.models)
let configuration = ModelConfiguration(cloudKitDatabase: .automatic)
let container = try! ModelContainer(for: schema, configurations: configuration)
return container
@ -20,10 +20,8 @@ final class WorkoutsContainer {
let configuration = ModelConfiguration(isStoredInMemoryOnly: true)
do {
let schema = Schema(SchemaV1.models)
let schema = Schema(SchemaVersion.models)
let container = try ModelContainer(for: schema, configurations: configuration)
let context = ModelContext(container)
return container
} catch {
fatalError("Failed to create preview ModelContainer: \(error.localizedDescription)")

View File

@ -12,23 +12,14 @@ struct CloudKitSyncObserver: ViewModifier {
.onReceive(NotificationCenter.default.publisher(for: .cloudKitDataDidChange)) { _ in
refreshID = UUID()
Task { @MainActor in
// do {
// for entity in modelContext.container.schema.entities {
// fetchAll<entity.Type>(of: entity.Type, from: modelContext)
// }
// } catch {
// print("ERROR: failed to fetch data on CloudKit change")
// }
//
// try? modelContext.fetch(FetchDescriptor<Exercise>())
// try? modelContext.fetch(FetchDescriptor<ExerciseType>())
// try? modelContext.fetch(FetchDescriptor<Muscle>())
// try? modelContext.fetch(FetchDescriptor<MuscleGroup>())
// try? modelContext.fetch(FetchDescriptor<Exercise>())
// try? modelContext.fetch(FetchDescriptor<Exercise>())
// try? modelContext.fetch(FetchDescriptor<Exercise>())
// try? modelContext.fetch(FetchDescriptor<Exercise>())
// TODO: add more entities?
do {
let _ = try await fetchAll(of: Exercise.self, from: modelContext)
let _ = try await fetchAll(of: Split.self, from: modelContext)
let _ = try await fetchAll(of: Workout.self, from: modelContext)
let _ = try await fetchAll(of: WorkoutLog.self, from: modelContext)
} catch {
print("ERROR: failed to fetch \(error.localizedDescription)")
}
}
}
}

View File

@ -5,7 +5,7 @@ enum SchemaV1: VersionedSchema {
static var models: [any PersistentModel.Type] = [
Split.self,
SplitExerciseAssignment.self,
Exercise.self,
Workout.self,
WorkoutLog.self
]

View File

@ -1,12 +0,0 @@
import SwiftData
enum SchemaV2: VersionedSchema {
static var versionIdentifier: Schema.Version = .init(1, 0, 1)
static var models: [any PersistentModel.Type] = [
Split.self,
SplitExerciseAssignment.self,
Workout.self,
WorkoutLog.self
]
}

View File

@ -1,12 +0,0 @@
import SwiftData
enum SchemaV3: VersionedSchema {
static var versionIdentifier: Schema.Version = .init(1, 0, 2)
static var models: [any PersistentModel.Type] = [
Split.self,
SplitExerciseAssignment.self,
Workout.self,
WorkoutLog.self
]
}

View File

@ -2,8 +2,18 @@ import SwiftData
enum SchemaVersion: Int {
case v1
case v2
case v3
static var current: SchemaVersion { .v3 }
static var current: SchemaVersion { .v1 }
static var schemas: [VersionedSchema.Type] {
[
SchemaV1.self
]
}
static var models: [any PersistentModel.Type] {
switch (Self.current) {
case .v1: SchemaV1.models
}
}
}

View File

@ -1,24 +1,29 @@
import SwiftData
import Foundation
struct WorkoutsMigrationPlan: SchemaMigrationPlan {
static var schemas: [VersionedSchema.Type] = [
SchemaV1.self,
SchemaV2.self
]
static var schemas: [VersionedSchema.Type] = SchemaVersion.schemas
static var stages: [MigrationStage] = [
// Migration from V1 to V2: Add status field to WorkoutLog
MigrationStage.custom(
fromVersion: SchemaV1.self,
toVersion: SchemaV2.self,
toVersion: SchemaV1.self,
willMigrate: { context in
// Get all WorkoutLog instances
let workoutLogs = try? context.fetch(FetchDescriptor<WorkoutLog>())
// Update each WorkoutLog with appropriate status based on completed flag
workoutLogs?.forEach { workoutLog in
// If completed is true, set status to .completed, otherwise set to .notStarted
workoutLog.status = workoutLog.completed ? WorkoutStatus.completed : WorkoutStatus.notStarted
print("migrating from v1 to v1")
let workouts = try? context.fetch(FetchDescriptor<Workout>())
workouts?.forEach { workout in
if let status = workout.status {
} else {
workout.status = .notStarted
}
// if let endDate = workout.end {
//
// } else {
// workout.end = Date()
// }
workout.end = Date()
}
},
didMigrate: { _ in