Files
houseplan-card/docs/specs/203-hide-room-names.md
T
2026-08-19 18:29:28 +03:00

20 KiB
Raw Blame History

Issue #203 — выключение названий скрывает все подписи комнат

  • Дата: 2026-08-19
  • Тип: bug · приоритет P2 · ценность 7/10 · сложность 3/10
  • Issue: #203
  • Ветка: issue/203-hide-room-names

Канонические документы: docs/SCOPE.md, docs/UX-MODES.md, docs/STYLING-HOOKS.md, docs/USER-GUIDE.ru.md, docs/TESTING.md.

1. Сценарий и персона

Администратор дома открывает настройки пространства, выключает «Отображать названия комнат (перетаскиваются)» и сохраняет. Он ожидает чистый View без постоянных подписей, например для маленького экрана, фонового чертежа с уже нанесёнными названиями или плана, где достаточно интерактивных устройств.

Это штатная часть J4/J6: явно выключенный визуальный слой должен исчезнуть на всех пользовательских представлениях одного пространства.

2. Что человек увидит до и после

До: draggable HTML-карточка исчезает вместе с температурой, влажностью, LQI и состоянием света, но на нарисованном плане без фонового изображения возникает другая SVG-подпись. Имя остаётся, перемещается в геометрический центр комнаты и меняет стиль. Компактная карточка пространства повторяет дефект.

После: при выключенной настройке в View, Devices editor и компактной карточке нет постоянной подписи комнаты ни в HTML, ни в SVG. В Plan editor имя по-прежнему временно показывается как редактируемый объект. При повторном включении возвращается прежняя draggable карточка с сохранённой позицией, масштабом, HA Area icon и разрешёнными метриками.

3. Подтверждённая проблема и причина

Persisted значение и основной resolver исправны:

  • spaceDisplayOf() возвращает showNames: false для явного settings.show_names: false;
  • _saveSpaceDialog() записывает show_names: d.showNames для существующего пространства;
  • основной .devlayer перестаёт рендерить _renderRoomLabel(), поэтому HTML-карточка и её .rlmetrics действительно исчезают.

Ошибка находится в двух fallback-ветках. _renderSvgRoomLabels() полного renderer при !space.bg && !disp.showNames создаёт <text class="rlabel">. renderSpaceCard() независимо делает то же через staticSvgLabels. Они инвертируют смысл настройки. Скрытая изометрическая ветка дополнительно форсирует HTML-карточки при iso && !space.bg, даже если showNames === false.

Именно смена HTML-карточки на SVG-текст объясняет все детали репорта: имя остаётся, метрики пропадают, сохранённая layout-позиция не используется, цвет и типографика становятся другими. На пространстве с bg дефект маскируется, потому что SVG-fallback уже запрещён условием space.bg.

4. Scope

  • сделать show_names: false единым запретом постоянных room-labels в полном flat/iso View, Devices editor и компактной карточке пространства;
  • сохранить принудительную видимость редактируемой HTML-подписи в Plan editor;
  • сохранить live-preview значения в открытом диалоге настроек пространства;
  • при show_names: true не менять состав, позицию, масштаб, цвет, метрики, HA Area icon, drag/resize и навигацию комнатной карточки;
  • удалить или обезвредить ошибочные SVG-fallback renderer и актуализировать больше не существующий .rlabel styling-hook;
  • добавить browser regression, mutation gate, визуальное доказательство и пользовательскую/тестовую документацию.

5. Non-scope

  • изменение текста/назначения переключателя или добавление второго режима «статические названия»;
  • скрытие названия комнаты внутри tooltip, диалога настроек, HA Area или accessibility-описания самой комнаты: настройка управляет подписями на плане;
  • удаление либо сброс layout.rl_<roomId>, масштаба подписи или room metrics;
  • изменение show_borders, room fill, Glow, openings, devices и room hover;
  • изменение дефолта show_names для новых/legacy пространств — это отдельная проблема #204;
  • schema/backend/API, migration, импорт/экспорт и Optimize;
  • публичное включение изометрии или изменение её геометрии;
  • редизайн комнатной карточки, Plan gear/handles или compact space card.

6. Контракт поведения

6.1. Матрица видимости

Поверхность show_names: true show_names: false
Full View, flat Одна HTML .roomlabel на именованную комнату Нет HTML/SVG room-label
Full View, hidden iso Та же HTML .roomlabel, спроецированная существующей iso-логикой Нет HTML/SVG room-label
Devices editor Одна HTML .roomlabel Нет HTML/SVG room-label
Plan editor Одна редактируемая HTML .roomlabel Та же editor-only .roomlabel
Compact space card Одна HTML .roomlabel Нет HTML/SVG room-label

