# Требования к модулю: 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): тёмная тема, пикеры/сегменты, дублирование цвета текстом — проверка владельцем при приёмке.