Pont WebView→App Group→WidgetKit : - CoachWidgetSnapshot.swift : modèle partagé App↔extension (App Group group.ch.hypnotruck.coach) - CoachWidgetBridge.swift : plugin Capacitor setSnapshot/clear + WidgetCenter.reloadAllTimelines - CoachWidgets.swift : 2 widgets (TimelineProvider + vues SwiftUI, small/medium) - bundle + enregistrement plugin + entitlements App Group (App + CoachLiveActivity) ⚠️ Reste câblage Mac (App Group portail + capability + Target Membership) : docs/widgets-runbook-mac.md. Hook web côté coach_sportif. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.2 KiB
Runbook Mac — widgets natifs iPhone (Séance du jour + Score de forme)
Pour le Claude « Cowork » (Mac) / Sylvain. Le code Swift + entitlements + le
hook web sont écrits côté coach_sportif/coach-ios par le Claude dev (Linux).
Il reste les étapes Mac/portail Apple ci-dessous — elles ne peuvent pas se
faire depuis Linux (provisioning + ajout de fichiers aux cibles dans Xcode).
Ce qui est déjà fait (committé)
coach-ios (natif) :
ios/App/App/CoachWidgetSnapshot.swift— modèle partagé App ↔ extension (App Group).ios/App/App/CoachWidgetBridge.swift— plugin CapacitorsetSnapshot/clear+WidgetCenter.reloadAllTimelines().ios/App/CoachLiveActivity/CoachWidgets.swift— 2 widgets (TimelineProvider + vues SwiftUI).ios/App/CoachLiveActivity/CoachLiveActivityBundle.swift— widgets ajoutés auWidgetBundle.ios/App/App/MainViewController.swift— plugin enregistré danscapacitorDidLoad().ios/App/App/App.entitlements— App Groupgroup.ch.hypnotruck.coachajouté.ios/App/CoachLiveActivity/CoachLiveActivity.entitlements— créé avec l'App Group.
coach_sportif (web, déjà en prod via webhook) :
web/static/widget-bridge.js+ include dans_layout.html— poussetoday(depuis/api/today) +forme(recovery_score). No-op hors app native.web/templates/home.html—data-form-scoreexposé sur le hero.
Étapes Mac à faire (dans l'ordre)
1. App Group sur le portail Apple
developer.apple.com → Certificates, IDs & Profiles → Identifiers → App Groups →
créer group.ch.hypnotruck.coach (si pas déjà créé).
2. Activer la capability sur les 2 cibles (Xcode)
⚠️ Quitter puis git pull d'abord (règle COWORK : jamais de pull Xcode ouvert).
Ouvrir ios/App/App.xcworkspace, puis pour App ET CoachLiveActivity :
- onglet Signing & Capabilities → + Capability → App Groups →
cocher
group.ch.hypnotruck.coach. - Vérifier que
CODE_SIGN_ENTITLEMENTSpointe bien sur le bon.entitlements(App →App/App.entitlements; CoachLiveActivity →CoachLiveActivity/CoachLiveActivity.entitlements, à régler si Xcode ne l'a pas pris).
3. Ajouter les nouveaux fichiers aux bonnes cibles (Target Membership)
Les fichiers existent sur disque mais doivent être référencés par le projet :
CoachWidgetSnapshot.swift→ cocher App ET CoachLiveActivity (fichier partagé).CoachWidgetBridge.swift→ cible App uniquement.CoachWidgets.swift→ cible CoachLiveActivity uniquement.CoachLiveActivity.entitlements→ pas une source (référencé par le build setting).
Méthode : clic droit sur le dossier de la cible → Add Files to "App"… (décocher Copy items, cocher la bonne cible), ou sélectionner le fichier → inspecteur de droite → Target Membership.
4. Build + test device
- Clean Build Folder (
Cmd+Shift+K) → Run sur l'iPhone. - Ouvrir l'app (charge la prod) une fois pour que
widget-bridge.jspousse le snapshot. - Écran d'accueil → ajouter les widgets Coach : « Séance du jour » (small/medium) et « Score de forme » (small).
- Vérifier qu'ils affichent les vraies données du jour. Tap → ouvre
/calendarresp./forme.
5. Debug si le widget reste vide
- Vérifier le snapshot écrit : Safari → Développement → iPhone → console →
await Capacitor.Plugins.CoachWidgetBridge.setSnapshot({today:{sport:"running",title:"Test",done:false}})puis long-press l'écran d'accueil → le widget doit se mettre à jour. - Si rien : l'App Group n'est pas partagé (étape 2) →
UserDefaults(suiteName:)renvoie nil.
Modèle de données (contrat web ↔ widget)
{
"today": { "sport": "running", "title": "Sortie longue", "subtitle": "90 min · Z2", "done": false },
"forme": { "score": 72, "label": "Prêt" } // null si pas de score
}
sport ∈ running | cycling | strength | mobility | hiking | walking | rest.
Suite possible (backlog)
- Complication Watch (nouvelle target widget watchOS — à créer dans Xcode).
- Lockscreen widgets (
accessoryRectangular/accessoryCircular) — ajouter les familles. - Background refresh (App Background Tasks) si on veut un widget à jour sans ouvrir l'app.