Условие !space.bg больше не создаёт альтернативный способ показать имя. Наличие или отсутствие фонового изображения не влияет на матрицу.

6.2. Повторное включение

Выключение не удаляет layout.rl_<roomId> и room settings. После повторного включения карточка возвращается в сохранённую позицию и с сохранёнными k/name_scale/label_scale. Разрешённые label_temp, label_hum, label_lqi и label_light снова отображаются по существующим правилам и данным.

6.3. Plan editor

Plan editor сохраняет исключение _markup: подпись нужна для drag, resize и доступа к редактируемому имени. Это исключение не должно протекать в View после выхода из редактора. Room gear и placeholder безымянной комнаты сохраняются.

6.4. Диалог настроек

При переключении showNames в edit-диалоге _spaceDisplayForRender() сразу проецирует новое значение в затемнённый пользовательский View. Cancel возвращает persisted значение, Save записывает boolean. Результат после повторного открытия совпадает с сохранённым состоянием.

7. Данные, совместимость и styling hooks

Persisted-формат не меняется: settings.show_names уже валидируется и хранит boolean. Миграция не нужна, конфигурация не переписывается при чтении.

div.roomlabel[data-hp="room-label"] остаётся каноническим hook видимой подписи. text.rlabel существовал только в противоречащей настройке fallback- ветке и после исправления не является доступным runtime hook; строка о нём в docs/STYLING-HOOKS.md удаляется или заменяется честным описанием отсутствия подписи. data-hp, data-id и data-area HTML-карточки не меняются.

Downgrade возвращает старый SVG-fallback, но не теряет данные. Пользовательский CSS, намеренно показывавший text.rlabel при выключенных названиях, перестаёт иметь target — это необходимое следствие исправления ложного поведения, а не новая точка расширения.

8. UX, i18n, accessibility и touch

Новых строк и элементов управления нет. Существующий русский и английский текст становится честным. Выключенная подпись не оставляет пустого DOM-узла, focus target или невидимой pointer-зоны. Tooltip комнаты и room hover остаются доступны по геометрии комнаты, поэтому получить сведения по комнате можно.

Touch/keyboard policy и события Plan editor не меняются. При включённых именах существующие drag, resize handles, Area navigation и accessibility-описания сохраняются.

9. Acceptance criteria и доказательства

AC Критерий Обязательное доказательство
AC1 На нарисованном пространстве без bg, при show_names:false, в flat View нет ни .roomlabel, ни .room-svg-labels text, ни [data-hp="room-label"]. Targeted Playwright smoke через реальный space setting.
AC2 AC1 выполняется в компактной карточке пространства. Тот же smoke на houseplan-space-card.
AC3 Hidden iso при show_names:false не форсирует подписи; при true сохраняет существующую projected HTML-карточку. Расширенный isometric contract/live smoke + отдельный iso mutant.
AC4 Plan editor показывает редактируемую подпись при show_names:false; после выхода View снова пуст. Browser mode-transition smoke с DOM assertions.
AC5 При true HTML-карточки, метрики, HA Area icon, сохранённая позиция/scale и текущие события не меняются. Существующие room-card/link/parity smokes + focused regression.
AC6 Toggle в edit-диалоге даёт live-preview, Save переживает повторное открытие, Cancel не пишет config. Расширенный smoke_space_settings.mjs либо отдельный targeted smoke.
AC7 show_borders, fills, Glow, devices, openings и room tooltip не меняются при выключении имён. DOM snapshot/assertions targeted smoke + reviewed golden.
AC8 Документация больше не обещает доступный text.rlabel hook и однозначно описывает переключатель. Diff STYLING-HOOKS, user guide и TESTING.
AC9 Ошибочный fallback доказан исполняемым мутантом. mutation-gate --check, clean green / mutant red.
AC10 Рабочие gates зелёные. typecheck, unit, build и все затронутые targeted smokes.

10. План автотестов

10.1. Unit/source contract

Новая pure-логика не требуется. Существующие unit spaceDisplayOf уже доказывают чтение явного false. Если итоговая реализация вынесет общую функцию матрицы видимости, добавить table-driven unit; иначе не дублировать Lit-template в искусственном source test.

10.2. Browser smoke

