7.4 KiB
Жесты и режимы очков (design, согласовано 2026-08-22)
Согласовано с пользователем. Реализация — opencode по TASK (см. ниже). Это документ проекта: сначала думаем, потом хуячим, потом тесты, потом ОБЯЗАТЕЛЬНО мануальные тесты на железе.
Ограничения системы (факты)
- Жестов всего шесть: Click, DoubleClick, TripleClick, SlideForward, SlideBackward, LongClick (+ SlideContinuous с delta).
- LongClick НЕ работает — перехвачен системным ассистентом RayNeo. Не рассчитывать, не использовать.
- SlideContinuous существует (SDK:
TempleAction.SlideContinuous(delta: Float, ...)— подтверждено javap) — плавный скролл возможен, delta = дельту движения пальца. Частоту событий и амплитуду дельт проверить на железе. - Экран очков — широкий 1280×480 (640×480 на глаз). Текста влезает мало → скролл ответа обязателен для длинных ответов.
- Оверлей общения затемняет кино (72% чёрного) → режим общения ЯВНЫЙ: пользователь видит, что он в чате, а не в кино. Это позволяет переназначать свайпы в режиме общения без конфликта.
- Нет клавиатуры — только жесты и голос. Выход из режима — только жестом.
- LLM думает 5-15с — нужен индикатор «думаю...», иначе экран замирает.
Общий паттерн жестов (единая семантика через все режимы)
| Жест | Смысл везде |
|---|---|
| TripleClick | вызов локального ассистента (переход в режим общения) |
| DoubleClick | отмена / назад |
| Click | основное действие текущего контекста |
Матрица жестов по состояниям (ЗАКРЫТА)
| Состояние | Click | DoubleClick | TripleClick |
|---|---|---|---|
| Кино | плей/пауза | игнор (назад некуда) | вызов ассистента (пауза + «слушаю...») |
| Прослушивание | отправить фразу | отмена, остаёмся в диалоге | игнор |
| Ответ виден | новая фраза (микрофон открывается) | выход из режима | игнор (уже в режиме) |
Ключевой принцип: клик = «главное действие здесь». В кино — плей/пауза, в диалоге — сказать новую фразу, при прослушивании — отправить. Один жест, контекст решает. Двойной — всегда «не хочу/назад». Тройной — всегда «хочу говорить с ассистентом».
Конфликтов нет: подрежимы различимы по состоянию (listening = микрофон открыт / assistantText непуст = ответ виден).
Решения по деталям
- Отмена диктовки (DoubleClick в прослушивании) — просто отмена, остаёмся в диалоге (назад к «ответу виден», ничего не теряется).
- Фильм после выхода (DoubleClick при ответе) — ВСЕГДА на паузе, независимо от того, был ли он на паузе до входа в режим ассистента.
- Скролл ответа — плавный: SlideContinuous, отслеживать движение пальца (delta), а не факт свайпа с шагом N. Свайпы SlideForward/SlideBackward в режиме общения — тоже скролл (запасной вариант, если SlideContinuous окажется нестабильным на железе).
- Новая фраза в режиме «ответ виден» — Click: микрофон открывается, «слушаю...». Старый ответ с экрана — стереть (история живёт в SQLite на телефоне, не теряется).
- Индикатор «думаю...» — после отправки фразы (между прослушиванием и ответом) показывать «думаю...» вместо замирания на тексте фразы.
Что делать (TASK для opencode)
В app-glasses (MainActivity.kt + оверлей):
- Переразметка жестов по матрице:
- Кино: как сейчас (Click=TOGGLE, TripleClick=вызов, свайпы=±30с, DoubleClick=игнор)
- Прослушивание: как сейчас (Click=отправить, DoubleClick=отмена, TripleClick=игнор)
- Ответ виден (listening=false, assistantText непуст): Click → новая фраза (открыть микрофон, стереть assistantText со старта), DoubleClick → выход из режима (закрыть оверлей, фильм на паузе, assistantText стереть), TripleClick → игнор, свайпы/SlideContinuous → скролл
- Скролл ответа: плавный через SlideContinuous (delta), scrollState для текста ответа; запасной вариант — дискретные свайпы. Ограничить скролл границами текста.
- Индикатор «думаю...»: состояние между отправкой фразы и получением ShowText; показывать в оверлее.
- Выход: DoubleClick при «ответ виден» — закрыть оверлей, фильм остаётся на паузе (не трогать play/pause при выходе, только при входе ставим паузу).
Тесты: юнит-тесты на чистую логику разметки жестов (переходы состояний, скролл-дельта → смещение), в духе GestureCommandsTest. Мануальные тесты — ОБЯЗАТЕЛЬНО на железе (142: очки 7687f645 + телефон AXGL024B05001337): полный цикл кино → тройной тап → фраза → «думаю...» → ответ → скролл → выход → фильм на паузе.
Смежные договорённости (архитектура агента)
Полная архитектура скиллов/тулсетов — в TASK-agent-tools.md. Ключевое для очков: ассистент — локальный, на телефоне; очки — тонкий клиент (микрофон → STT → телефон → LLM → ShowText на очки). Режим общения — поверх любого режима (кино/чат), активируется тройным тапом из любого места.