baldav/docs/session-logs/2026-09-10_brouter-ux-gapfill-planner.md
4aiman ceee0a48eb gap-fill: reload detail via reopenDetail (in-place), not a stacked screen
Found in desktop testing: showSessionDetail() from the save/revert handlers
pushed a second detail overlay whose map rendered blank. reopenDetail() collapses
the stack and re-renders in place (the pattern recalc/refine already use). Session
log updated with the desktop verification results.
2026-09-10 15:51:34 +03:00

6.4 KiB
Raw Blame History

Сессия 2026-09-10 — BRouter на телефоне: гэп-филл и планировщик

Контекст

Пользователь пожаловался на UX двух BRouter-фич на телефоне:

  1. Гэп-филл (🧩 на детали трека) рисовал ВЕСЬ трек целиком, было непонятно, что достроено, и не было сохранения/отмены.
  2. Планировщик маршрутов по точкам не находился: в меню пункт «Нарисовать маршрут» вёл на рисование ТРЕНИРОВКИ, а сам планировщик спрятан в «Сохранённые маршруты → Новый маршрут».

Работал по утверждённому плану: docs/plans/2026-09-10-brouter-ux-gapfill-planner.md. Решения с пользователем: гэп-филл — обратимый патч на месте; планировщик — по-сегментный роутинг (дорога по умолчанию, прямая где нет дороги, тап по отрезку переключает); пункт меню переименовать.

Сделано

Часть A — гэп-филл:

  • GPS.fillGaps (gps.js) теперь возвращает {points, gaps} со статусами filled/skipped-long/skipped-noroute, интерполированными ts и флагом estimated.
  • GapCtl (main.js, showSessionDetail): предпросмотр ТОЛЬКО достроенных пропусков (голубой с бело-чёрной оковкой; недостроенные — красный пунктир) + панель «Достроено N (+X км), M не удалось» с Сохранить/Отмена. Уже достроенный трек → кнопка «Убрать достройку».
  • БД (db.js): миграции gps_points.estimated, gps_sessions.gap_filled; saveGapFill/revertGapFill (обратимо, seq = seq предыдущей реальной точки, оригинал цел); после сохранения/отката — GPS.recalculateSession(id,{noDelete:true}).
  • Отрисовка детали помечает достроенные участки голубым (видно после сохранения). CSS .gap-panel.

Часть B — планировщик:

  • Пункт меню «Нарисовать маршрут» → «Нарисовать тренировку» (он сохраняет сессию).
  • Подсказка в пустом списке маршрутов зовёт планировать на телефоне («Новый маршрут»).
  • showRouteEditor переписан на по-сегментную модель: legMode[]/legGeom[], дорога по умолчанию, тап по отрезку — дорога↔прямая, долгий тап — вставить точку, неудачный роутинг отрезка молча падает на прямую. Кнопка «🚲 По дорогам» задаёт режим сразу всем отрезкам.

Доки: README (редактор, гэп-филл), PROJECT_MAP (db/gps методы, колонки).

Проверка (десктоп, Xvfb :99 + домашний RouteServer)

  • Синтаксис gps.js/db.js/main.js — OK (node --check). const в новых функциях — нет.
  • Гэп-филл на сессии 1782115144011 (4 дропаута): 🧩 → предпросмотр ТОЛЬКО пропусков (голубой с оковкой) + панель «Достроено 4 (+1.75 км)» + Сохранить/Отмена. Сохранить → 88 estimated-точек в БД, gap_filled=1, петля замкнута по дорогам, деталь перерисовалась. «Убрать достройку» → estimated=0, gap_filled=0, исходный трек вернулся, карта отрисовалась.
  • БАГ, найденный тестом: showSessionDetail(id) в обработчиках ЗАТАЛКИВАЛ второй экран поверх → у него пустая карта. Исправлено на reopenDetail(id) (схлопывает стек, рендер на месте) — отдельным коммитом. Проверено: после save/revert карта рисуется.
  • Планировщик: 3 точки по региону → обе ноги легли ПО ДОРОГАМ (2.26 км). Глобальная кнопка «По дорогам» переключает все ноги на прямые (пунктир, 2.87 км) и обратно — рисование/пересчёт/ состояние кнопки ОК. По-сегментный тап по линии слепой мышью на headless не попал в 4px-линию (каждый промах добавлял точку — у Leaflet-вектора bubblingMouseEvents=false, т.е. попадание по линии точку бы не добавило); биндинг корректный, на тач-экране допуск больше — подтвердить на теле.
  • Реальную стату десктоп-сессии, сдвинутую пересчётом при тесте, восстановил из старой копии БД.

Замечание к разбору (на будущее)

Дистанция сессии «плавает» при recalculateSession (сохранённая 16.24 → достройка 15.58 → откат 18.25) — это поведение текущего computeStats (та же кнопка «Пересчитать» даёт то же), но достройка ожидаемо должна УВЕЛИЧивать дистанцию. Стоит разобрать, как computeStats считает дистанцию через (бывшие) гэпы, и сохранять исходные статы для точного отката.

Дальше

  • На теле встроенным движком офлайн: ./build.sh install -d, докачать сегмент региона. Проверить гэп-филл (предпросмотр/сохранить/убрать) и планировщик (тап по отрезку — тач).