---
name: gametime-ux-watch-companion
description: memory note gametime-ux-watch-companion
metadata:
  type: project
---
# GameTime — UX interface montre synchronisée (ticket #91, UX 2026-07-25)

Conception UX d'une app compagnon Wear OS synchronisée avec l'app téléphone pour piloter une séance en cours depuis le poignet.

Références à respecter :
- `gametime-session-execution-timer-refactor`
- `gametime-ux-step-chaining-override`
- `gametime-architecture-step-chaining-override`
- `gametime-ux-score-chrono`
- `gametime-online-layer-philosophy`

## Décision produit structurante

La montre est une **surface compagnon de pilotage**, pas une deuxième app autonome de séance.

- **Téléphone = source de vérité de l'exécution**.
- **Montre = télécommande + miroir d'état**.
- Toute action lancée sur la montre est une **intention utilisateur** envoyée au téléphone, puis confirmée par le retour d'état.
- La montre ne doit jamais exposer un modèle d'exécution différent de celui du téléphone.

Justification :
- la logique de séance, des chronos, des overrides d'étapes et du repos existe déjà côté téléphone ;
- cela évite les divergences de calcul entre deux appareils ;
- cela rend la cohérence UX compréhensible : un seul état réel, visible sur deux surfaces.

## Principe de surface

Sur montre, la hiérarchie doit être radicale :

1. **où j'en suis** : série, exercice, étape/passage si nécessaire ;
2. **ce qui se passe maintenant** : chrono dominant ou état dominant ;
3. **l'action unique la plus probable** ;
4. **les actions de contournement** dans une surface secondaire.

La montre ne doit pas tenter de reproduire toute l'interface téléphone. Pas de médias, pas d'édition, pas de paramètres, pas de détails historiques.

## Surfaces montre

## 1. État sans séance active

Écran affiché si aucune séance n'est en cours côté téléphone.

Contenu :

```text
Aucune séance en cours

Lance une séance sur le téléphone.
```

CTA optionnel si le système le permet :

```text
[Actualiser]
```

Règles :
- aucun contrôle d'exécution affiché ;
- pas de faux bouton `Démarrer` ;
- si la montre n'est pas connectée au téléphone, le message devient :

```text
Téléphone indisponible

Rouvre GameTime sur le téléphone.
```

## 2. Écran principal `Séance active`

Écran par défaut dès qu'une séance en cours existe. C'est la surface centrale de la feature.

Structure recommandée sur écran rond :

```text
SÉRIE 2 / 5
Pompes tempo
Passage 1 / 3 · Étape 2 / 4

00:18
Chrono étape

Série 01:42 · Score 00:51

[Pause]
```

### Hiérarchie d'information

L'ordre visuel doit être fixe :

1. `SÉRIE X / Y` toujours en haut.
2. Nom de l'exercice sur 1 à 2 lignes max.
3. Ligne contextuelle compacte :
   - `Passage A / B` seulement si l'exercice en a ;
   - `Étape C / D` seulement si l'exercice en a ;
   - si les deux existent, les concaténer sur une seule ligne.
4. **Chrono dominant** en très grand.
5. Libellé du chrono dominant ou de l'état.
6. Ligne compacte des autres chronos simultanés, si utile.
7. Bouton principal pleine largeur.

### Règle du chrono dominant

La montre ne doit afficher qu'un seul chrono en grand. Ordre de priorité UX :

1. `Repos` si un repos est en cours.
2. `Étape` si une étape temps est active ou en état `Chrono suivant prêt`.
3. `Score chrono` s'il est actif et qu'aucune étape temps n'est prioritaire.
4. `Temps de série` si actif.
5. Sinon, l'état dominant remplace le chrono.

Les autres chronos actifs restent en secondaire sur une seule ligne compacte, par exemple :

```text
Série 03:12 · Score 01:08
```

But : rester lisible pendant l'effort tout en respectant le modèle multi-chronos existant.

### Bouton principal contextuel

Le bas de l'écran porte **une seule action primaire** dont le libellé dépend de l'état :

- `Démarrer l'exercice`
- `Pause`
- `Reprendre`
- `Démarrer le chrono`
- `Passer le repos`

