12 KiB
Требования к модулю: 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→ syncprofile; - экран «Библиотека» (Ф-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) — расширениеAppSettingsm09 (+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. Инварианты (🛡 — нарушать запрещено)
- UI не пишет в LocalDb — только вызовы
WorkoutCore(единственный писатель, инвариант m09); ViewModel хранит только UI-состояние. - Офлайн-first — каждый экран работает без сети (КУ-3); сеть — только SyncQueue по действиям пользователя (кнопка/фоновое расписание).
- Тайны — API-ключ не отображается открыто и не логируется (З-6); в UI — замаскированное поле.
- Допуск — блокировки по
Safety.*снимаются только явными действиями с логированием (startAnyway/ отмена) — Ф-13.2/13.5. - Версии программ на телефоне неизменяемы и только читаются (Ф-10.1); активная версия фиксируется у тренировки при старте (Ф-10.3 — уже в m09).
- Удаление упражнения — только логическое (
is_active=false, Ф-4.2); история читаема.
4. Критерии приёмки модуля
assembleDebugсобирается, APK запускается (вручную владельцем); unit-тесты зелёные (ProgramView/зоны/валидация настроек).- Ручной смок сценария на устройстве/эмуляторе владельца: первый запуск (настройки) → «Сегодня» (дневник) → допуск (все 4 исхода по порогам) → тренировка (2–3 подхода с меткой плана, таймер отдыха) → закончить → история (карточка с план/факт) → программы (план на сегодня) → профиль → библиотека (добавить/исключить).
- Смок синхронизации на живом (docker) сервере: действия сценария
п. 2 уходят пакетами
/api/v1/sync, подтверждённые GUID удаляются из очереди (счётчик «Сегодня» → 0), строки видны вsrc.*(банее-статусы соответствуют). - Экраны соответствуют UI/UX-стандарту (разд. 2): тёмная тема, пикеры/сегменты, дублирование цвета текстом — проверка владельцем при приёмке.