74 lines
5.1 KiB
Markdown
74 lines
5.1 KiB
Markdown
---
|
|
issueRef: "#176"
|
|
version: 5
|
|
updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"}
|
|
updatedAt: 1785321673401
|
|
---
|
|
|
|
## #176 — Cadrage UX (2026-07-29)
|
|
|
|
Statut : **cadrage exploitable, nouveau lot**, app téléphone, `lib/presentation/workout_execution_screen.dart`, widget `_TimedStepBody` (L2907-2963), rendu dans `_CurrentStepPane` (branche générale, L2811-2838, `Expanded(child: step.type == time ? _TimedStepBody(...) : ...)`).
|
|
|
|
### Constat, vérifié en lecture directe
|
|
`_TimedStepBody` est placé dans un `Expanded` par son parent (toute la hauteur disponible lui est allouée), mais **à l'intérieur** de ce widget rien n'exploite cet espace :
|
|
|
|
```dart
|
|
Column( // pas de mainAxisAlignment.center, pas de Expanded interne, pas de FittedBox
|
|
children: [
|
|
Text('Objectif : Xs'),
|
|
Center(child: Text(remainingLabel, style: displayMedium)), // taille fixe, non scalable
|
|
if (!running) [...'Chrono prêt'..., FilledButton 'Lancer'],
|
|
],
|
|
)
|
|
```
|
|
|
|
Le `Text(remainingLabel)` a une taille de police fixe (`displayMedium`), la `Column` s'aligne en haut (comportement par défaut) : tout l'espace du `Expanded` non consommé par le contenu à taille naturelle reste vide en bas. Résultat : le chrono reste petit que le bouton `Lancer` soit visible ou non, et une fois le chrono démarré (`running == true`, le bloc `Lancer`/`Chrono prêt` disparaît), l'espace libéré n'est récupéré par personne — comportement exactement décrit par le ticket.
|
|
|
|
À comparer avec `_RepsWithStopwatchScoreStepBody` (L2965+) et le bloc `Expanded → LayoutBuilder → FittedBox(scaleDown) → SizedBox(hauteur de référence fixe)` déjà utilisé en L2740-2772 pour dimensionner un contenu à une zone variable : ce pattern existe déjà dans ce fichier, `_TimedStepBody` ne le reprend pas.
|
|
|
|
### Comportement attendu
|
|
Le chrono (et le bouton `Lancer` quand il est visible) doivent occuper **tout** l'espace vertical disponible dans le `Expanded` parent, dans les deux états :
|
|
|
|
- **Avant démarrage** (`!running`) : chrono + `Chrono prêt` (si prêt) + bouton `Lancer`, empilés et **centrés**, mis à l'échelle ensemble pour remplir la zone disponible (largeur et hauteur).
|
|
- **Après démarrage** (`running`) : le bloc `Chrono prêt`/`Lancer` disparaît (inchangé), et le chrono seul se remet à l'échelle pour **regrandir** et occuper tout l'espace libéré — pas de saut brutal de layout, juste une nouvelle mise à l'échelle du même mécanisme.
|
|
|
|
### Implémentation recommandée
|
|
Réutiliser le mécanisme `FittedBox(fit: BoxFit.contain)` déjà présent dans ce fichier (au lieu de `BoxFit.scaleDown` utilisé ailleurs, qui ne permet que de rétrécir — ici on veut aussi agrandir) :
|
|
|
|
```dart
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
Text('Objectif : ${_formatShortSeconds(step.defaultTargetValue)}'), // inchangé, taille fixe
|
|
const SizedBox(height: 4),
|
|
Expanded( // NOUVEAU : réclame tout l'espace restant
|
|
child: LayoutBuilder(
|
|
builder: (context, c) => FittedBox(
|
|
fit: BoxFit.contain, // scale up ET down, contrairement à scaleDown
|
|
child: SizedBox(
|
|
width: c.maxWidth,
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text(remainingLabel, style: /* displayMedium, référence */),
|
|
if (!running) ...[
|
|
const SizedBox(height: 8),
|
|
if (readyToStart) Text('Chrono prêt', ...),
|
|
const SizedBox(height: 4),
|
|
FilledButton.icon(onPressed: onStartTimer, icon: Icons.play_arrow, label: 'Lancer'),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
```
|
|
|
|
- Le `FittedBox(BoxFit.contain)` prend le bloc de référence (chrono seul, ou chrono + libellé + bouton selon l'état) et le met à l'échelle pour remplir exactement la largeur ET la hauteur du `Expanded` — c'est ce même mécanisme qui fait automatiquement grandir le chrono quand le bouton disparaît : le bloc de référence devient plus petit (moins d'enfants), donc le facteur d'échelle appliqué par `FittedBox` augmente pour combler le même espace disponible.
|
|
- Le bouton `Lancer` grandit avec le reste (proportionnellement) tant qu'il est visible — cohérent avec la demande explicite du ticket (« chrono + bouton commencer prennent la place disponible »).
|
|
- Point de vigilance dev : choisir une taille de référence (police du `Text(remainingLabel)`, hauteur du bouton) qui donne un **rendu correct au repos** (échelle ≈ 1) sur la taille d'écran de référence du projet, quitte à ajuster ces valeurs empiriquement — le `FittedBox` absorbe l'écart, mais des proportions de référence déséquilibrées donneraient un mauvais rendu même mis à l'échelle. Ne pas plafonner l'échelle maximale (pas de `scaleDown`) : la demande explicite est que ça puisse grandir au-delà de la taille actuelle.
|
|
- Ne touche pas au cas `hasTimedWithManualScore` (L2725-2809, `_TimedStepWithManualScoreBody`) : ce lot ne concerne que le chrono seul, sans score manuel, branche générale de `_CurrentStepPane`.
|