fix(workoutkit): warmup/cooldown nil quand durée 0 (évite assertion crash)

La signature CustomWorkout(warmup: WorkoutStep?, cooldown: WorkoutStep?)
accepte nil. Or notre code passait toujours un WorkoutStep(goal: .time(
warmupMin * 60, .seconds)) — avec warmupMin = 0 on créait un step de
durée zéro qui déclenchait un assertion failure interne dans
CustomWorkout.init (precondition Apple non catchable depuis try/catch
Swift, crash dur).

Confirmé via crash report iOS sur build 1.2 (14) :
  Thread 5 crashed → _assertionFailure
    → CustomWorkout.init(activity:location:displayName:warmup:blocks:
       cooldown:)
  EXC_BREAKPOINT (SIGTRAP)

Fix : let warmupStep: WorkoutStep? = warmupMin > 0 ? WorkoutStep(...)
: nil — idem cooldown. Permet aux apps web de pousser des séances 100%
décrites en blockSteps (renforcement avec items warmup + main + aux +
cooldown détaillés et nommés via displayName).

Bump version requis côté Mac avant rebuild TestFlight.
This commit is contained in:
Sylvain Bettinelli
2026-05-18 09:51:31 +00:00
parent 94f5beebcb
commit 80567d4611

View File

@@ -151,8 +151,15 @@ public class CoachWorkoutKitPlugin: CAPPlugin, CAPBridgedPlugin {
cooldownMin: Double cooldownMin: Double
) async throws { ) async throws {
// 1. Warmup un WorkoutStep avec un goal time // 1. Warmup un WorkoutStep optionnel. Si warmupMin == 0, on passe
let warmupStep = WorkoutStep(goal: .time(warmupMin * 60, .seconds)) // nil au CustomWorkout (la signature accepte WorkoutStep?). Passer
// un WorkoutStep(goal: .time(0, .seconds)) déclenche un assertion
// failure dans CustomWorkout.init (precondition Apple non
// catchable). Cas d'usage : séances 100% décrites en blockSteps
// (renforcement avec items détaillés warmup+main+aux+cooldown).
let warmupStep: WorkoutStep? = warmupMin > 0
? WorkoutStep(goal: .time(warmupMin * 60, .seconds))
: nil
// 2. Construit la liste d'IntervalSteps depuis stepsSpec. // 2. Construit la liste d'IntervalSteps depuis stepsSpec.
// Chaque entrée = (durée min, zone HR optionnelle, isWork bool, label optionnel). // Chaque entrée = (durée min, zone HR optionnelle, isWork bool, label optionnel).
@@ -177,8 +184,11 @@ public class CoachWorkoutKitPlugin: CAPPlugin, CAPBridgedPlugin {
// se répète repeats fois. // se répète repeats fois.
let block = IntervalBlock(steps: intervalSteps, iterations: repeats) let block = IntervalBlock(steps: intervalSteps, iterations: repeats)
// 4. Cooldown // 4. Cooldown idem warmup : nil si cooldownMin == 0 pour éviter
let cooldownStep = WorkoutStep(goal: .time(cooldownMin * 60, .seconds)) // l'assertion failure sur WorkoutStep de durée 0.
let cooldownStep: WorkoutStep? = cooldownMin > 0
? WorkoutStep(goal: .time(cooldownMin * 60, .seconds))
: nil
// 6. CustomWorkout location selon l'activité (indoor pour // 6. CustomWorkout location selon l'activité (indoor pour
// strength/yoga/core, outdoor pour cardio extérieur). // strength/yoga/core, outdoor pour cardio extérieur).