feat(healthkit): deleteWorkout dans CoachHealthRoute (supprime workout d'Apple Santé)
Nouveau plugin method @objc deleteWorkout(workoutUUID:) -> retrouve le HKWorkout par UUID puis HKHealthStore.delete. requestAuthorization étendu pour inclure share auth de HKWorkoutType (requise pour delete). Utilisé par la page /workouts au swipe-to-delete pour synchroniser la suppression avec Apple Santé. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@ public class CoachHealthRoutePlugin: CAPPlugin, CAPBridgedPlugin {
|
||||
CAPPluginMethod(name: "requestAuthorization", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getRoute", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getCharacteristics", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "deleteWorkout", returnType: CAPPluginReturnPromise),
|
||||
]
|
||||
|
||||
private lazy var store = HKHealthStore()
|
||||
@@ -51,7 +52,10 @@ public class CoachHealthRoutePlugin: CAPPlugin, CAPBridgedPlugin {
|
||||
if let dob = HKObjectType.characteristicType(forIdentifier: .dateOfBirth) { types.insert(dob) }
|
||||
if let sex = HKObjectType.characteristicType(forIdentifier: .biologicalSex) { types.insert(sex) }
|
||||
if let blood = HKObjectType.characteristicType(forIdentifier: .bloodType) { types.insert(blood) }
|
||||
store.requestAuthorization(toShare: nil, read: types) { ok, err in
|
||||
// Share workoutType requis pour deleteWorkout (HKHealthStore.delete
|
||||
// exige share auth). Read-only pour les autres types.
|
||||
let shareTypes: Set<HKSampleType> = [HKObjectType.workoutType()]
|
||||
store.requestAuthorization(toShare: shareTypes, read: types) { ok, err in
|
||||
if let err = err {
|
||||
call.resolve(["granted": false, "reason": err.localizedDescription])
|
||||
} else {
|
||||
@@ -201,4 +205,46 @@ public class CoachHealthRoutePlugin: CAPPlugin, CAPBridgedPlugin {
|
||||
call.resolve(["available": true, "route": payload, "count": payload.count])
|
||||
}
|
||||
}
|
||||
|
||||
/// Supprime un workout d'Apple Santé via son UUID. Requiert l'autorisation
|
||||
/// share pour HKWorkoutType (demandée dans requestAuthorization). Renvoie
|
||||
/// {deleted: true} si trouvé+supprimé, {deleted: false, reason: ...} si
|
||||
/// introuvable, ou reject() si erreur HealthKit.
|
||||
@objc func deleteWorkout(_ call: CAPPluginCall) {
|
||||
guard HKHealthStore.isHealthDataAvailable() else {
|
||||
call.reject("HealthKit unavailable")
|
||||
return
|
||||
}
|
||||
guard let uuidStr = call.getString("workoutUUID"),
|
||||
let uuid = UUID(uuidString: uuidStr) else {
|
||||
call.reject("workoutUUID requis (UUID string)")
|
||||
return
|
||||
}
|
||||
// 1. Retrouver le HKWorkout via son UUID (même pattern que getRoute).
|
||||
let pred = HKQuery.predicateForObject(with: uuid)
|
||||
let wq = HKSampleQuery(
|
||||
sampleType: HKObjectType.workoutType(),
|
||||
predicate: pred,
|
||||
limit: 1,
|
||||
sortDescriptors: nil
|
||||
) { _, results, err in
|
||||
if let err = err {
|
||||
call.reject("Workout fetch failed: \(err.localizedDescription)")
|
||||
return
|
||||
}
|
||||
guard let workout = results?.first as? HKWorkout else {
|
||||
call.resolve(["deleted": false, "reason": "workout not found"])
|
||||
return
|
||||
}
|
||||
// 2. Supprime le workout d'Apple Santé (requiert share auth pour workoutType).
|
||||
self.store.delete(workout) { success, err in
|
||||
if let err = err {
|
||||
call.reject("Delete failed: \(err.localizedDescription)")
|
||||
return
|
||||
}
|
||||
call.resolve(["deleted": success])
|
||||
}
|
||||
}
|
||||
store.execute(wq)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user