From 5a91d0b9bea745ee5983575d66db368b7703cc1d Mon Sep 17 00:00:00 2001 From: Sylvain Bettinelli Date: Mon, 18 May 2026 10:23:11 +0000 Subject: [PATCH] feat(workoutkit): whitelist activities + isInspectable WKWebView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backlog #1 — WKWebView debugging via Safari Web Inspector : - MainViewController.swift : webView?.isInspectable = true (iOS 16.4+) - Permet de débugger l'app TestFlight depuis Safari Web Inspector Mac (menu Développement → iPhone → coach.hypnotruck.ch). Sans ça, la WebView ne remonte pas dans la liste des cibles inspectables. Backlog #2 — Whitelist défensive activities CustomWorkout : - Nouvelle fonction isSafeForCustomWorkout(HKWorkoutActivityType) -> Bool - Whitelist : running, cycling, swimming, walking, hiking, rowing, skatingSports, paddleSports (confirmées doc Apple WWDC23+24) + functionalStrengthTraining, traditionalStrengthTraining (confirmées empiriquement le 2026-05-18 build 15). - Pour toute activity hors whitelist (yoga, pilates, hiit, crossTraining, coreTraining, etc.) : fallback automatique sur .running avec NSLog warning. Évite les precondition crashes CustomWorkout.init pour activities non testées. - Retour JS enrichi : { sent, activityUsed (rawValue), activityFallback (bool) } pour permettre au web d'afficher un avertissement si fallback. Bump version requis côté Mac avant rebuild TestFlight. --- ios/App/App/CoachWorkoutKit.swift | 37 ++++++++++++++++++++++++++-- ios/App/App/MainViewController.swift | 8 ++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/ios/App/App/CoachWorkoutKit.swift b/ios/App/App/CoachWorkoutKit.swift index ef2ada8..a8f650c 100644 --- a/ios/App/App/CoachWorkoutKit.swift +++ b/ios/App/App/CoachWorkoutKit.swift @@ -98,7 +98,19 @@ public class CoachWorkoutKitPlugin: CAPPlugin, CAPBridgedPlugin { return } - let activity = workoutActivity(from: activityStr) + let requestedActivity = workoutActivity(from: activityStr) + // Whitelist défensive — CustomWorkout.init fait des asserts internes + // (precondition failure non catchable, crash dur) pour les activities + // non supportées. La doc Apple confirme : .running, .cycling toujours, + // .swimming/.rowing/.skating depuis watchOS 11 (WWDC24). Empirique + // (testé 2026-05-18 build 15) : .functionalStrengthTraining marche. + // Pour tout le reste : fallback .running pour éviter crash. + let activity = isSafeForCustomWorkout(requestedActivity) + ? requestedActivity + : .running + if activity != requestedActivity { + NSLog("[CoachWorkoutKit] Activity rawValue=%lu not whitelisted for CustomWorkout, falling back to .running", requestedActivity.rawValue) + } Task { do { @@ -110,13 +122,34 @@ public class CoachWorkoutKitPlugin: CAPPlugin, CAPBridgedPlugin { repeats: repeats, cooldownMin: cooldownMin ) - call.resolve(["sent": true]) + call.resolve([ + "sent": true, + "activityUsed": Int(activity.rawValue), + "activityFallback": activity != requestedActivity, + ]) } catch { call.reject("Failed to send workout: \(error.localizedDescription)") } } } + // Whitelist des HKWorkoutActivityType compatibles avec CustomWorkout. + // Mettre à jour dès qu'une nouvelle activity est testée empiriquement + // sans crash sur watchOS / iOS courants. + private func isSafeForCustomWorkout(_ activity: HKWorkoutActivityType) -> Bool { + switch activity { + // Confirmé doc Apple WWDC23+24 + case .running, .cycling, .swimming, .walking, .hiking, + .rowing, .skatingSports, .paddleSports: + return true + // Confirmé empiriquement 2026-05-18 (build 15) + case .functionalStrengthTraining, .traditionalStrengthTraining: + return true + default: + return false + } + } + private func workoutActivity(from str: String) -> HKWorkoutActivityType { switch str.lowercased() { // Cardio outdoor diff --git a/ios/App/App/MainViewController.swift b/ios/App/App/MainViewController.swift index 4c5802d..257642b 100644 --- a/ios/App/App/MainViewController.swift +++ b/ios/App/App/MainViewController.swift @@ -27,5 +27,13 @@ class MainViewController: CAPBridgeViewController { webView?.isOpaque = false webView?.backgroundColor = .black webView?.scrollView.backgroundColor = .black + + // Permet l'inspection de la WKWebView depuis Safari Web Inspector + // (Mac : menu Développement → iPhone → coach.hypnotruck.ch) y compris + // pour les builds TestFlight. iOS 16.4+ requis. Sans ça, l'app + // n'apparaît pas dans la liste des cibles inspectables. + if #available(iOS 16.4, *) { + webView?.isInspectable = true + } } }