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: "requestAuthorization", returnType: CAPPluginReturnPromise),
|
||||||
CAPPluginMethod(name: "getRoute", returnType: CAPPluginReturnPromise),
|
CAPPluginMethod(name: "getRoute", returnType: CAPPluginReturnPromise),
|
||||||
CAPPluginMethod(name: "getCharacteristics", returnType: CAPPluginReturnPromise),
|
CAPPluginMethod(name: "getCharacteristics", returnType: CAPPluginReturnPromise),
|
||||||
|
CAPPluginMethod(name: "deleteWorkout", returnType: CAPPluginReturnPromise),
|
||||||
]
|
]
|
||||||
|
|
||||||
private lazy var store = HKHealthStore()
|
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 dob = HKObjectType.characteristicType(forIdentifier: .dateOfBirth) { types.insert(dob) }
|
||||||
if let sex = HKObjectType.characteristicType(forIdentifier: .biologicalSex) { types.insert(sex) }
|
if let sex = HKObjectType.characteristicType(forIdentifier: .biologicalSex) { types.insert(sex) }
|
||||||
if let blood = HKObjectType.characteristicType(forIdentifier: .bloodType) { types.insert(blood) }
|
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 {
|
if let err = err {
|
||||||
call.resolve(["granted": false, "reason": err.localizedDescription])
|
call.resolve(["granted": false, "reason": err.localizedDescription])
|
||||||
} else {
|
} else {
|
||||||
@@ -201,4 +205,46 @@ public class CoachHealthRoutePlugin: CAPPlugin, CAPBridgedPlugin {
|
|||||||
call.resolve(["available": true, "route": payload, "count": payload.count])
|
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