Capacitor 8 n'auto-découvre pas les plugins in-app Swift (qui ne sont pas
des npm packages). Les plugins définis dans le target App doivent être
enregistrés manuellement via une sous-classe de CAPBridgeViewController
qui override capacitorDidLoad().
Ajouts :
- ios/App/App/MainViewController.swift : sous-classe qui registers
CoachWorkoutKitPlugin() dans capacitorDidLoad()
- Main.storyboard : customClass pointe sur MainViewController (module
'App' target) au lieu de CAPBridgeViewController (module Capacitor)
- project.pbxproj : 4 entrées pour MainViewController.swift (BuildFile,
FileReference, group, Sources phase)
Après rebuild, Capacitor.Plugins.CoachWorkoutKit sera dispo en JS.
L'API WorkoutScheduler.shared.preview(plan) n'existe pas (ou pas avec cette
signature) dans le SDK iOS de l'utilisateur — compile error 'Value of type
WorkoutScheduler has no...'.
On garde uniquement WorkoutScheduler.shared.schedule(plan, at: now), qui
est l'API stable depuis iOS 17.0. Effet : le workout devient immédiatement
disponible dans Apple Watch → Exercice → Workouts personnalisés.
Le 1er schedule déclenche automatiquement la dialog d'autorisation iOS
'Coach Hypnotruck souhaite ajouter des workouts à votre Apple Watch' si pas
encore accordée. Plus besoin du authorizationState query manuel.
Trade-off : pas de sheet de prévisualisation système avant ajout (l'user ne
voit pas la structure dans une UI native avant que le workout soit ajouté).
Mais c'est le bon compromis pour avoir un build qui marche. On pourra
réintroduire preview() plus tard si on bump le deployment target.
Compile errors :
- WorkoutAlertEnumeration n'existe pas → c'est WorkoutAlert (et il faut
passer l'alert via WorkoutStep.alert, pas en param d'IntervalStep)
- IntervalStep init est .init(_ purpose:, step: WorkoutStep) — pas de goal
ni alert direct, faut wrapper dans WorkoutStep d'abord
- WorkoutScheduler.shared.preview(plan) ajouté en iOS 17.4+ → wrap dans
if #available(17.4) avec fallback schedule() pour 17.0-17.3
Ajouts :
- requestAuthorization() avant preview/schedule (idempotent si déjà accordée)
- HeartRateZoneAlert appliqué sur work + rest steps via .alert (style mutable)
Plugin Capacitor Swift in-app (ios/App/App/CoachWorkoutKit.swift) qui utilise
le framework Apple WorkoutKit (iOS 17+ / watchOS 10+) pour construire un
CustomWorkout structuré (warmup + IntervalBlock work/rest répété + cooldown)
et présenter la sheet système iOS qui propose à l'user d'ajouter le workout
à ses workouts personnalisés Apple Watch.
API JS (côté WebView) :
Capacitor.Plugins.CoachWorkoutKit.isAvailable()
Capacitor.Plugins.CoachWorkoutKit.sendInterval({
activity, displayName, warmupMin, work, rest, repeats, cooldownMin
})
Activity supportées : running / cycling / walking / hiking
HR zones (1-5) optionnelles via HeartRateZoneAlert sur work + rest steps.
Workflow attendu user :
1. coach.hypnotruck.ch → /settings ou bouton 'Envoyer Apple Watch' depuis /calendar
2. JS appelle WK.sendInterval(...)
3. Plugin Swift construit CustomWorkout + IntervalBlock + alerts
4. WorkoutScheduler.shared.preview(plan) ouvre la sheet iOS native
5. User tape 'Ajouter aux workouts' → workout dispo dans Apple Watch
→ Exercice → Course → Workouts personnalisés → [displayName]
Build à faire sur le Mac (cap sync ios + Xcode build → install iPhone).
Phase 1 = MVP plugin + bouton test sur /settings de coach.hypnotruck.ch.
Phase 2 = bouton 'Envoyer Apple Watch' sur card du jour /calendar (convertit
la séance prévue en CustomWorkout).
Phase 3 = bibliothèque templates intervalles (10x400m, fartlek, etc.).
Project.pbxproj : ajouté 4 entrées (PBXBuildFile + PBXFileReference + group +
Sources phase) avec IDs D1BD5B1990CF3F2B9C5D000{1,2}.
- package.json : name 'coach-mobile', description mentionne iOS+Android,
scripts 'sync', 'sync:ios', 'sync:android', 'open:android', 'build:android'
- README.md : titre "Coach Hypnotruck — Mobile (iOS + Android)", section
Architecture mentionne Coque Android Capacitor + Health Connect, commande
cap-assets sans --ios pour générer les deux plateformes en une fois
- coach-ios.local.json filename CONSERVÉ pour ne pas casser les references
dans le code Swift natif AppDelegate.swift / CoachAuth.swift
Action user pour finaliser :
1. Renommer le repo Gitea : Settings → Repository name → coach-mobile
2. Local : `mv ~/coach-ios ~/coach-mobile && cd ~/coach-mobile`
3. Update remote : `git remote set-url origin git@gitea:sylvain/coach-mobile.git`
@capacitor/assets v3.0.5 → 87 assets Android générés à partir des sources
1024x1024 (icon) et 2732x2732 (splash) déjà présentes :
- mipmap-{m,h,xh,xxh,xxxh}dpi : ic_launcher.png + _round + _foreground
(foreground/background layers pour adaptive icons Android 8+)
- drawable-{land,port}-{l,m,h,xh,xxh,xxxh}dpi : splash.png
- mipmap-anydpi-v26 : ic_launcher.xml et ic_launcher_round.xml
(XML adaptive icon refs vers les layers PNG)
iOS pbxproj : strip leading zero `0920` → `920` (effet de bord du tool, pas
de comportement Xcode modifié — juste format normalisé).
Reste assets marketing pour Play Console (Feature Graphic 1024x500,
screenshots phone) — à générer au moment du upload, pas dans le repo.
@capgo/capacitor-health plugin (déjà dans package.json) requiert min SDK 26
(Android 8.0+) — Health Connect n'existe pas en deçà. Bump explicite avec
commentaire pour ne pas se faire piéger plus tard si on baisse le min sdk.
Privacy Policy URL pointée vers https://coach.hypnotruck.ch/privacy (route
déjà servie par FastAPI). C'est la page que Health Connect ouvre dans une
WebView quand l'user clique "Politique de confidentialité" dans la dialog
de permissions natives.
iOS déjà 100% configuré côté Health (entitlement + NSHealthShareUsage +
NSHealthUpdateUsage en FR). Rien à toucher.
Génère la structure Capacitor Android (gradle + manifest + activity Java/Kotlin)
avec applicationId 'ch.hypnotruck.coach' (cohérent avec iOS), minSdk 24, target 36.
8 plugins synchronisés au passage (déjà déclarés dans package.json) :
@capacitor/{app,geolocation,haptics,local-notifications,push-notifications,
splash-screen,status-bar} et @capgo/capacitor-health.
Build APK toujours bloqué côté infra (Android SDK non installé sur cette machine,
+ attente validation Play Console pour signing/upload). Mais la structure est
prête : `cap sync` après modification du web puis `./gradlew assembleDebug`
sur une machine avec Android SDK.
Étape suivante : configurer permissions Health Connect dans AndroidManifest +
sync iOS pour cohérence cross-platform.
Évite le redirect 303 du backend /login qui casse WKWebView (WebKitErrorDomain
code 102, frame load interrupted by policy change). Le cookie est posé
directement dans HTTPCookieStorage.shared avec les bons attributs (domain
coach.hypnotruck.ch, path /, secure, expire 1 an).
Token lu depuis CoachAuth.kCoachWebToken défini dans CoachAuth.swift
(gitignored). Template fourni dans CoachAuth.swift.example.
Setup côté Mac mini :
1. cp ios/App/App/CoachAuth.swift.example ios/App/App/CoachAuth.swift
2. Éditer pour mettre la vraie valeur du token
3. Dans Xcode, Right-click App folder → Add Files → sélectionner CoachAuth.swift
WebKit error code 102 (Frame load interrupted by policy change) sur le redirect
303 retourné par /login après pose du cookie. Solution Phase 0 : laisser le
user saisir le token une fois via le formulaire /login standard, le cookie
coach_web_token (1 an, secure, httponly, samesite=lax) doit persister dans
WKWebView pour les lancements suivants.
Si la persistance cookie échoue : inject natif via AppDelegate.swift à venir.
- capacitor.config.ts charge coachWebToken depuis coach-ios.local.json (gitignored)
- server.url devient https://coach.hypnotruck.ch/login?token=... → backend pose le cookie 1 an, redirige vers /
- Au prochain lancement, le cookie tient → /login?token redirige direct vers /
- coach-ios.local.json.example fourni pour setup Mac mini
- Capacitor 8 + plugins natifs (push, local-notif, geoloc, HealthKit Capgo, splash, status bar, haptics)
- Config pointe vers https://coach.hypnotruck.ch (server.url)
- Icône 1024×1024 + splash 2732×2732 depuis icon-512 PWA coach_sportif
- README complet avec procédure build sur Mac mini
- Bundle ID : ch.hypnotruck.coach, App name : Coach Hypnotruck