v1.60.0: harden background editing and device state

This commit is contained in:
Matysh
2026-08-07 13:02:46 +03:00
parent 29fb9deb43
commit 3028122016
47 changed files with 2566 additions and 674 deletions
+6 -3
View File
@@ -130,9 +130,12 @@ references and duplicates by name|area. Manual files: transactional HTTP upload
`removed:true` is a binding tombstone, not a renderable marker. It claims an
HA binding against automatic discovery while intentionally exposing that same
binding to the Add picker. Every plan-level resolver excludes its entity or
all entities of its device. Re-adding replaces the tombstone; virtual markers
need no tombstone because they have no discovery source.
binding to the Add picker. A device tombstone excludes all data of that device;
an entity tombstone excludes the standalone entity binding but does not mutate
the same entity out of a still-live parent device. Runtime-filtered references
such as `controls` remain persisted and become active again after re-add.
Re-adding replaces the tombstone; virtual markers need no tombstone because
they have no discovery source.
## Server-side configuration (current shape, v1.51+)
+1 -1
View File
@@ -1,6 +1,6 @@
# Plan image backdrop
Status: current in v1.60.0-beta.1. The complete Background editor contract is in
Status: current in v1.60.0. The complete Background editor contract is in
`DECOR-EDITOR.md`.
## Placement model
+38 -1
View File
@@ -1,6 +1,29 @@
# Changelog
## v1.60.0-beta.1 — 2026-08-07
## v1.60.0 — 2026-08-07
- **Audit hardening.** Deleting one virtual marker no longer removes its
neighbours; real `v_*` ids remain positionable; deletion tombstones are
hidden for old clients and binding-scoped for entity members of live HA
devices. Runtime-filtered controls are no longer destructively saved. Trail
deletion is transactional. Optimisation clamps migrated physical styles,
validates `cell_cm`, preserves invalid legacy transforms for manual repair
and reports model-version bookkeeping honestly. Flat shapes are rejected,
furniture selectors initialise reliably, rotated resize keeps its fixed
corner, mode switches cancel live transforms, and the demo bundle is rebuilt
from the same source as production. English device names containing
`thermometer` now resolve as temperature sensors instead of matching the
broader meter rule.
- Auto icons now update immediately after rebinding and can be explicitly
pinned; imperial stroke-field bounds use inches; decor magnet geometry is
memoised; Undo and Redo share the same live-gesture boundary.
- A marker can no longer list its own bound entity (or an entity of its bound
device) as an external light control. Legacy self-controls are ignored immediately;
marker Save removes them, and plan optimisation also cleans a directly bound
entity self-reference. The explicit `is_light` switch
remains the only way to classify that bound relay as a light source. Active
fans/hoods still use the yellow working-state plate without entering Glow,
Light fill or room light statistics.
- **The Background editor now has one coherent transform and style system.**
Every decor kind can be selected, moved, resized proportionally (Shift for
@@ -42,6 +65,20 @@
a model exception. Mixed media entities fade only when none of them is
currently available and powered.
- **Returning to a long-suspended View is stable.** In normal View (not kiosk),
transient zero/partial ResizeObserver boxes no longer overwrite the saved
viewport. After a genuinely long background sleep the plan is revealed only
after the stage size is measurable and quiet, then zoom and centre are
applied in one frame. Critical wall fill/stroke attributes also live directly
on the SVG paths, so a warm Lovelace re-mount cannot show the browser's black
default paint while component styles are being restored. Editors, kiosk and
quick tab switches keep their existing immediate behaviour.
- **Device-info actions stay inside narrow dialogs.** The Edit, Open in HA and
Close actions now wrap as complete buttons when the small HA dialog cannot
fit one row; reduced mobile padding preserves useful width. The leading Edit
action can no longer be pushed beyond the left edge of the modal.
## v1.59.2 — 2026-08-07
- **A11Y-02: one accessible dialog shell.** Every House Plan modal now uses
+39 -1
View File
@@ -6,7 +6,30 @@
> **Правило проекта:** оба файла пополняются в одном коммите с самим
> изменением — как и остальная документация (см. docs/STATUS.md).
## v1.60.0-beta.1 — 2026-08-07
## v1.60.0 — 2026-08-07
- **Исправления по аудиту.** Удаление одного виртуального маркера больше не
удаляет соседние; реальные id вида `v_*` можно перемещать; tombstone скрыт
даже для старых клиентов и действует на привязку, а не вырезает entity из
живого родительского HA-устройства. Временно неактивные controls больше не
стираются при обычном сохранении. Удаление trail стало транзакционным.
Оптимизация ограничивает мигрируемые физические размеры, валидирует
`cell_cm`, не выбрасывает некорректный legacy transform и честно отделяет
bump версии модели от миграции. Нулевые фигуры отбрасываются, список мебели
выбирает сохранённый символ, resize повернутого объекта сохраняет опорный
угол, а смена режима отменяет незавершённый transform.
Английские имена устройств со словом `thermometer` теперь распознаются как
датчики температуры, а не попадают под более общее правило счётчиков.
- Автоиконка обновляется сразу после смены привязки и может быть явно
закреплена; границы толщины в imperial-режиме показываются в дюймах;
геометрия магнита кешируется; Undo и Redo одинаково работают с живым жестом.
- Маркер больше не может записать собственную entity или сущность привязанного
устройства в список других управляемых источников света. Старая самоссылка сразу
игнорируется; сохранение маркера удаляет её, а оптимизация планов также чистит
прямую самоссылку `entity:*`;
считать само реле источником света можно только явным флагом. Включённая
вытяжка/вентилятор по-прежнему получает жёлтую подложку работающего устройства,
но не участвует в Glow, заливке «Свет» и статистике освещения комнаты.
- **Редактор подложки получил единую систему стилей и трансформаций.** Любой
объект декора можно выбрать, переместить, пропорционально масштабировать
@@ -50,6 +73,21 @@
конкретной модели. Составной медиамаркер бледнеет, только когда среди его
сущностей нет доступной и включённой.
- **Возврат к давно свёрнутому Просмотру больше не дёргает план.** В обычном
Просмотре (не киоск) нулевые и промежуточные размеры `ResizeObserver` больше
не перезаписывают сохранённый viewport. После действительно долгого сна
вкладки план открывается, когда размер сцены уже измерен и успокоился, а
масштаб и центр применяются одним кадром. Критические параметры заливки и
контура толстых стен теперь также заданы прямо на SVG-путях: при тёплом
пересоздании Lovelace браузер не успевает показать стандартную чёрную
заливку до восстановления стилей компонента. Редакторы, киоск и быстрые
переключения вкладок работают по-прежнему без задержки.
- **Действия карточки устройства не выходят за границы узкого диалога.**
Кнопки «Редактировать», «Открыть в HA» и «Закрыть» теперь переносятся только
целиком, если в малом диалоге HA не хватает одной строки; на телефоне также
уменьшены боковые отступы. Первая кнопка больше не уезжает за левый край.
## v1.59.2 — 2026-08-07
- **A11Y-02: единая доступная оболочка диалогов.** Все модальные окна House Plan
+13 -8
View File
@@ -1,6 +1,6 @@
# Background editor: current contract
Status: implemented in v1.60.0-beta.1. This document is the source of
Status: implemented in v1.60.0. This document is the source of
truth for the decorative layer. `BACKDROP.md`, `LIVE-TEXT.md` and
`FURNITURE.md` describe the specialised parts.
@@ -12,7 +12,7 @@ device state or Home Assistant actions.
| Invariant | Contract |
|---|---|
| Coordinates | Every committed position and box dimension is quantised to the space grid. Proportional resize uses a common scale increment so both axes stay on-grid; `Shift` never disables the grid. |
| Coordinates | Axis-aligned positions and every box dimension are quantised to the space grid. A rotated resize keeps its opposite world-space corner fixed and quantises dimensions; its derived unrotated storage origin is not post-snapped, because that would translate the entire object. `Shift` never disables dimension snapping. |
| Physical values | Stroke and text sizes are stored in centimetres; the UI shows cm/in for small values and m/ft for object dimensions. |
| Undo | Decor and backdrop use the same named 50-command stack as plan geometry. |
| Cancel | `Esc` restores the state at the start of an active drag/draw/resize/rotate gesture. A completed gesture is reverted with Undo. |
@@ -33,7 +33,7 @@ device state or Home Assistant actions.
| Oval | Drag its bounding box; `Shift` makes a circle | `R` for a circle, `Rx × Ry` for an oval | bounding size, angle, contour and optional fill |
| Text | Click to open the text form | the saved label is selected immediately | content, HA variables, colour/opacity, physical size and angle |
| Furniture | Pick a symbol, then click its centre | wall magnet unless `Shift` is held | size, angle and contour style; the common frame preserves ratio unless `Shift` is held |
| Erase | Click a decor object | immediate removal | Undo restores it |
| Erase | Click a decor object | confirmation dialog, then removal | Undo restores it |
The editor always opens on **Select**. If the space has an image, the Plan
backdrop tool appears next to Select but is never armed implicitly.
@@ -74,8 +74,10 @@ rectangle or sofa does not make its outline thicker. A legacy object with render
pixel-identical until edited or explicitly optimised; conversion is
`width_cm = width / GRID_PITCH × cell_cm`.
The toolbar values are session defaults for newly drawn objects. Double-click
properties edit an existing object without creating a second style model.
The toolbar values are session defaults for newly drawn objects. Colour is a
compact swatch; its popover owns both the native colour field and opacity, so
alpha controls do not consume permanent toolbar space. Double-click properties
edit an existing object without creating a second style model.
## Interaction state machine
@@ -86,12 +88,15 @@ idle → draft/move/scale/rotate → release → named history command → debou
Only the active tool owns pointer events. Drawing tools can therefore start a
new line or figure exactly on top of an existing object. Select and Erase are
the only decor tools that target existing decor; the backdrop body belongs
the general tools that target existing decor. The deliberate exception is
Text: clicking an existing text label with Text opens that label's editor;
clicking any non-text shape still starts a new label. The backdrop body belongs
only to the Plan backdrop tool.
`Ctrl/Cmd+Z` first cancels an unfinished draft or live gesture, then walks the
shared history. `Ctrl+Shift+Z` and `Ctrl+Y` redo. Native text-field history wins
while focus is inside an input.
shared history. `Ctrl+Shift+Z` and `Ctrl+Y` obey the same transaction boundary:
the first invocation cancels a live gesture, the next redoes. Native text-field
history wins while focus is inside an input.
## Code ownership
+25 -8
View File
@@ -81,15 +81,23 @@ the old behaviour until an editing client materialises it.
- "Delete" appears beside Hide/Show for every existing marker. It asks for
confirmation and commits immediately. HA device/entity markers leave only
the tombstone above; virtual markers are removed outright.
- Deleting a generated light-group binding also removes that group from the
plan's light-source set. On a legacy unseeded config its formerly folded
member lamps may consequently appear as ordinary devices. This is deliberate
delete semantics, not restoration of a hidden group.
- Deletion removes the marker layout, pending activity state, attachments and
saved vacuum trails. A late drag from a stale browser tab is ignored by the
server while the tombstone exists.
- Deleted bindings are excluded from room LQI, light-source resolution, room
light statistics/fill/Glow, registry-wide climate averages, explicit room
temperature/humidity sources and another marker's `controls`. References in
openings and live text are retained but become inactive (no lock/contact
badge and `—` respectively) so adding the device again restores them without
reconstructing configuration.
- A deleted **device binding** is excluded from room LQI, light-source
resolution, room light statistics/fill/Glow, registry-wide climate averages
and explicit room sources. An **entity binding** tombstone suppresses that
standalone plan object; it does not remove the same entity from the data of
a still-live parent HA device. Tombstones are binding-scoped, not mutations
of the HA registry.
- References in openings, live text and another marker's persisted `controls`
are retained but become inactive (no lock/contact badge, `—`, or control
action respectively). Adding the binding again restores them without
reconstructing configuration or performing an unrelated Save first.
- Duplicate names are still numbered, light groups still fold — those are
aggregation, not hiding.
@@ -103,8 +111,11 @@ source precedence is (`_visualSamples` / `_actEntity`):
«Открыть/закрыть» (`tap_action: 'cover'` — `coverEntityOf`, the same helper
and the same entity the tap drives). It wins over EVERYTHING below;
2. the marker's **resolved light sources** (`resolvedLightSources`): bound
`controls` first, otherwise its primary controllable entity when
`is_light` is set, otherwise automatic `light.*`. This exact set also feeds
`controls` first (other targets only: an `entity:*` marker's bound entity and
a `device:*` marker's child entities are excluded), otherwise its primary controllable entity when
`is_light` is set, otherwise automatic `light.*` only when `light` is the
device's resolved functional role. An auxiliary LED/display light on a
media player or appliance does not turn the whole marker into a lamp. This exact set also feeds
Glow, Light fill, room light stats and group toggle;
3. otherwise the device's **resolved state role**
(`resolvedDeviceStateEntities`): functional device domains first, then
@@ -158,6 +169,12 @@ marker with no running effect. Explicit `off` deliberately reuses the existing
not add another visual status. When a marker resolves several media entities,
it fades only if none is currently available and powered.
The media role also outranks auxiliary `light.*`/`switch.*` entities belonging
to the same physical device. Status LEDs, display illumination and vendor
options therefore neither paint the media marker nor enter room light
aggregates automatically. Explicit marker `controls` or `is_light` remains the
user override for a real light source.
### A cover is never painted (owner 2026-08-04)
«У штор не должно быть жёлтой подложки НИКОГДА, индикация открыто/закрыто за
+1 -1
View File
@@ -1,6 +1,6 @@
# House Plan — продуктовый аудит и план улучшений
Срез: **v1.60.0-beta.1**, 7 августа 2026. Документ основан на чтении исходников, локальном проходе главных пользовательских сценариев и проверке фактических состояний интерфейса. Для принятых задач в нём также фиксируется актуальный статус реализации.
Срез: **v1.60.0**, 7 августа 2026. Документ основан на чтении исходников, локальном проходе главных пользовательских сценариев и проверке фактических состояний интерфейса. Для принятых задач в нём также фиксируется актуальный статус реализации.
## 1. Краткая оценка
+1 -1
View File
@@ -1,6 +1,6 @@
# Документация House Plan
Этот каталог — новая точка входа в русскоязычную документацию House Plan. Материалы ниже сверены с исходным кодом и интерфейсом версии **v1.60.0-beta.1**.
Этот каталог — новая точка входа в русскоязычную документацию House Plan. Материалы ниже сверены с исходным кодом и интерфейсом версии **v1.60.0**.
| Документ | Для кого | Что внутри |
|---|---|---|
+2 -2
View File
@@ -15,11 +15,11 @@
| Item | State |
|---|---|
| Version | **v1.60.0-beta.1** everywhere (manifest, const.py, package.json, CARD_VERSION) — first pre-release of the unified Background editor and true device deletion line. The tag points at the tested `dev` commit and GitHub Release uses `prerelease=true`; `main` remains on stable v1.59.2 |
| Version | **v1.60.0** everywhere (manifest, const.py, package.json, CARD_VERSION) — stable release of the unified Background editor, true device deletion and the complete beta audit hardening. Stable publication fast-forwards `main` to the exact tested `dev` commit and uses `prerelease=false` |
| Workflow | Owner's rule since 2026-08-05: ordinary fixes/features are made **locally, without tests and without commits**. A requested pre-release gets the full tests/build/smokes, one tested `dev` commit/tag and a GitHub Release with `prerelease=true`; `main` stays untouched. A requested stable release gets the same full gate, then `main` is fast-forwarded to the exact tested `dev` SHA and the GitHub Release uses `prerelease=false`. Nothing is copied to the home instance by hand |
| GitHub | https://github.com/Matysh/houseplan-card — `main` carries stable releases; pre-release tags may point directly at `dev`. Work lands on `dev` and is merged into `main` for a stable release, so `dev` is normally equal to or ahead of `main`, never behind. Push via SSH key `ha_jb` (remote git@github.com:…); API releases via the fine-grained PAT in `~/.git-credentials` (Contents R/W, issued 2026-07-23) |
| CI | v1.60.0-beta.1 uses the full local release gate; exact counts are recorded by `npm run inventory` and the test logs rather than copied here. Native Windows cannot start the current HA pytest plugin (`fcntl` is Unix-only), so the exact-SHA Ubuntu Validate remains mandatory: `release.yml` withholds the asset until every matching run finishes green; GitHub Validate and the release asset are verified after the tag is pushed |
| CI | v1.60.0 uses the full local release gate; exact counts are recorded by `npm run inventory` and the test logs rather than copied here. Native Windows cannot start the current HA pytest plugin (`fcntl` is Unix-only), so the exact-SHA Ubuntu Validate remains mandatory: `release.yml` withholds the asset until every matching run finishes green; GitHub Validate and the release asset are verified after the tag is pushed |
| HACS | Custom repository works. **Inclusion PR: hacs/default#9004** — open, valid, labeled, mergeable clean, never drafted. Queue: 1212 open, 835 older than ours. Merge rate COLLAPSED: 75 in July but almost all in the first decade, 0 in the last week (checked 2026-07-29) — maintainers process in rare bursts; ETA unknowable, months at best. Nothing actionable on our side |
| Home instance | ha.jbstudio.pro (SSH port **22222**, key `ha_jb`; HA config root is `/mnt/data/supervisor/homeassistant` — `/config` does NOT exist in this SSH environment), last direct copy was **v1.57.0**; from v1.58.0 on it updates itself through HACS by tag (no scp) |
| Localization | UI en/ru (src/i18n/*.json), everything user-visible localized incl. kiosk popover |
+36 -3
View File
@@ -697,6 +697,15 @@ Run the *core flows* (marked ★ below) in each environment at least once per mi
since v1.52.0, target colours reach only the glow/activity effect; without explicit Toggle
the click opens info as usual; the info card lists targets with states;
locks/other domains are filtered out of controls [auto: smoke_controls]
- [ ] Bound-entity self-control regression: a marker bound to
`entity:switch.hood` with legacy `controls: ["switch.hood"]` is not a
light source/group, opens with no self chip and its explicit Toggle acts
directly on the switch. When ON it may still show the ordinary yellow
working-state plate, but creates no Glow/Light fill/statistics; setting
`is_light` explicitly restores those light behaviours
[auto: smoke_controls; unit: devices.test.mjs, plan-optimizer.test.mjs].
Repeat with a `device:*` binding whose controls contain one of that
device's child switches; the child is excluded while external targets remain
- [ ] Glow fill (v1.35.0): fill mode "Light sources" — every room painted with
one uniform darkness color; lit lamps glow with a radial gradient
(rgb_color → color temp → default color; brightness scales opacity),
@@ -737,6 +746,11 @@ Run the *core flows* (marked ★ below) in each environment at least once per mi
or gesture; a released operation is reverted through Undo. Decor stays
purely visual and inert outside its editor [auto: smoke_decor /
smoke_grid_fade; unit: decor-geometry.test.mjs]
- [ ] Background-editor gesture regressions: a perfectly horizontal/vertical
rect or ellipse draft is discarded; switching tools during a live move
restores the pointer-down snapshot; resizing a rotated box keeps the
opposite corner fixed without a post-resize grid wobble
[auto: smoke_decor; unit: decor-geometry.test.mjs]
- [ ] Opening hover preview (v1.32.1): with the Opening tool, hovering near a
wall shows a dashed 90 cm ghost snapped onto the wall (with a center
dot); no ghost far from walls, over an existing opening (click = edit),
@@ -804,12 +818,13 @@ Run the *core flows* (marked ★ below) in each environment at least once per mi
immediately [manual]
- [ ] Delete an auto device: no icon and no Show-hidden ghost; it does not
return on rebuild/reload, but its binding is offered by Add. Re-add it:
one marker only, fresh centred/grid position, no tombstone [unit + manual]
one marker only, fresh centred/grid position, no tombstone
[auto: smoke_hidden_flag; unit + manual]
- [ ] Delete an entity marker and a virtual marker: the entity is offered by
Add (with Show entities when applicable); the virtual marker is gone and
can be recreated manually. The exact deleted entity remains offered even
if HA marks its registry entry hidden. Other virtual markers survive both
Save and Delete [unit + manual]
Save and Delete [auto: smoke_hidden_flag; unit + manual]
- [ ] Deleted device contributes to none of LQI, climate average, explicit room
temp/humidity, resolved lights, Light fill, Glow, room stats or another
marker's controls. Hidden device keeps the documented hidden semantics
@@ -818,8 +833,16 @@ Run the *core flows* (marked ★ below) in each environment at least once per mi
opening and a deleted live-text variable prints `—`; re-adding the
binding restores both. Layout, attachments and current/previous vacuum
trails are gone [unit + backend + manual]
- [ ] Tombstones stay binding-scoped: deleting a standalone entity does not
remove the same entity from a still-live parent device; temporarily
inactive `controls` remain stored and become active again after re-add.
A stale old card sees a non-virtual tombstone as hidden, never visible
[unit: devices.test.mjs; manual for the old-card fallback]
- [ ] Multi-tab race: after deletion, a stale tab's late layout/update is
acknowledged as ignored and cannot resurrect the old position [backend]
- [ ] A live explicit non-virtual marker whose custom id begins with `v_`
accepts both point and batch layout writes; only an actually orphaned
virtual id is ignored [backend: test_ha_websocket.py]
## Icon rules ★
@@ -985,6 +1008,10 @@ require hands on real hardware — they remain for the human pass.
runs kept per marker, survives reloads, shared by every screen) and never
outruns the icon: drawn segments lag one point, and the last segment is a
rAF-driven tip glued to the puck centre every frame.
- Calling trail delete for a marker with no stored run is a true no-op: its
source/vacuum pair stays subscribed. A successful delete removes only that
marker's pairs and immediately rebuilds the subscription
[backend: test_trail_recorder.py].
- Trail style: cartography casing (dark halo 2.25 + light core 0.9),
readable over any room fill.
- Hidden marker: neither puck nor trail. Uncalibrated active map: no puck.
@@ -1290,6 +1317,11 @@ require hands on real hardware — they remain for the human pass.
snap to nodes in ONE write, openings stay on their walls, and pressing the
button a second time reports nothing to do. Cancel does nothing at all
[auto: smoke_grid_snap + unit test/align-grid.test.mjs]
- [ ] Optimizer migration safety: legacy decor width/text size is clamped to
the backend schema, `fill: true` receives explicit fill style, invalid
legacy `plan_scale` is preserved for repair, an already canonical plan is
a no-op, and a future model version is never downgraded
[unit: plan-optimizer.test.mjs; backend: test_validation.py]
## Backdrop picture: move & scale (docs/BACKDROP.md, dev)
@@ -1636,7 +1668,8 @@ require hands on real hardware — they remain for the human pass.
- [ ] **Complete properties**: double click a piece and change its symbol,
width/depth in m/ft, angle, contour colour/opacity and line width in
cm/in. Save keeps its centre/transform and reloads exactly; Cancel changes
nothing [manual]
nothing; reopening a non-first symbol selects that exact option
[auto: smoke_furniture; manual]
- [ ] **It is only decor**: a piece takes no tap in view mode, has no entity
and no state, and does not appear in any room aggregation. Erase removes
it; Delete removes the selected one [auto: smoke_furniture]
+6 -6
View File
@@ -1,6 +1,6 @@
# House Plan — полное руководство пользователя
Актуально для **v1.60.0-beta.1**. Руководство заново составлено по исходному коду и фактическому интерфейсу этой версии. Старые README и тематические спецификации использовались только для перепроверки сценариев.
Актуально для **v1.60.0**. Руководство заново составлено по исходному коду и фактическому интерфейсу этой версии. Старые README и тематические спецификации использовались только для перепроверки сценариев.
House Plan — локальная интеграция и две Lovelace-карточки для Home Assistant:
@@ -391,8 +391,8 @@ House Plan читает реестры устройств, сущностей и
| Привязка | Устройство, сущность или виртуальный маркер |
| Комната | Автоматическая HA-зона либо ручное назначение, включая комнату без зоны |
| Действие по нажатию | Карточка House Plan, HA more-info, toggle, запуск сценария или управление шторами |
| Управляет источниками света | Группа `light.*`/`switch.*`, переключаемая вместе |
| Это источник света | Позволяет реле/выключателю создавать световое пятно |
| Управляет другими источниками света | Группа других `light.*`/`switch.*`, переключаемая вместе. Собственная entity и сущности привязанного устройства сюда не входят |
| Это источник света | Явно считает само реле/выключатель источником света и позволяет ему создавать световое пятно |
| Использовать температуру climate | Добавляет `current_temperature` термостата/кондиционера в маркер и среднее комнаты |
| Скрыть / Показать | Кнопка в левом нижнем углу диалога. После сохранения убирает или возвращает значок; LQI скрытого устройства всё ещё может участвовать в среднем комнаты |
| Удалить | Кнопка рядом со «Скрыть». После подтверждения сразу полностью убирает устройство с плана и позволяет позднее добавить его заново |
@@ -519,7 +519,7 @@ House Plan читает реестры устройств, сущностей и
| `lock.*` | Оранжевый при unlocked/open | Переход при locking/unlocking | Замкнут/открыт | Карточка; Toggle запрещён |
| `valve.*` | Оранжевый при open/opening/closing | Переход при opening/closing | Обычно нет | Карточка; Toggle можно выбрать явно |
| `climate.*` | Жёлтый только при реальном heating/cooling/working и т. п. | Работа по `hvac_action`/аналогичному атрибуту | Нет | Внутренняя карточка |
| `media_player.*` | Нейтральный при любом включённом/транспортном состоянии; приглушённый при `off`, как при `unknown`/`unavailable` | Нет: `playing` не считается работой | Нет | Внутренняя карточка |
| `media_player.*` | Нейтральный при любом включённом/транспортном состоянии; приглушённый при `off`, как при `unknown`/`unavailable` | Нет: `playing`, вспомогательная подсветка и служебные переключатели не считаются работой | Нет | Внутренняя карточка |
| `vacuum.*` | Жёлтый при cleaning и returning | Работа при cleaning, переход при returning | Нет | Внутренняя карточка; движущийся puck открывает HA more-info |
| `script.*` | Жёлтый, пока `on` | Работа, пока выполняется | Нет | Внутренняя карточка или явный Run |
| `automation.*` | Нейтральный даже при `on` | Короткое событие после явного Run из плана | Нет | Внутренняя карточка или явный Run |
@@ -585,13 +585,13 @@ House Plan читает реестры устройств, сущностей и
| Овал | Drag по габаритам; `Shift` фиксирует круг | Контур и независимая заливка с прозрачностью; показывается `R` либо `Rx × Ry` |
| Текст | Клик открывает диалог | Многострочный текст, переменные HA, цвет/прозрачность, физический размер и угол; масштаб и поворот ручками |
| Мебель | Выбор символа и клик по центру | Символ, размер, цвет, толщина, поворот; магнитится к стене |
| Стереть | Клик по объекту | Удаляет сразу |
| Стереть | Клик по объекту | После подтверждения удаляет объект; действие можно отменить через Undo |
Новые фигуры создаются не меньше половины клетки. После создания объект остаётся выбранным. Создание, движение и изменение размера всегда квантуются по сетке. При рисовании и перемещении действует лёгкий магнит к углам, серединам, центрам и рёбрам других объектов декора и комнат; устройства, проёмы и картинка-подложка не являются целями магнита.
Картинка подложки интерактивна только в своём инструменте. В остальных инструментах этого редактора она показана с непрозрачностью `0.5`, а в просмотре и других редакторах — `1.0`.
Цвет контура/текста/мебели и его прозрачность задаются общим полем. Толщина и размер текста хранятся физически и показываются в сантиметрах или дюймах. Для прямоугольника и овала заливка имеет собственные цвет и прозрачность. Большие размеры в свойствах показываются в метрах или футах.
Цвет контура/текста/мебели и его прозрачность задаются общим компактным полем: нажмите на образец цвета, чтобы открыть выбор цвета и прозрачности. Толщина и размер текста хранятся физически и показываются в сантиметрах или дюймах. Для прямоугольника и овала заливка имеет собственные цвет и прозрачность. Большие размеры в свойствах показываются в метрах или футах.
Редактор подложки использует тот же именованный Undo/Redo на 50 команд, что и геометрия плана. `Esc` отменяет только незавершённое рисование или текущий drag/resize/поворот; после отпускания указателя используйте `Ctrl+Z`/`Cmd+Z`. Повтор — `Ctrl+Shift+Z` либо `Ctrl+Y`.
+20
View File
@@ -137,6 +137,26 @@ Lovelace **пересоздаёт элемент карточки** — выбр
из осевшей геометрии (`_bootSettled`), поэтому холодный бут по-прежнему платит
полный защитный цикл.
### 2.1. Возврат после долгого сна вкладки
Тёплый viewport решает пересоздание экземпляра, но после долгого background
браузер, HA chrome и websocket могут проснуться в разных кадрах. В этот момент
`ResizeObserver` способен выдать нулевой или промежуточный размер сцены. Такой
размер больше никогда не меняет `_view`.
Если вкладка была скрыта не меньше 15 секунд, обычный режим Просмотра включает
короткий `_resumeSettling`: содержимое сцены остаётся за её уже правильным
фоном, пока размер не станет ненулевым и спокойным. После этого сохранённые
центр и zoom пересчитываются по окончательной геометрии и открываются одним
кадром. Памятка `warmBoot` во время промежуточного кадра не обновляется.
Быстрое переключение вкладок, редакторы и киоск в этот путь не входят.
Толстые стены дополнительно имеют критические `fill`, `stroke`, opacity и
`fill-rule` как SVG presentation attributes. Поэтому даже промежуточный кадр
нового DOM-экземпляра не может получить браузерную заливку `black` до того,
как применятся стили компонента; CSS hooks при этом сохранены и по обычному
каскаду остаются сильнее presentation attributes.
## 3. Диалоги переживают пересоздание
В той же записи памятки лежит `dlg`: `{ kind, space, mode, data }`, где