Files
GameTime/.ideai/memory/gametime-ux-watch-companion.md
Blomios 917777e18b chore(wip): consolidation intermédiaire multi-tickets (sprints Statistiques, UI, Bug resolution, Serveur-client)
Regroupe l'état de travail en cours réalisé dans un même worktree sur
plusieurs tickets/sprints (#85, #136, #145, #155-160, #162-164),
mélangeant des tickets QA et inProgress. Ne constitue pas une feature
terminée : commit de sauvegarde avant triage/split par ticket en
branches feature/* dédiées. Exclut les dossiers d'environnement de
build locaux et le heap dump parasite (.gitignore mis à jour).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 16:48:54 +02:00

16 KiB

name, description, metadata
name description metadata
gametime-ux-watch-companion memory note gametime-ux-watch-companion
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 :

Aucune séance en cours

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

CTA optionnel si le système le permet :

[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 :
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 :

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 :

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 :

[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 :

REPOS
Après série 2 / 5

00:37
Repos en cours

Exercice suivant
Fentes sautées

[Pause]

Actions secondaires sur l'écran Actions :

[Passer le repos]

Si le repos est en pause :

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 :

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 :
[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 :

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 :

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 :

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 :

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.