VEU.WathBody/1-docs/4-modules/m10-phone-ui/module_reqs.md

12 KiB
Raw Permalink Blame History

Требования к модулю: m10-phone-ui

Модуль — TrainingUi телефона Phone.WatchBody (архитектура разд. 1.2): Jetpack Compose + Material 3 поверх ядра m09 (WorkoutCore, LocalDb, SyncQueue, ApiClient, SettingsRepository). Голосовой ввод — m11 (кнопка микрофона — заглушка ручного ввода), канал часов — m12 (пульс/связь — прочерки). Самодостаточная копия требований (d-dev-6). Источники: Ф-3, Ф-4, Ф-5, Ф-6, Ф-10 (просмотр), Ф-11.1–11.3, Ф-13.1–13.2/13.5, Ф-14.2 (manual), tech-req 4.1/6, ui-ux-recommendations разд. 3/5.

1. Назначение и границы

В границах модуля:

  • Compose-каркас: MainActivity, тёмная тема Material 3, нижняя навигация 5 вкладок — Сегодня / Тренировка / История / Программы / Профиль; экраны «Библиотека» и «Настройки» — переходами из «Сегодня»/«Профиля» (иконки в appbar);
  • экран «Сегодня» (Ф-13.1): ввод дневника за 2–3 касания — АД (сист./диаст.), вес, пульс покоя, самочувствие 1–5 (сегмент); показ записи дня; кнопка «Начать тренировку» → поток допуска; счётчик очереди sync;
  • поток «Допуск» (Ф-13.2, модальный экран перед стартом силовой): подтягивает АД из сегодняшнего дневника, ввод пульса сидя вручную; AdmissionChecker (m09) → исходы: ALLOW («Начать»), CARDIO_ONLY (силовые заблокированы — сообщение, прогулка), CANCEL (предложение прогулки, кнопка «Отменить» 🛡 логируется), POSTPONE (перенос; старт — явное «Всё равно начать» → startAnyway 🛡 лог); выбор session_kind при старте (сегмент: обычная/возврат/делоад/ тест, умолчание normal — Ф-14.5);
  • экран «Тренировка» (Ф-3): статус-строка (связь с часами — серый прочерк до m12; сеть онлайн/офлайн), пульс «—» (канал — m12), блок упражнения (текущее из плана сессии дня + рабочий вес), форма подхода: пикер веса с шагом 2,5 кг (умолчание — последний вес упражнения), пикер повторов, RPE 1–10 сегмент (Ф-13.3), боль в колене 0–10 сегмент — только для группы «ноги» (Ф-13.3), метка «по плану/отклонение» (считает WorkoutCore); таймер отдыха (обратный отсчёт Rest.DefaultSec, фон красный/жёлтый (последние 10 с)/зелёный + текстовая подпись состояния); кнопки: «Отдых» (старт таймера), микрофон (заглушка — ручной ввод подхода, m11 заменит), «Закончить», «Сбросить» (отмена с подтверждением — статус cancelled, Ф-3.5); ≤ 4 активных элемента одновременно (Ф-3.6);
  • экран «История» (Ф-5): список finished/cancelled (дата, длительность, число подходов; средний пульс — если есть), карточка тренировки: подходы (упражнение, вес × повторения, источник «голос/часы/правка» — в m10 «правка», метка плана, RPE), отчёт план/факт по тренировке (доля подходов «по плану» — Ф-11.3, локально по in_plan);
  • экран «Программы» (Ф-10/Ф-11): активная версия (недели → сессии → упражнения → план подходов вес × повторы, target RPE/ отдых — если заданы), план на сегодня (сессия дня недели); список локально известных версий; 🛡 версии только читаются — активация/применение rules-draft в v1 — консоль владельца (m08; решение гейта 1.3);
  • экран «Профиль» (Ф-6): пол, год рождения, вес, макс. пульс (Hr.MaxBpm вручную или расчёт Танаки 208 − 0,7 × возраст); зоны 50/70/85 % (показ; на часы — m12); сохранение → saveProfile → sync profile;
  • экран «Библиотека» (Ф-4): список упражнений (название, группа, базовое/изоляция, активные/исключённые), добавить, переименовать, исключить (is_active=false 🛡 логическое, Ф-4.2); выбор упражнения при вводе подхода — из плана сессии + библиотека;
  • экран «Настройки» (tech-req 4.1): Server.BaseUrl (валидация — абсолютный https:// URL, иначе «Сохранить» неактивна), Server.ApiKey (поле-пароль, 🛡 не отображается в открытом виде и не логируется), Sync.WifiOnly, Hr.MaxBpm (120–240/пусто), Rest.DefaultSec (30–600), Safety.* (BpCancel*, BpCardio*, RestingHrSitting, HrStrengthMax 100–180) — расширение AppSettings m09 (+ hrMaxBpm, hrStrengthMax); кнопка «Синхронизировать сейчас» (+結果-баннер); первый запуск — экран настройки подключения показывается до остальных вкладок;
  • баннеры синхронизации (Ф-7.3/7.5): тихий статус — «в очереди N записей», «Синхронизация временно недоступна» (сбой сети/ ретрай), «Данные успешно синхронизированы» (первая успешная), ошибки авторизации/конфликта из флагов SyncWorker (401 — «ключ неверен», 409 — «конфликт версии»); состояние — WorkInfo unique-work «sync» + SyncDao.count();
  • сервисы UI: ProgramView — разбор body активной версии (чистая функция поверх PlanMatch: сессия дня → список упражнений с сетами); ZoneCalculator (Танака/ручной, зоны 50/70/85); расширение AppSettings/SettingsRepository; расписание sync — UI вызывает SyncWorker.schedule после действий WorkoutCore и по кнопке (WorkoutCore ядро остаётся без Android-контекста);
  • unit-тесты (pure JVM): ProgramView (сессия дня, пустой/ битый body), ZoneCalculator, валидация настроек (URL/диапазоны).

Вне границ модуля: STT/TTS и голосовые команды (m11 — кнопка микрофона остаётся заглушкой ручного ввода), пульс/связь с часами и предупреждение HrStrengthMax во время тренировки (m12 — канал; настройка вводится в m10), редактор программ и создание версий author=user (решение гейта 1.3 — v1 просмотр; создание — консоль), применение rules-draft подтверждением атлета (Ф-12.3 — в v1 консоль владельца; эндпоинт активации для атлета — кандидат v2), ответ атлета на авто-break (Ф-14.2 — серверного пути записи ответа нет, кандидат v2), домашний поддерживающий комплекс (Ф-14.6, v2), восстановление пульса пропущенного периода (m12), админ-функции.

2. Решения интерфейса (tech-req 6, ui-ux разд. 3/5)

  • Тёмная тема по умолчанию, Material 3; шрифт ≥ 16 pt, контраст WCAG AA, цели касания ≥ 48 dp;
  • ключевые действия — нижняя треть экрана (одна рука);
  • числовой ввод — пикеры (вес шаг 2,5 кг; повторы шаг 1), не клавиатура; RPE/самочувствие/боль — сегмент-контролы, не слайдеры;
  • цветовые сигналы дублируются текстом/иконкой (таймер отдыха, статусы допуска, баннеры);
  • предупреждения — спокойные формулировки («Пульс выше порога. Отдохните или завершите»), без тревожной лексики;
  • уведомления только значимые (SUS ≥ 80 — порог релиза; приёмка вручную владельцем, эмулятора в среде нет).

3. Инварианты (🛡 — нарушать запрещено)

  1. UI не пишет в LocalDb — только вызовы WorkoutCore (единственный писатель, инвариант m09); ViewModel хранит только UI-состояние.
  2. Офлайн-first — каждый экран работает без сети (КУ-3); сеть — только SyncQueue по действиям пользователя (кнопка/фоновое расписание).
  3. Тайны — API-ключ не отображается открыто и не логируется (З-6); в UI — замаскированное поле.
  4. Допуск — блокировки по Safety.* снимаются только явными действиями с логированием (startAnyway / отмена) — Ф-13.2/13.5.
  5. Версии программ на телефоне неизменяемы и только читаются (Ф-10.1); активная версия фиксируется у тренировки при старте (Ф-10.3 — уже в m09).
  6. Удаление упражнения — только логическое (is_active=false, Ф-4.2); история читаема.

4. Критерии приёмки модуля

  1. assembleDebug собирается, APK запускается (вручную владельцем); unit-тесты зелёные (ProgramView/зоны/валидация настроек).
  2. Ручной смок сценария на устройстве/эмуляторе владельца: первый запуск (настройки) → «Сегодня» (дневник) → допуск (все 4 исхода по порогам) → тренировка (2–3 подхода с меткой плана, таймер отдыха) → закончить → история (карточка с план/факт) → программы (план на сегодня) → профиль → библиотека (добавить/исключить).
  3. Смок синхронизации на живом (docker) сервере: действия сценария п. 2 уходят пакетами /api/v1/sync, подтверждённые GUID удаляются из очереди (счётчик «Сегодня» → 0), строки видны в src.* (банее-статусы соответствуют).
  4. Экраны соответствуют UI/UX-стандарту (разд. 2): тёмная тема, пикеры/сегменты, дублирование цвета текстом — проверка владельцем при приёмке.