Build 21
This commit is contained in:
@@ -15,9 +15,12 @@ class HealthKitService: ObservableObject {
|
||||
|
||||
private let userDefaults = UserDefaults.standard
|
||||
private let isEnabledKey = "healthKitEnabled"
|
||||
private let workoutStartDateKey = "healthKitWorkoutStartDate"
|
||||
private let workoutSessionIdKey = "healthKitWorkoutSessionId"
|
||||
|
||||
private init() {
|
||||
loadSettings()
|
||||
restoreActiveWorkout()
|
||||
}
|
||||
|
||||
func loadSettings() {
|
||||
@@ -28,6 +31,62 @@ class HealthKitService: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
/// Restore active workout state
|
||||
private func restoreActiveWorkout() {
|
||||
if let startDate = userDefaults.object(forKey: workoutStartDateKey) as? Date,
|
||||
let sessionIdString = userDefaults.string(forKey: workoutSessionIdKey),
|
||||
let sessionId = UUID(uuidString: sessionIdString)
|
||||
{
|
||||
currentWorkoutStartDate = startDate
|
||||
currentWorkoutSessionId = sessionId
|
||||
print("HealthKit: Restored active workout from \(startDate)")
|
||||
}
|
||||
}
|
||||
|
||||
/// Persist active workout state
|
||||
private func persistActiveWorkout() {
|
||||
if let startDate = currentWorkoutStartDate, let sessionId = currentWorkoutSessionId {
|
||||
userDefaults.set(startDate, forKey: workoutStartDateKey)
|
||||
userDefaults.set(sessionId.uuidString, forKey: workoutSessionIdKey)
|
||||
} else {
|
||||
userDefaults.removeObject(forKey: workoutStartDateKey)
|
||||
userDefaults.removeObject(forKey: workoutSessionIdKey)
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify and restore health integration
|
||||
func verifyAndRestoreIntegration() async {
|
||||
guard isEnabled else { return }
|
||||
|
||||
guard HKHealthStore.isHealthDataAvailable() else {
|
||||
print("HealthKit: Device does not support HealthKit")
|
||||
return
|
||||
}
|
||||
|
||||
checkAuthorization()
|
||||
|
||||
if !isAuthorized {
|
||||
print(
|
||||
"HealthKit: Integration was enabled but authorization lost, attempting to restore..."
|
||||
)
|
||||
|
||||
do {
|
||||
try await requestAuthorization()
|
||||
print("HealthKit: Authorization restored successfully")
|
||||
} catch {
|
||||
print("HealthKit: Failed to restore authorization: \(error.localizedDescription)")
|
||||
}
|
||||
} else {
|
||||
print("HealthKit: Integration verified - authorization is valid")
|
||||
}
|
||||
|
||||
if hasActiveWorkout() {
|
||||
print(
|
||||
"HealthKit: Active workout restored - started at \(currentWorkoutStartDate!)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func setEnabled(_ enabled: Bool) {
|
||||
isEnabled = enabled
|
||||
userDefaults.set(enabled, forKey: isEnabledKey)
|
||||
@@ -73,6 +132,8 @@ class HealthKitService: ObservableObject {
|
||||
|
||||
currentWorkoutStartDate = startDate
|
||||
currentWorkoutSessionId = sessionId
|
||||
persistActiveWorkout()
|
||||
print("HealthKit: Started workout for session \(sessionId)")
|
||||
}
|
||||
|
||||
func endWorkout(endDate: Date) async throws {
|
||||
@@ -93,26 +154,45 @@ class HealthKitService: ObservableObject {
|
||||
|
||||
let energyBurned = HKQuantity(unit: .kilocalorie(), doubleValue: calories)
|
||||
|
||||
let workout = HKWorkout(
|
||||
activityType: .climbing,
|
||||
start: startDate,
|
||||
end: endDate,
|
||||
duration: duration,
|
||||
totalEnergyBurned: energyBurned,
|
||||
totalDistance: nil,
|
||||
metadata: [
|
||||
HKMetadataKeyIndoorWorkout: true
|
||||
]
|
||||
let workoutConfiguration = HKWorkoutConfiguration()
|
||||
workoutConfiguration.activityType = .climbing
|
||||
workoutConfiguration.locationType = .indoor
|
||||
|
||||
let builder = HKWorkoutBuilder(
|
||||
healthStore: healthStore,
|
||||
configuration: workoutConfiguration,
|
||||
device: .local()
|
||||
)
|
||||
|
||||
do {
|
||||
try await healthStore.save(workout)
|
||||
try await builder.beginCollection(at: startDate)
|
||||
|
||||
let energyBurnedType = HKQuantityType.quantityType(forIdentifier: .activeEnergyBurned)!
|
||||
let energySample = HKQuantitySample(
|
||||
type: energyBurnedType,
|
||||
quantity: energyBurned,
|
||||
start: startDate,
|
||||
end: endDate
|
||||
)
|
||||
try await builder.addSamples([energySample])
|
||||
|
||||
try await builder.addMetadata([HKMetadataKeyIndoorWorkout: true])
|
||||
|
||||
try await builder.endCollection(at: endDate)
|
||||
let workout = try await builder.finishWorkout()
|
||||
|
||||
print(
|
||||
"HealthKit: Workout saved successfully with id: \(workout?.uuid.uuidString ?? "unknown")"
|
||||
)
|
||||
|
||||
currentWorkoutStartDate = nil
|
||||
currentWorkoutSessionId = nil
|
||||
persistActiveWorkout()
|
||||
} catch {
|
||||
print("HealthKit: Failed to save workout: \(error.localizedDescription)")
|
||||
currentWorkoutStartDate = nil
|
||||
currentWorkoutSessionId = nil
|
||||
persistActiveWorkout()
|
||||
|
||||
throw HealthKitError.workoutSaveFailed
|
||||
}
|
||||
@@ -121,6 +201,8 @@ class HealthKitService: ObservableObject {
|
||||
func cancelWorkout() {
|
||||
currentWorkoutStartDate = nil
|
||||
currentWorkoutSessionId = nil
|
||||
persistActiveWorkout()
|
||||
print("HealthKit: Workout cancelled")
|
||||
}
|
||||
|
||||
func hasActiveWorkout() -> Bool {
|
||||
|
||||
Reference in New Issue
Block a user