Pendant natif du lecteur web. Bouton Démarrer par bloc : un exercice à la fois, décompte en anneau, passage auto, haptique à chaque transition, pause et navigation. Pendant une routine au sol, la montre est bien plus pratique que d'aller chercher le téléphone — c'est tout l'intérêt de la version watchOS. Chaque exercice écoulé est coché via RoutineStore.toggle, donc renvoyé à l'iPhone puis au serveur : à la fin le bloc est à jour sur les trois surfaces. La durée par exercice est désormais transmise dans le snapshot (duration_sec, optionnel pour rester compatible avec les snapshots déjà persistés) : la vue guidée utilise la vraie durée au lieu de répartir celle du bloc. RoutineGuidedView.swift est déjà référencé dans le pbxproj (target CoachWatch), aucun Add Files à faire. Backup : project.pbxproj.bak-guided NON COMPILÉ — à inclure au prochain build Xcode. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
143 lines
6.2 KiB
Markdown
143 lines
6.2 KiB
Markdown
# Runbook Mac — Routine quotidienne sur l'Apple Watch
|
|
|
|
**Écrit côté dev (Linux) le 2026-08-03. Rien n'est compilé.** Ce document dit
|
|
quoi faire sur le Mac pour activer la fonctionnalité, et comment la tester.
|
|
|
|
## Ce que ça fait
|
|
|
|
La routine anti-douleurs (6 blocs) apparaît sur la montre, cochable au doigt.
|
|
Une coche faite sur la Watch remonte à l'iPhone, qui la POSTe au serveur — donc
|
|
la page `/routine` et le widget de la home reflètent immédiatement l'état, et
|
|
inversement.
|
|
|
|
## Architecture (à connaître avant de débugger)
|
|
|
|
```
|
|
page /routine (web) Apple Watch (RoutineView)
|
|
│ coche │ coche
|
|
▼ ▼
|
|
POST /api/routine/check ConnectivityManager.sendRoutine
|
|
│ │ sendMessage / transferUserInfo
|
|
▼ ▼
|
|
data/routine_log.json ◄────────── CoachLiveBridge (délégué WCSession)
|
|
▲ POST /api/routine/day │ routeIfNotLiveSample()
|
|
│ ▼
|
|
└─────────────────────── CoachRoutineBridge (NotificationCenter)
|
|
│ notifyListeners
|
|
▼
|
|
routine.js re-render
|
|
```
|
|
|
|
Trois décisions structurantes, à ne pas défaire sans raison :
|
|
|
|
1. **L'état est serveur, plus en localStorage.** La Watch n'a aucun accès au
|
|
localStorage du WKWebView : il fallait un arbitre commun aux trois surfaces.
|
|
2. **On transmet l'état COMPLET du jour, jamais un delta.** Si un message
|
|
WatchConnectivity se perd, le suivant recale tout au lieu de laisser les deux
|
|
côtés diverger. C'est aussi pour ça que `updateApplicationContext` convient :
|
|
le système n'en garde que le dernier, ce qui est la sémantique voulue.
|
|
3. **`CoachRoutineBridge` n'est PAS `WCSession.delegate`.** `CoachLiveBridge`
|
|
l'est déjà et le délégué est unique. `CoachLiveBridge.routeIfNotLiveSample()`
|
|
aiguille les messages `routineDone` vers `NotificationCenter` — c'est le seul
|
|
endroit où j'ai touché au flux live workout (validé E2E sur device le 31/05),
|
|
et il retourne `true` sans rien émettre, donc `LiveStore` n'est pas pollué.
|
|
|
|
Les blocs eux-mêmes **voyagent avec l'état** : rien n'est codé en dur côté
|
|
watchOS. Modifier la routine côté web ne demande donc aucun rebuild.
|
|
|
|
## Étapes Mac
|
|
|
|
### 1. Récupérer le code
|
|
|
|
```bash
|
|
# Xcode FERMÉ (règle COWORK)
|
|
cd ~/coach-ios && git pull
|
|
npm install && npx cap sync ios
|
|
open ios/App/App.xcworkspace
|
|
```
|
|
|
|
### 2. Rien à ajouter dans Xcode
|
|
|
|
Les trois nouveaux fichiers sont **déjà référencés dans `project.pbxproj`**,
|
|
dans la bonne target :
|
|
|
|
| Fichier | Target |
|
|
|---|---|
|
|
| `App/CoachRoutineBridge.swift` | App |
|
|
| `CoachWatch/RoutineStore.swift` | CoachWatch |
|
|
| `CoachWatch/RoutineView.swift` | CoachWatch |
|
|
|
|
Vérification rapide si un doute :
|
|
```bash
|
|
grep -c "RoutineView.swift" ios/App/App.xcodeproj/project.pbxproj # doit valoir 4
|
|
```
|
|
(4 = PBXBuildFile + PBXFileReference + children du groupe + Sources phase.)
|
|
|
|
Backup du pbxproj avant modification : `project.pbxproj.bak-routine`.
|
|
|
|
### 3. Build
|
|
|
|
Clean Build Folder (`Cmd+Shift+K`) → Run sur l'iPhone, avec la Watch appairée.
|
|
|
|
⚠️ `CoachAuth.swift` doit exister (gitignored) : le plugin s'en sert pour
|
|
authentifier son POST vers `/api/routine/day`. Sans lui, ça ne compile pas.
|
|
|
|
### 4. Tester le cycle complet
|
|
|
|
1. Ouvrir l'app iPhone sur `/routine` — ça pousse les blocs vers la Watch.
|
|
2. Sur la Watch : app Coach → **Routine du jour** → la liste des 6 blocs doit
|
|
apparaître avec la progression.
|
|
3. Cocher un bloc sur la Watch → retour à l'iPhone, la page `/routine` doit se
|
|
mettre à jour **sans rechargement** (event `routineUpdated`).
|
|
4. Cocher un bloc sur l'iPhone → rouvrir la vue Watch, l'état doit suivre.
|
|
5. Vérifier côté serveur :
|
|
```bash
|
|
ssh ubuntu@83.228.246.229 'cat /home/ubuntu/coach_sportif/data/routine_log.json'
|
|
```
|
|
|
|
### 5. Si la Watch affiche « Ouvre l'app Coach sur l'iPhone »
|
|
|
|
C'est l'état vide normal au premier lancement : la montre n'a pas encore reçu de
|
|
blocs. Si ça persiste après avoir ouvert `/routine` sur l'iPhone :
|
|
|
|
- console Safari (Développement → iPhone → coach.hypnotruck.ch) :
|
|
```js
|
|
await Capacitor.Plugins.CoachRoutineBridge.getStatus()
|
|
```
|
|
→ `paired` et `watchAppInstalled` doivent être `true`.
|
|
- Xcode console, filtre `subsystem:ch.hypnotruck.coach category:routine`.
|
|
- `updateApplicationContext` échoue silencieusement si la session n'est pas
|
|
activée : vérifier que `CoachLiveBridge.load()` a bien tourné (c'est lui qui
|
|
active la session).
|
|
|
|
### 6. Si une coche Watch ne remonte pas
|
|
|
|
- Hors de portée de l'iPhone, c'est **normal et attendu** : `transferUserInfo`
|
|
garantit la livraison différée, la coche partira au prochain rapprochement.
|
|
La vue affiche un bouton « Renvoyer vers l'iPhone » si l'envoi a échoué net.
|
|
- Sinon : vérifier le log `POST /api/routine/day` côté Xcode (le plugin logue le
|
|
code HTTP en cas d'échec — un 401 signifie un `CoachAuth.kCoachWebToken`
|
|
périmé).
|
|
|
|
## Séance guidée au poignet (2026-08-03)
|
|
|
|
`CoachWatch/RoutineGuidedView.swift` — bouton **Démarrer** sur chaque bloc :
|
|
un exercice à la fois, décompte en anneau, passage automatique, haptique à
|
|
chaque transition, pause / précédent / suivant.
|
|
|
|
Chaque exercice écoulé est coché via `RoutineStore.toggle`, donc renvoyé à
|
|
l'iPhone puis au serveur : à la fin, le bloc est déjà à jour sur les trois
|
|
surfaces sans un geste de plus.
|
|
|
|
Le fichier est **déjà référencé dans le pbxproj** (target CoachWatch), aucun
|
|
« Add Files » à faire. Backup : `project.pbxproj.bak-guided`.
|
|
|
|
À tester au build : démarrer le bloc 1 sur la montre, laisser tourner deux
|
|
exercices, vérifier que la page `/routine` de l'iPhone se coche toute seule.
|
|
|
|
## Reste à faire (hors périmètre de ce chantier)
|
|
|
|
- Complication watchOS « Routine » : la target `CoachWatchWidgets` n'existe
|
|
toujours pas (cf. `docs/widgets-runbook-mac.md`).
|
|
- Notification de rappel sur la montre si la routine n'est pas faite à 20 h.
|