Cette action unique est le raccourci du cas d'usage le plus probable à cet instant.

## 3. Écran `Actions`

Surface secondaire accessible depuis `Séance active` par swipe horizontal ou tap sur un affordance discret `Actions`.

Cette surface contient les actions moins fréquentes, sous forme de gros boutons verticaux scrollables.

Ordre des actions :

```text
[Passer l'étape]        // seulement si applicable
[Passer le passage]     // seulement si applicable
[Terminer la série]
[Passer la série]
[Passer le repos]       // seulement pendant le repos
```

Règles :
- n'afficher que les actions réellement applicables à l'état courant ;
- ne pas afficher d'action impossible ou déjà satisfaite ;
- pendant un chrono en cours, `Passer la série` doit demander une confirmation ;
- pendant un repos, `Terminer la série` disparaît car la série est déjà terminée.

### Confirmations montre

Deux confirmations seulement, pour éviter les erreurs grossières pendant l'effort :

1. `Passer la série ?`
   `Le chrono en cours sera ignoré.`
   `[Annuler] [Passer]`

2. `Passer le passage ?`
   `L'étape en cours sera ignorée.`
   `[Annuler] [Passer]`

`Passer l'étape` peut être immédiat : coût faible, fréquence plus élevée.

## 4. Écran `Repos`

Quand le repos est en cours, l'écran principal change de nature et devient un écran repos, pas un simple bandeau.

Structure :

```text
REPOS
Après série 2 / 5

00:37
Repos en cours

Exercice suivant
Fentes sautées

[Pause]
```

Actions secondaires sur l'écran `Actions` :

```text
[Passer le repos]
```

Si le repos est en pause :

```text
REPOS
00:37
Repos en pause

[Reprendre]
```

## États à couvrir

## 1. Séance pas encore lancée / début de série

Cas : la série existe, mais aucun chrono qui démarre au début de série n'a encore été lancé.

Affichage :

```text
SÉRIE 1 / 4
Burpees
Étape 1 / 3

00:20
Prêt à démarrer

[Démarrer l'exercice]
```

Règle obligatoire :
- si l'exercice est sous chrono **et** que la première étape est une étape `Temps`, le bouton reste **unique** :

```text
[Démarrer l'exercice]
```

Cette action démarre à la fois :
- le timer de série si `timeEnabled` ;
- le chrono de la première étape ;
- le score chrono si `scoreInputMode == stopwatch`.

La montre ne doit jamais afficher deux boutons concurrents du type `Démarrer l'exercice` et `Démarrer l'étape`.

## 2. Chrono running

Cas nominal pendant l'effort.

Affichage :
- chrono dominant animé visuellement ;
- libellé `En cours` ou libellé du chrono (`Chrono étape`, `Score chrono`, `Temps de série`) ;
- bouton principal `Pause`.

Effet du bouton :
- met la séance en pause ;
- la pause suspend tous les chronos running, y compris le repos.

## 3. Séance en pause

Affichage :

```text
SÉRIE 2 / 5
Pompes tempo

00:18
Séance en pause

[Reprendre]
```

Règles :
- l'état doit être explicite ;
- aucun chrono ne doit sembler continuer ;
- si l'utilisateur reprend depuis le téléphone, la montre revient automatiquement à l'état running.

## 4. `Chrono suivant prêt`

Cas imposé par `autoStartNextTimedStep = false` après une étape temps suivie d'une autre étape temps.

Affichage :

```text
SÉRIE 2 / 5
Pompes tempo
Passage 1 / 3 · Étape 3 / 4

00:15
Chrono suivant prêt

[Démarrer le chrono]
```

Règles :
- ne pas réutiliser `Démarrer l'exercice` ;
- ne pas auto-démarrer ;
- conserver l'état après pause/reprise ;
- l'écran doit rendre évident qu'on est déjà avancé dans la séquence, mais en attente d'un lancement manuel.

## 5. Entre les séries

Deux cas distincts :

1. repos configuré et lancé ;
2. pas de repos en cours, prochaine série prête.

Si pas de repos :

```text
SÉRIE 3 / 5
Pompes tempo

Prêt pour la série suivante

[Démarrer l'exercice]
```

