Доки: жесты и режимы общения с ассистентом (design) + TASK
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
# Задача: жесты и режимы общения с ассистентом на очках (design в docs/gestures-and-modes.md)
|
||||
|
||||
Прочитай `docs/gestures-and-modes.md` — там согласованная с пользователем матрица жестов и все решения. Реализуй в `app-glasses`. Механику тулсетов/ассистента (app-phone) НЕ трогать.
|
||||
|
||||
## Что сделать
|
||||
|
||||
### 1. Переразметка жестов по матрице (MainActivity.kt, collectTempleActions)
|
||||
|
||||
| Состояние | Click | DoubleClick | TripleClick | Свайпы/SlideContinuous |
|
||||
|---|---|---|---|---|
|
||||
| Кино (listening=false, assistantText пуст) | TOGGLE (как сейчас) | игнор | вызов ассистента (как сейчас) | ±30с (как сейчас) |
|
||||
| Прослушивание (listening=true) | отправить (как сейчас) | отмена, остаёмся в диалоге (как сейчас) | игнор | игнор |
|
||||
| Ответ виден (listening=false, assistantText непуст) | **новая фраза**: стереть assistantText, открыть микрофон, listening=true | **выход из режима**: закрыть оверлей, стереть assistantText, фильм на паузе (НЕ трогать play/pause — пауза уже стоит с момента входа) | игнор | **скролл ответа** (плавный SlideContinuous, запасной — дискретные свайпы) |
|
||||
|
||||
Важно: состояние «ответ виден» определяется `!listening && assistantText.isNotBlank()`.
|
||||
|
||||
### 2. Скролл ответа (плавный)
|
||||
|
||||
- SlideContinuous: накапливать `delta` (float) → смещать scrollState текста ответа. Направление: SlideForward = вниз по тексту (к концу), SlideBackward = вверх (к началу) — уточнить знак дельты на железе.
|
||||
- Ограничить скролл границами текста (0..maxScroll).
|
||||
- Запасной вариант: SlideForward/SlideBackward — скролл на страницу (например, ±200px или высоту видимой области), если SlideContinuous окажется шумным.
|
||||
- Текст ответа в оверлее должен быть в scrollable-контейнере (Column + verticalScroll(rememberScrollState()) или LazyColumn — на твой выбор, но скролл обязателен).
|
||||
|
||||
### 3. Индикатор «думаю...»
|
||||
|
||||
- Состояние thinking: true с момента отправки фразы (Click при прослушивании / SttPhrase ушёл) до прихода ShowText.
|
||||
- В оверлее: если thinking и assistantText пуст — показывать «думаю...» (вместо «слушаю...» после того как фраза отправлена).
|
||||
- Как определить: пока listening=true — «слушаю...»/текст фразы; когда listening стал false, а ShowText ещё не пришёл — «думаю...».
|
||||
|
||||
### 4. Выход из режима
|
||||
|
||||
DoubleClick при «ответ виден»: закрыть оверлей (listening=false, sttText="", assistantText=""), НЕ трогать movieController (фильм остаётся на паузе — он уже на паузе с момента входа в режим).
|
||||
|
||||
## Ограничения
|
||||
|
||||
- Код только Kotlin
|
||||
- НЕ трогать app-phone (ассистент, тулсеты, скиллы)
|
||||
- НЕ трогать MovieController/playback-логику
|
||||
- Тесты: юнит-тесты на чистую логику разметки жестов (новое состояние «ответ виден», переходы, скролл-дельта → смещение) — в духе GestureCommandsTest. Если логика в MainActivity (не чистая) — вынеси чистую часть (решение по жесту из состояния) в отдельный файл/функцию для тестируемости.
|
||||
- Сборка: `./gradlew :app-glasses:assembleDebug` — зелёная; `./gradlew :app-glasses:testDebugUnitTest` — зелёный (старые + новые)
|
||||
- НЕ коммитить
|
||||
|
||||
## Проверка
|
||||
|
||||
1. `./gradlew :app-glasses:testDebugUnitTest` — зелёные
|
||||
2. `./gradlew :app-glasses:assembleDebug` — собирается
|
||||
3. Опиши в ответе: какие файлы создал/изменил, как определил состояние «ответ виден», как работает скролл (SlideContinuous или запасной), что осталось проверить на железе.
|
||||
Reference in New Issue
Block a user