Files
view-mate/docs/gestures-and-modes.md

7.4 KiB
Raw Permalink Blame History

Жесты и режимы очков (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 непуст = ответ виден).

Решения по деталям

  1. Отмена диктовки (DoubleClick в прослушивании) — просто отмена, остаёмся в диалоге (назад к «ответу виден», ничего не теряется).
  2. Фильм после выхода (DoubleClick при ответе) — ВСЕГДА на паузе, независимо от того, был ли он на паузе до входа в режим ассистента.
  3. Скролл ответа — плавный: SlideContinuous, отслеживать движение пальца (delta), а не факт свайпа с шагом N. Свайпы SlideForward/SlideBackward в режиме общения — тоже скролл (запасной вариант, если SlideContinuous окажется нестабильным на железе).
  4. Новая фраза в режиме «ответ виден» — Click: микрофон открывается, «слушаю...». Старый ответ с экрана — стереть (история живёт в SQLite на телефоне, не теряется).
  5. Индикатор «думаю...» — после отправки фразы (между прослушиванием и ответом) показывать «думаю...» вместо замирания на тексте фразы.

Что делать (TASK для opencode)

В app-glasses (MainActivity.kt + оверлей):

  1. Переразметка жестов по матрице:
    • Кино: как сейчас (Click=TOGGLE, TripleClick=вызов, свайпы=±30с, DoubleClick=игнор)
    • Прослушивание: как сейчас (Click=отправить, DoubleClick=отмена, TripleClick=игнор)
    • Ответ виден (listening=false, assistantText непуст): Click → новая фраза (открыть микрофон, стереть assistantText со старта), DoubleClick → выход из режима (закрыть оверлей, фильм на паузе, assistantText стереть), TripleClick → игнор, свайпы/SlideContinuous → скролл
  2. Скролл ответа: плавный через SlideContinuous (delta), scrollState для текста ответа; запасной вариант — дискретные свайпы. Ограничить скролл границами текста.
  3. Индикатор «думаю...»: состояние между отправкой фразы и получением ShowText; показывать в оверлее.
  4. Выход: DoubleClick при «ответ виден» — закрыть оверлей, фильм остаётся на паузе (не трогать play/pause при выходе, только при входе ставим паузу).

Тесты: юнит-тесты на чистую логику разметки жестов (переходы состояний, скролл-дельта → смещение), в духе GestureCommandsTest. Мануальные тесты — ОБЯЗАТЕЛЬНО на железе (142: очки 7687f645 + телефон AXGL024B05001337): полный цикл кино → тройной тап → фраза → «думаю...» → ответ → скролл → выход → фильм на паузе.

Смежные договорённости (архитектура агента)

Полная архитектура скиллов/тулсетов — в TASK-agent-tools.md. Ключевое для очков: ассистент — локальный, на телефоне; очки — тонкий клиент (микрофон → STT → телефон → LLM → ShowText на очки). Режим общения — поверх любого режима (кино/чат), активируется тройным тапом из любого места.