L'utilisateur comprend qu'il redémarre une nouvelle série, pas la séance depuis zéro.

## 6. Repos running / repos en pause

Voir surface `Repos`.

Le repos doit être traité comme un état de premier rang, car c'est souvent le seul moment où l'utilisateur regarde la montre entre deux séries.

## 7. Pas de séance active

Voir surface `État sans séance active`.

## 8. Téléphone temporairement indisponible

Cas spécifique à la cohabitation téléphone/montre.

La montre peut afficher le dernier état connu, mais il doit être clairement marqué comme potentiellement obsolète :

```text
Connexion perdue
Dernier état reçu il y a quelques secondes

[Réessayer]
```

Règles :
- désactiver les actions de pilotage tant que la connexion n'est pas rétablie ;
- ne pas laisser croire qu'un tap local a réellement modifié la séance sans confirmation ;
- au retour de connexion, la montre remplace entièrement son affichage par l'état confirmé du téléphone.

## Mapping des contrôles

## Gestes retenus

- **Tap** sur le bouton principal : action primaire contextuelle.
- **Swipe horizontal** : bascule entre `Séance active` et `Actions`.
- **Scroll vertical / couronne** : parcours des actions si la liste dépasse.
- **Bouton système / retour système** : navigation système uniquement.

Décision UX : ne pas attribuer de commande métier obligatoire à un bouton physique matériel. Les montres Wear OS n'offrent pas toutes la même ergonomie matérielle.

## Mapping détaillé

### Sur `Séance active`

- `Démarrer l'exercice`
  - déclenche tous les chronos de début de série applicables ;
  - couvre explicitement le cas exercice chrono + première étape chrono.

- `Pause`
  - met la séance en pause ;
  - suspend série, étape, score chrono, repos.

- `Reprendre`
  - reprend exactement l'état suspendu.

- `Démarrer le chrono`
  - démarre l'étape temps prête après un enchaînement manuel.

- `Passer le repos`
  - raccourci contextuel possible si UX test montre que c'est plus utile que `Pause` pendant le repos ;
  - sinon garder `Pause` en primaire et déplacer `Passer le repos` dans `Actions`.

Décision recommandée pour v1 :
- pendant le repos, **bouton principal = `Pause`**, pour garder la cohérence avec le reste de la séance ;
- `Passer le repos` reste en action secondaire.

### Sur `Actions`

- `Passer l'étape`
  - disponible seulement si une étape courante existe.

- `Passer le passage`
  - disponible seulement si l'exercice a plusieurs passages/séquences et si le passage courant n'est pas déjà terminé.

- `Terminer la série`
  - finalise la série et arrête/enregistre les chronos actifs selon les règles existantes.

- `Passer la série`
  - ignore la série courante avec confirmation si un chrono ou une séquence est en cours.

- `Passer le repos`
  - disponible seulement si repos en cours.

## Cohérence téléphone ↔ montre

## Source de vérité

Décision UX ferme :

- l'état autoritaire de séance vit sur le téléphone ;
- la montre affiche une **projection compacte** de cet état ;
- la montre n'invente jamais un état final seule.

## Modèle d'interaction

Cycle UX attendu pour une action montre :

1. l'utilisateur tape sur la montre ;
2. la montre passe brièvement le bouton en état `Envoi...` ;
3. le téléphone applique la commande ;
4. la montre reçoit l'état confirmé et remplace l'affichage.

Si l'état confirmé diffère de l'intention initiale parce que le téléphone a déjà changé entre-temps, c'est **le dernier état confirmé** qui gagne visuellement.

Exemple :
- l'utilisateur tape `Pause` sur la montre ;
- presque au même moment, il a déjà repris sur le téléphone ;
- la montre ne doit pas essayer de "corriger" localement ; elle se recale sur le dernier snapshot confirmé.

## Règle de conflit UX

En cas d'actions quasi simultanées téléphone/montre :

- le système applique un ordre réel côté source de vérité ;
- la montre n'affiche jamais un dialogue de conflit ;
- elle se contente d'afficher le résultat réel le plus récent.

