baldav/docs/plans/2026-09-26-map-follow-toggle.md
4aiman d6fe47a924 Recording map: follow toggle to free-pan while riding
New ⊕ button on the recording screen toggles map auto-follow. When off,
the map stays put so you can look around when unsure where you are (off
the track, or the track leads where there is no road); new GPS points no
longer recentre it. Tapping it back on recentres on the current position
and resumes following. Default on per screen entry (not persisted).

Guards followMode around panTo/setView in onPoint/onBatchUpdate/
onStateChange. Independent of the compass freeze/rotate controls.
2026-09-26 23:44:18 +03:00

7.2 KiB
Raw Blame History

План: кнопка тоггла "следование карты за позицией" на экране записи

Context (зачем)

Во время записи карта на экране трекинга постоянно снэпится (panTo) на текущую GPS-позицию при каждой новой точке. Кейс пользователя: отклонился от трека или трек ведёт туда, где дороги нет, надо осмотреться по карте вокруг - но карта тут же прыгает обратно на позицию, подвигать её невозможно. Нужна кнопка-тумблер: нажал - карта перестаёт следовать за позицией (можно свободно двигать/смотреть), нажал снова - карта центрируется на текущей позиции и следование возобновляется.

Решения по UX (согласованы с пользователем):

  • Кнопка - плитка 32x32 в общем правом ряду кнопок карты, с символом (не словом), активное состояние подсвечивается (как freeze/roads). Активна = следование включено.
  • Только кнопка-тумблер. Драг карты пальцем следование НЕ выключает (строго как в запросе).
  • Повторный тап (включение следования) сразу центрирует карту на текущей позиции.
  • Следование по умолчанию включено при каждом заходе на экран (в localStorage не храним).

Где сейчас следование (frontend/js/main.js, функция renderRecordingInline)

Автоследование = центрирование вида карты на текущей точке. Происходит в:

  • GPS.recording.onPoint, ~4840: map.panTo(ll) - основное следование при записи.
  • GPS.recording.onPoint состояние waiting_gps, ~4857: map.setView([p.lat,p.lon],15).
  • GPS.recording.onStateChange "ready", ~4814: map.setView([p.lat,p.lon],16) - разовый locate.
  • GPS.recording.onBatchUpdate, ~5005: map.panTo(last) - следование при пакетном апдейте.

Маркер позиции (updateMe/refreshMe) вид карты НЕ трогает - при выключенном следовании точка продолжит обновляться на своём месте, просто карта не будет прыгать. Компас/поворот (compassFrozen, applyBearing) ортогональны следованию - panTo на bearing не влияет.

Фикс (frontend/js/main.js, только renderRecordingInline)

  1. Флаг: рядом с compassFrozen/rotOffset (~4470-4477) добавить let followMode = true;.
  2. Кнопка: по образцу freezeBtn/roadsBtn (~4624-4676) создать followBtn (class="rec-map-btn rec-follow-btn", символ-цель, title="Следить за позицией"), добавить в btnWrap, сразу выставить followBtn.classList.add("active") (followMode=true). onclick:
    • followMode = !followMode;
    • followBtn.classList.toggle("active", followMode);
    • при включении - центрировать на текущей точке: взять последнюю точку GPS.recording.points (как в onBatchUpdate: сортировка по ts, последняя) и map.panTo.
  3. Загардить все 4 места следования условием if (followMode):
    • ~4840 map.panTo(ll) -> if (followMode) map.panTo(ll);
    • ~4857 waiting_gps map.setView(...) -> обернуть в if (followMode) (return оставить).
    • ~4814 "ready" map.setView(...) -> обернуть в if (followMode).
    • ~5005 map.panTo(last) -> if (followMode) map.panTo(last);

CSS (frontend/css/styles.css)

После .rec-dark-toggle { right:8px; bottom:238px; } (~1248) добавить позицию для новой кнопки в следующем свободном слоте стека: .rec-follow-btn { right: 8px; bottom: 276px; }. Базовый вид и .active уже есть у .rec-map-btn / .rec-map-btn.active - переиспользуем.

Символ кнопки

Плитка-цель, читается как "центрировать на мне": glyph круг-с-точкой/крест-в-круге (например "⊕" плюс-в-круге или "◎" bullseye) - выбрать широко отрисовываемый. Смысл несёт title (текст). Активная подсветка = следование включено.

Регрессии (проверить рядом)

  • Freeze-кнопка компаса (compassFrozen) и поворот карты - не задеты (следование = только центр вида, поворот = bearing). Убедиться, что обе кнопки работают независимо.
  • Маркер позиции updateMe при выключенном следовании продолжает двигаться (карта стоит).
  • Второй, отдельный экран setupLiveUpdates (мини-карта gpsMap, ~5030, свой panTo 5039/5055) НЕ трогаем - это превью в списке, у него нет ряда кнопок. Пользователь просил "экран трекинга" = renderRecordingInline.

Верификация

  • Десктоп (Xvfb :99, DISPLAY=:99 ./build.sh): открыть экран записи, начать запись (или подсадить точки), проверить:
    1. следование по умолчанию включено, кнопка подсвечена, карта идёт за точкой;
    2. тап -> подсветка гаснет, карту можно свободно двигать, новые точки её не возвращают;
    3. тап -> карта центрируется на текущей позиции, подсветка загорается, следование снова идёт. Скрин каждого состояния.
  • Сборка APK + телефон (по явной просьбе): в реальной записи проехать/постоять, отжать кнопку, подвигать карту, вернуть кнопкой. Коммит ДО теста на телефоне, доработки - отдельным коммитом.
  • README/PROJECT_MAP + лог сессии обновить вместе с коммитом.

Не в этой задаче

Авто-выключение следования при драге карты (пользователь выбрал "только кнопка"). Хранение состояния следования между сессиями (по умолчанию всегда включено).