6.4 KiB
6.4 KiB
Спецификация 05: интеграция UI — экран «Тренировка» и «Настройки»
Источники: Ф-1.1 (активация кнопкой, экран активной тренировки), Ф-1.6 (правка ≤ 2 касаний), Ф-3.1 (статус-строка), решения гейта 1.3 №1/№2, ui-ux разд. 3 (текст дублирует цвет, нижняя треть, ≥ 48 dp). Единицы 6–7. Расширение экранов m10.
1. Экран «Тренировка» — кнопка микрофона и прослушивание
- в TopAppBar рядом с Edit — кнопка Mic (
Icons.Filled.Mic/MicOff), цель ≥ 48 dp; состояние дублируется текстом в теле экрана: «Слушаю…» (индикатор — пульсирующая точка) / «Голос выключен» (🛡 цвет → текст); - первое включение (последовательность, без блокировки
интерфейса):
- разрешение
RECORD_AUDIO(runtime-запрос): отказ → голос выключен, сообщение «Без разрешения микрофона голос недоступен» (кнопка остаётся доступной для повторного запроса); - модель не загружена (
ModelStore.isDownloaded()=false) → диалог «Модель распознавания не загружена. Скачать сейчас? (~45 МБ)» → да → загрузка (прогресс %, ошибки текстом, кнопка «Отмена»), по успеху — старт прослушивания; нет → голос выключен; - готово →
SttEngine.startListening(спец 02);
- разрешение
- повторное нажатие — выключение (
stopListening); выход с экрана тренировки — остановка прослушивания (DisposableEffect); прослушивание работает только при активной тренировке (Ф-1.1) — заглушка «Нет активной тренировки» кнопки не активирует;
2. Обратная связь на экране
- строка последней команды (текст, не только цвет 🛡): «Принято: подход 60 на 10» / «Принято: вес 62,5» / «Принято: отдых 90» / «Принято: РПЭ 7» / «Не распознано» / «Число вне диапазона» / «Сначала выберите упражнение» (эффекты Message исполнителя);
- строка появляется при первой команде, остаётся до следующей.
3. Текущее упражнение (решение гейта 1.3 №2)
- строки блока «План сессии» — clickable: тап выбирает «текущее упражнение» (подсветка + подпись «текущее»);
- умолчание — первый пункт плана сессии дня; план пуст — используется последний выбранный в форме подхода (selected exercise m10 сохраняется); совсем нет — ничего не выбрано, голосовые Approach/Weight отклоняются (no_exercise, спец 03 §5);
- голос пишет подходы в текущее упражнение (
logSet(source= "voice")); ручная форма m10 (Edit) остаётся без изменений (правка ≤ 2 касаний, Ф-1.6); - эффект
WorkingWeight(w)— обновляет вес формы m10 и показ плана (следующие «Подход» озвучивают уже новый вес, если атлет говорит «подход на R» без веса — НЕ входит в грамматику v1: вес в команде обязателен, Ф-1.2).
4. Таймер отдыха
- эффект
RestStarted(s)→restLeft = s(переиспользование RestCard/RestTimer m10; фазы цвет+текст без изменений); - ручной старт кнопкой «Отдых» остаётся (умолчание
Rest.DefaultSec).
5. «Настройки» — блок «Распознавание речи» (расширение m10)
Voice.ModelUrl— текстовое поле, умолчаниеhttps://alphacephei.com/vosk/models/vosk-model-small-ru-0.22.zip; валидация — абсолютный https:// URL (кнопка «Сохранить» неактивна при ошибке — паттерн BaseUrl m10);- статус модели: «Не загружена» / «Загружена (N МБ)»;
- кнопка «Загрузить» →
ModelStore.downloadс прогрессом (повтор при ошибке; замена каталога при смене URL); - кнопка «Проверить TTS» → «Русский голос доступен» /
«TTS недоступен — только сигналы и текст» (
ttsAvailable(), спец 04); - AppSettings m09/m10 расширяется полем
voiceModelUrl(errata m10 по образцуhrMaxBpm; SettingsRepository — DataStore).
6. Разрешения и манифест
AndroidManifest.xml:<uses-permission android:name="android.permission.RECORD_AUDIO"/>— runtime (dangerous), запрос только из кнопки микрофона (не при старте приложения);- интернет для загрузки модели — существующее разрешение m09 (SyncWorker); распознавание сеть не использует (🛡 офлайн).
7. Тесты
- unit (pure JVM): ViewModel-логика эффектов (WorkingWeight →
состояние веса, RestStarted → секунды, Message → строка
статуса) — где выделено в чистые функции; валидация
Voice.ModelUrl(паттерн SettingsValidator m10); - ручной смок — критерии 2/3 module_reqs (полный голосовой сценарий + синхронизация command_log).