diff --git a/ios/App/App/CoachWorkoutKit.swift b/ios/App/App/CoachWorkoutKit.swift index 7a8571c..550daf9 100644 --- a/ios/App/App/CoachWorkoutKit.swift +++ b/ios/App/App/CoachWorkoutKit.swift @@ -14,12 +14,12 @@ // repeats: 6, // cooldownMin: 10, // }) -// → { sent: true } si l'user a tapé "Ajouter aux workouts" dans la sheet +// → { sent: true } si la sheet a été présentée et user a tapé Ajouter // → reject avec error string sinon // -// L'app présente une sheet système iOS qui demande à l'user de confirmer -// l'ajout du workout au Watch. Le workout devient alors disponible dans -// Apple Watch → Exercice → Workouts personnalisés → [displayName]. +// Sur iOS 17.4+ : utilise WorkoutScheduler.shared.preview(plan) qui ouvre +// la sheet système iOS 'Ajouter aux workouts'. +// Sur iOS 17.0-17.3 (rare) : fallback schedule() qui ajoute direct. import Foundation import Capacitor @@ -103,50 +103,59 @@ public class CoachWorkoutKitPlugin: CAPPlugin { repeats: Int, cooldownMin: Double ) async throws { - // 1. Warmup step (1 fois) + + // 1. Warmup — un WorkoutStep avec un goal time let warmupStep = WorkoutStep(goal: .time(warmupMin * 60, .seconds)) - // 2. Work + Rest interval block (répété N fois) - var workAlerts: [any WorkoutAlertEnumeration] = [] + // 2. Work step — wrapped dans un IntervalStep avec purpose .work + var workWorkoutStep = WorkoutStep(goal: .time(workMin * 60, .seconds)) if let zone = workHrZone { - workAlerts.append(HeartRateZoneAlert(zone: zone)) + workWorkoutStep.alert = HeartRateZoneAlert(zone: zone) } - let workStep = IntervalStep( - .work, - goal: .time(workMin * 60, .seconds), - alert: workAlerts.first as? (any WorkoutAlertEnumeration) - ) + let workInterval = IntervalStep(.work, step: workWorkoutStep) - var restAlerts: [any WorkoutAlertEnumeration] = [] + // 3. Rest step — IntervalStep purpose .recovery + var restWorkoutStep = WorkoutStep(goal: .time(restMin * 60, .seconds)) if let zone = restHrZone { - restAlerts.append(HeartRateZoneAlert(zone: zone)) + restWorkoutStep.alert = HeartRateZoneAlert(zone: zone) } - let restStep = IntervalStep( - .recovery, - goal: .time(restMin * 60, .seconds), - alert: restAlerts.first as? (any WorkoutAlertEnumeration) - ) + let restInterval = IntervalStep(.recovery, step: restWorkoutStep) - let intervalBlock = IntervalBlock( - steps: [workStep, restStep], - iterations: repeats - ) + // 4. Block répété N fois + let block = IntervalBlock(steps: [workInterval, restInterval], iterations: repeats) - // 3. Cooldown step + // 5. Cooldown let cooldownStep = WorkoutStep(goal: .time(cooldownMin * 60, .seconds)) - // 4. Custom workout + // 6. CustomWorkout let custom = CustomWorkout( activity: activity, location: .outdoor, displayName: displayName, warmup: warmupStep, - blocks: [intervalBlock], + blocks: [block], cooldown: cooldownStep ) - // 5. Plan + preview (présente la sheet système "Ajouter à mes workouts") + // 7. Plan let plan = WorkoutPlan(.custom(custom)) - try await WorkoutScheduler.shared.preview(plan) + + // 8. Request authorization si pas déjà accordée + let authState = await WorkoutScheduler.shared.authorizationState + if authState != .authorized { + _ = try await WorkoutScheduler.shared.requestAuthorization() + } + + // 9. Présenter la sheet système (iOS 17.4+) ou scheduler direct (17.0-17.3) + if #available(iOS 17.4, *) { + try await WorkoutScheduler.shared.preview(plan) + } else { + // Fallback : schedule "now" pour rendre dispo sur Watch + let now = Calendar.current.dateComponents( + [.year, .month, .day, .hour, .minute], + from: Date() + ) + _ = try await WorkoutScheduler.shared.schedule(plan, at: now) + } } }