Commit Graph

8 Commits

Author SHA1 Message Date
Sylvain Bettinelli
5e9b4a3df6 La Live Activity restait affichée après la fin de séance
La montre n'annonçait pas la fin : le flux de samples s'arrêtait, et
l'iPhone ne pouvait pas distinguer « séance terminée » de « montre hors de
portée ». La Live Activity restait donc figée sur la dernière FC reçue —
un cœur à 74 bpm en permanence dans la Dynamic Island.

Trois causes cumulées, toutes corrigées :

1. Aucun message de fin. WorkoutManager envoie maintenant `liveEnded` à
   l'arrêt de la session HealthKit, en cas d'échec, et en mode test.
2. Le seul chemin de terminaison côté iPhone était le watchdog de
   LiveStore, un Timer du main runloop — qui ne tourne pas quand l'app est
   suspendue en arrière-plan, c'est-à-dire pendant toute la séance.
   `endLive()` termine désormais l'activité dès réception du message.
3. `dismissalPolicy: .default` laissait la bannière ~4 h APRÈS la fin.
   Passé en `.immediate`.

Filet de sécurité : `adoptExisting()` au lancement reprend la main sur une
activité orpheline (app tuée pendant une séance, `current` perdu) et
termine celles de plus de 6 h.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 12:50:32 +00:00
Sylvain
5a1568ef2f perf(watchos-live): FC poussée en temps réel à chaque échantillon (throttle 2s -> envoi immédiat)
Le throttle fixe de 2s ajoutait jusqu'à 2s de latence sur /live vs l'app
Exercice native d'Apple (instantanée). Désormais chaque nouvel échantillon FC
est envoyé immédiatement ; throttle léger 0.5s conservé uniquement pour
calories/distance (anti-saturation BLE).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 12:05:27 +02:00
Sylvain
3ce8ca9e28 feat(watchos): mode Test (FC simulée) — valide le flux sans HealthKit
Bouton "Test (FC simulée)" qui envoie des samples synthétiques (FC ~110-150,
calories, distance, durée) via WCSession toutes les 2s, sans démarrer de séance
HealthKit. Permet de valider watch -> iPhone -> /live indépendamment de
l'autorisation Santé (bloquée par un sous-système Santé coincé sur la Watch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 20:21:24 +02:00
Sylvain
d1c1b88da4 feat(watchos): message clair si accès Santé refusé (au lieu de Error(7))
Si authorizationStatus(workoutType) == .sharingDenied après requestAuthorization,
on n'essaie pas de démarrer la séance (qui échouerait en HKErrorAuthorizationDenied)
et on affiche un message demandant d'activer Coach dans Réglages → Santé.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 19:54:48 +02:00
Sylvain
6cb89359c6 chore(watchos): logs diagnostics séance (autorisation + erreur HK domaine/code)
Logger os "ch.hypnotruck.coach.watchkitapp/workout" : trace requestAuthorization,
statut de partage, startActivity/beginCollection, transitions de session et
surtout didFailWithError (domaine+code) pour identifier la cause de l'Error(7).
Logger en constante de fichier (Sendable) pour rester accessible aux délégués
nonisolated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 19:50:56 +02:00
Sylvain
a4f8276b13 fix(watchos): empêche les sessions HK multiples + nettoie après échec/fin
Garde anti double-démarrage (guard !isRunning, session == nil) pour éviter la
cascade de HKLiveWorkoutBuilder en Error(7) quand on retape l'activité. Reset
session/builder à nil après échec, fin et erreur de séance pour permettre une
nouvelle tentative propre. Le statusMessage d'erreur reste donc visible sur le
picker.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 19:47:17 +02:00
Sylvain
167c1e4c27 fix(watchos): WorkoutManager @MainActor — concurrency Swift 6 clean
Classe @MainActor (implicitement Sendable) ; callbacks HealthKit nonisolated qui
calculent les valeurs hors-main puis hoppent via Task { @MainActor }. Récupère le
builder depuis la session passée au délégué (plus de capture de self non-Sendable).
Build watchsimulator : 0 warning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 16:22:17 +02:00
Sylvain
c6f5a7ffc9 feat(watchos): WorkoutManager (HKLiveWorkoutBuilder) — séance live + push iPhone
HKWorkoutSession(healthStore:configuration:) + associatedWorkoutBuilder +
HKLiveWorkoutDataSource. Collecte FC (mostRecent), calories/distance (sum) via
statistics(for:), publication @Published sur main, envoi throttlé (2s) vers
ConnectivityManager. Clôture async endCollection(at:)/finishWorkout(). Build OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 16:20:11 +02:00