feat(workoutkit): whitelist activities + isInspectable WKWebView
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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user