Расширить demo/smoke_space_settings.mjs или создать небольшой именной smoke:

  1. взять пространство без plan_url/bg, включить имена и зафиксировать одну HTML-карточку с метрикой и сохранённой layout-позицией;
  2. открыть edit-диалог и выключить имена, проверить live-preview;
  3. Save и повторное открытие подтверждают false и отсутствие любых labels;
  4. перейти в Plan — подпись и editor affordance видимы; вернуться в View — снова скрыты;
  5. повторить ключевую проверку в hidden iso и compact space card;
  6. включить имена обратно и проверить восстановление карточки, позиции/scale и метрики;
  7. отдельно проверить Cancel и отсутствие pageerror/console error.

demo/smoke_styling_hooks.mjs меняет прежнее утверждение «SVG-label существует при false» на честное отсутствие любого label; HTML hook при true остаётся. Смежные smoke_room_cards.mjs, smoke_room_link.mjs, room-label parity и iso smokes прогоняются до code review.

10.3. Golden и mutation gate

Добавить/переиспользовать focused light/dark golden для нарисованного пространства: reviewed baseline при false не содержит имён, при true содержит существующие HTML-карточки. Общий golden:verify и полный smoke идут перед бетой, но затронутые focused кадры обязательны при реализации.

Mutation gate обязан независимо защищать все три места исходного дефекта:

Mutant id Обязательная поломка Guard
hidden-room-names-full-svg-fallback Вернуть SVG-fallback _renderSvgRoomLabels() полного flat renderer при show_names:false. Targeted full-card smoke из AC1 обязан завершиться non-zero.
hidden-room-names-compact-svg-fallback Вернуть staticSvgLabels компактной карточки при show_names:false. Targeted compact-card smoke из AC2 обязан завершиться non-zero.
hidden-room-names-iso-override Вернуть независимый iso && !space.bg override, который форсирует HTML .roomlabel вопреки show_names:false. Isometric contract/live smoke из AC3 обязан завершиться non-zero.

Все три entries регистрируются в scripts/mutation-gate.mjs; каждый якорь встречается ровно один раз. На чистом коде все guards зелёные, на каждом мутанте соответствующий guard красный. Объединять full/compact/iso в один мутант нельзя: иначе исправленная ветка может маскировать непроверенную соседнюю.

11. Риски и меры

Риск Мера
Скрытие протечёт в Plan и лишит пользователя редактируемого имени. Отдельная строка матрицы, AC4 и реальный переход режимов.
Исправится full card, но останется compact или iso override. Независимые AC2/AC3 и mutants по renderer.
Повторное включение сбросит позицию/scale/metrics. Запрет записи layout и round-trip AC5/AC6.
Вместе с label исчезнет tooltip/room pointer geometry. Label DOM меняется отдельно от room shape; AC7.
Удалится документированный styling hook без объяснения. Актуализация STYLING-HOOKS и compatibility note §7.

Performance улучшается либо нейтрален: удаляются DOM/SVG nodes и map по комнатам при выключенном слое, новых проходов/таймеров/network calls нет. Security/privacy boundary не меняется; настройка не становится механизмом сокрытия данных.

12. Rollback

Frontend-изменение откатывается вместе с тестами и документацией одним коммитом. Данные и schema не меняются. Откат возвращает только ошибочный SVG-fallback/iso override и не требует восстановления config или layout.

13. Release-артефакты

  • пользовательские записи в docs/CHANGELOG.md и docs/CHANGELOG.ru.md в implementation-коммите с User-Visible: yes;
  • обновления docs/USER-GUIDE.ru.md, docs/STYLING-HOOKS.md и docs/TESTING.md;
  • targeted full/compact/Plan/iso browser evidence, styling-hook regression и executable mutation gate;
  • focused reviewed light/dark golden и синхронные bundle snapshots;
  • отдельные backend, schema, migration, performance и security artifacts не нужны;
  • полные golden/smoke/performance остаются предрелизным гейтом.

14. Принятые предположения

Принято предположительно, поменять свободно при ревью:

  1. «Скрыть названия» управляет постоянными labels на плане, но не удаляет имя из tooltip/диалогов и не является privacy-функцией.
  2. Plan editor сохраняет текущую принудительную видимость независимо от persisted show_names, потому что там имя является редактируемым объектом.
  3. Hidden iso обязан соблюдать тот же user setting, несмотря на прежний технический override iso && !space.bg.
  4. Канонический styling hook видимой подписи — существующий HTML div.roomlabel; отдельный статический режим и новый hook не добавляются.
  5. Если удаление мёртвого .rlabel CSS увеличит визуальный diff только за счёт отсутствующих nodes, это входит в задачу; прочая типографика не меняется.