Autrement dit : **pas de résolution de conflit visible par l'utilisateur**, seulement un réalignement rapide de l'UI.

## Règle de latence

La montre doit distinguer trois cas UX :

1. **latence courte**
   - simple état `Envoi...` sur le bouton.

2. **latence perceptible**
   - texte discret `En attente du téléphone`.

3. **absence de réponse**
   - état `Connexion perdue` et actions désactivées.

Les seuils temporels exacts sont laissés à Architect, mais la surface doit prévoir ces trois états distincts.

## Signaux sonores et haptiques

## Principe

Pour respecter #92, la montre doit privilégier **l'haptique**. L'audio montre n'est pas requis pour le MVP.

Décisions UX :
- par défaut, **pas de son obligatoire côté montre** ;
- retour principal = vibration ;
- si un son est ajouté plus tard, il doit être bref, non intrusif, et ne jamais prendre le focus audio au détriment de la musique de fond.

## Patterns recommandés

- démarrage/pause/reprise confirmé : **impulsion courte** ;
- fin d'un chrono ou fin de repos : **double impulsion** ;
- état `Chrono suivant prêt` : **double impulsion** au moment où l'état est atteint, puis silence ;
- perte de connexion après action utilisateur : **impulsion lourde unique** optionnelle.

Règles :
- pas de bip de décompte 3-2-1 imposé sur la montre au MVP ;
- pas de répétition haptique continue ;
- éviter la duplication agressive téléphone + montre sur le même événement.

## Exigences de donnée pour Architect

La montre a besoin d'un view model compact, orienté exécution, pas de tout le snapshot séance brut.

Minimum UX requis :

- présence ou absence d'une séance active ;
- statut de connexion téléphone↔montre ;
- `seriesIndex`, `seriesTotal` ;
- `exerciseName` ;
- contexte séquence :
  - `sequenceIndex?`, `sequenceTotal?`
  - `stepIndex?`, `stepTotal?`
  - `stepName?`
- type et valeur du **chrono dominant** ;
- liste compacte des autres chronos actifs visibles ;
- état global :
  - `ready`
  - `running`
  - `paused`
  - `nextTimerReady`
  - `restRunning`
  - `restPaused`
  - `noActiveSession`
  - `phoneUnavailable`
- libellé de l'action primaire autorisée ;
- liste des actions secondaires autorisées ;
- indicateur `commandPending`.

## Hypothèses techniques laissées à Architect

Points explicitement non tranchés par UX, à valider techniquement :

1. faisabilité et coût d'une app Wear OS Flutter dédiée ou module compagnon séparé ;
2. capacité à exposer côté téléphone un flux d'état d'exécution suffisamment compact et fréquent pour la montre ;
3. stratégie de mise à jour du chrono affiché sur la montre :
   - push fréquent depuis le téléphone ;
   - ou interpolation locale à partir d'horodatages autoritaires ;
4. transport exact téléphone↔montre et garanties d'acknowledgement pour les commandes ;
5. comportement si le téléphone est verrouillé, en arrière-plan, ou si le process principal est suspendu ;
6. possibilité de déclencher des vibrations montre sans prise de focus audio ;
7. capacité à rendre idempotentes les commandes utilisateur (`pause`, `resume`, `skipStep`, `finishSet`, etc.) ;
8. découpage des use cases côté téléphone pour exposer uniquement les commandes compatibles montre ;
9. gestion exacte des timeouts et des seuils de latence visibles dans l'UI ;
10. politique de duplication ou non des signaux entre téléphone et montre sur un même événement.

## Synthèse décisionnelle pour la suite

La montre doit rester une surface extrêmement simple :

- un écran principal `Séance active` ;
- un écran secondaire `Actions` ;
- un écran dédié `Repos` quand le repos est l'état dominant ;
- des états explicites pour pause, `Chrono suivant prêt`, absence de séance et perte de connexion ;
- une seule action primaire contextuelle à la fois ;
- téléphone autoritaire, montre suiveuse interactive.

Cette forme couvre l'objectif utilisateur réel : piloter entièrement la séance sans sortir le téléphone, tout en conservant la logique d'exécution déjà stabilisée dans GameTime.
