mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
docs: catch all documentation up to v1.23.1
- READMEs (en+ru): doors/windows/locks section (openings tool, live rendering, drag, double-click properties), presence ripples + per-device icon size/rotation in the manual-marker section. - ARCHITECTURE: room geometry rules (derived walls, no-overlap, merge/split via polyclip-ts and why not polygon-clipping), doors & windows model (space.openings, snapToWall, absolute coords, security), per-marker display fields + cell_cm ruler. - DEVELOPMENT: gotchas — polygon-clipping ESM/types mismatch; same-version redeploys keep ?v so browsers cache the old bundle. - STATUS: snapshot refreshed (releases to v1.23.1, dacha deployed v1.23.1), milestones v1.17–v1.23.1 incl. the lost-sources lesson (push right after building). - ROADMAP: 8 shipped Quality-Scale items ticked (done since v1.12.0). - TESTING: restored the v1.22.0 ripple checklist lost in the sandbox reset.
This commit is contained in:
@@ -133,6 +133,21 @@ Rooms may not overlap: a click strictly inside an existing room, or an outline t
|
|||||||
- **Split** — click a room, then two points on its walls; the chord cuts it in two. The bigger part stays the room it was (name, area, devices); the smaller one asks for a new name and area.
|
- **Split** — click a room, then two points on its walls; the chord cuts it in two. The bigger part stays the room it was (name, area, devices); the smaller one asks for a new name and area.
|
||||||
|
|
||||||
|
|
||||||
|
### Doors, windows and locks
|
||||||
|
|
||||||
|
In markup mode the **"Opening"** tool places doors and windows: click next to a wall and the
|
||||||
|
opening snaps onto it. Pick the type, the **length in real centimetres** (defaults: door 90 cm,
|
||||||
|
window 120 cm), an open/close sensor and — for doors — a **lock entity**.
|
||||||
|
|
||||||
|
With a sensor bound, the plan comes alive: the door leaf swings on its hinge and the swing arc
|
||||||
|
draws itself in as the real door opens; a window opens its two casements. While open, the moving
|
||||||
|
parts take an accent colour. A door with a lock shows a padlock badge next to it — green when
|
||||||
|
locked, orange when unlocked. For safety the lock can **not** be toggled from the plan; a click
|
||||||
|
on the opening shows a status card with both states instead.
|
||||||
|
|
||||||
|
Openings are easy to adjust later: hovering one highlights it, you can **drag it along the
|
||||||
|
walls** (it slides around corners too), and a **double click opens its properties**.
|
||||||
|
|
||||||
### Step 3. Devices appear by themselves
|
### Step 3. Devices appear by themselves
|
||||||
|
|
||||||
As soon as you save a room bound to an area, **the devices of that area are automatically laid out inside the outline**. These are the same devices shown on the **Settings → Devices → (filtered by the room)** page — only the meaningful ones, without service records, bridges and duplicates.
|
As soon as you save a room bound to an area, **the devices of that area are automatically laid out inside the outline**. These are the same devices shown on the **Settings → Devices → (filtered by the room)** page — only the meaningful ones, without service records, bridges and duplicates.
|
||||||
@@ -178,6 +193,12 @@ You can also place a **single entity** (not just a whole device): start typing i
|
|||||||
|
|
||||||
Not everything has to be left to the automation. With the **+** button in the header you can place any device, group or a **virtual point** on the plan (for example, an "Inlet valve" that does not exist as a device). Set a name, icon, model, link, description and, if you wish, attach a **PDF manual**.
|
Not everything has to be left to the automation. With the **+** button in the header you can place any device, group or a **virtual point** on the plan (for example, an "Inlet valve" that does not exist as a device). Set a name, icon, model, link, description and, if you wish, attach a **PDF manual**.
|
||||||
|
|
||||||
|
The same dialog controls how the device looks on the plan. **Display** switches between the
|
||||||
|
icon badge, an animated **presence ripple** (pulsing rings while the entity is active, a faint
|
||||||
|
dot when idle — great for motion sensors) or both, with a per-device ring colour and size. The
|
||||||
|
**icon size** (×0.5–3) and **rotation** are also per-device, so a wall valve can be small and
|
||||||
|
turned the way it is mounted.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -135,6 +135,21 @@ title: План дома
|
|||||||
- **Разделить** — кликните комнату, затем две точки на её стенах; хорда разрежет её надвое. Бо́льшая часть остаётся прежней комнатой (имя, зона, устройства), меньшая просит новое имя и зону.
|
- **Разделить** — кликните комнату, затем две точки на её стенах; хорда разрежет её надвое. Бо́льшая часть остаётся прежней комнатой (имя, зона, устройства), меньшая просит новое имя и зону.
|
||||||
|
|
||||||
|
|
||||||
|
### Двери, окна и замки
|
||||||
|
|
||||||
|
В режиме разметки инструмент **«Проём»** ставит двери и окна: кликните рядом со стеной — проём
|
||||||
|
примагнитится к ней. Выберите тип, **длину в реальных сантиметрах** (по умолчанию дверь 90 см,
|
||||||
|
окно 120 см), датчик открытия и — для двери — **замок**.
|
||||||
|
|
||||||
|
С привязанным датчиком план оживает: створка двери поворачивается на петле, и дуга распахивания
|
||||||
|
дорисовывается по мере открытия настоящей двери; окно раскрывает две створки. Пока открыто,
|
||||||
|
подвижные части подсвечены акцентным цветом. У двери с замком рядом отображается замочек —
|
||||||
|
зелёный, когда заперто, оранжевый, когда нет. Ради безопасности замок с плана **нельзя**
|
||||||
|
переключить — клик по проёму показывает карточку с обоими статусами.
|
||||||
|
|
||||||
|
Проёмы легко поправить позже: при наведении проём подсвечивается, его можно **перетащить вдоль
|
||||||
|
стен** (в том числе за угол), а **двойной клик открывает свойства**.
|
||||||
|
|
||||||
### Шаг 3. Устройства появляются сами
|
### Шаг 3. Устройства появляются сами
|
||||||
|
|
||||||
Как только вы сохранили комнату с привязкой к зоне, **устройства этой зоны автоматически расставляются внутри контура**. Берутся те же устройства, что показаны на странице **Настройки → Устройства → (фильтр по нужной комнате)** — только осмысленные, без служебных записей, мостов и дубликатов.
|
Как только вы сохранили комнату с привязкой к зоне, **устройства этой зоны автоматически расставляются внутри контура**. Берутся те же устройства, что показаны на странице **Настройки → Устройства → (фильтр по нужной комнате)** — только осмысленные, без служебных записей, мостов и дубликатов.
|
||||||
@@ -182,6 +197,12 @@ title: План дома
|
|||||||
|
|
||||||
Не всё нужно оставлять на автоматику. Кнопкой **+** в шапке можно поставить на план любое устройство, группу или **виртуальную точку** (например, «Вентиль на вводе», которого нет как устройства). Задайте имя, иконку, модель, ссылку, описание и при желании приложите **PDF-инструкцию**.
|
Не всё нужно оставлять на автоматику. Кнопкой **+** в шапке можно поставить на план любое устройство, группу или **виртуальную точку** (например, «Вентиль на вводе», которого нет как устройства). Задайте имя, иконку, модель, ссылку, описание и при желании приложите **PDF-инструкцию**.
|
||||||
|
|
||||||
|
В этом же диалоге настраивается вид устройства на плане. **Отображение** переключает значок,
|
||||||
|
анимированную **пульсацию присутствия** (расходящиеся кольца, пока сущность активна, и тусклая
|
||||||
|
точка в покое — идеально для датчиков движения) или то и другое сразу, с цветом и размером колец
|
||||||
|
на устройство. **Размер значка** (×0,5–3) и **поворот** — тоже индивидуальные: вентиль на стене
|
||||||
|
может быть маленьким и повёрнутым так, как он установлен.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -86,6 +86,15 @@ Built from the registries (`_buildDevices`), rules carried over 1-to-1 from the
|
|||||||
|
|
||||||
## Device markers (v1.6.0+)
|
## Device markers (v1.6.0+)
|
||||||
|
|
||||||
|
Per-marker appearance (v1.22.0): `display: badge|ripple|icon_ripple` (+`ripple_color`,
|
||||||
|
`ripple_size`) draws presence-style pulsing rings gated by the pure `isActiveState` —
|
||||||
|
deliberately independent of the card-wide `live_states` toggle, with `unavailable` counting as
|
||||||
|
idle. `size` (icon multiplier via the `--dev-size` CSS var — value badges scale along) and
|
||||||
|
`angle` rotate/scale a single icon. Room drawing shows a live **ruler** (`segmentCm` +
|
||||||
|
`formatLength`, metres or feet+inches by `hass.config.unit_system`); the scale is per-space
|
||||||
|
`cell_cm` (default 5 cm per grid cell).
|
||||||
|
|
||||||
|
|
||||||
`config.markers[]`: `{id, binding:'device:<id>'|'entity:<eid>'|'virtual', space?, area?, hidden?,
|
`config.markers[]`: `{id, binding:'device:<id>'|'entity:<eid>'|'virtual', space?, area?, hidden?,
|
||||||
name?, icon?, model?, link?, description?, pdfs:[{name,url}]}`. A hybrid: auto-discovered HA devices
|
name?, icon?, model?, link?, description?, pdfs:[{name,url}]}`. A hybrid: auto-discovered HA devices
|
||||||
appear on their own; a marker with `binding=device:<id>` overrides them (metadata/rebinding/hiding),
|
appear on their own; a marker with `binding=device:<id>` overrides them (metadata/rebinding/hiding),
|
||||||
@@ -109,6 +118,18 @@ Plan files: `<config>/houseplan/plans/<space>.<ext>` → URL `/houseplan_files/p
|
|||||||
If the server config is empty, the card falls back to the legacy bundle (the dacha) and shows a
|
If the server config is empty, the card falls back to the legacy bundle (the dacha) and shows a
|
||||||
"To server" migration button in edit mode. The dacha was migrated on 2026-07-04.
|
"To server" migration button in edit mode. The dacha was migrated on 2026-07-04.
|
||||||
|
|
||||||
|
## Room geometry rules (v1.19–v1.21)
|
||||||
|
|
||||||
|
A **line is never an entity of its own**: walls are *derived* from room outlines
|
||||||
|
(`roomEdges`, deduped by `segKey`), so an abandoned outline leaves nothing behind and deleting
|
||||||
|
a room keeps the walls its neighbours still contribute. Rooms may not overlap
|
||||||
|
(`pointStrictlyInside` + `roomsOverlap`; being ON a shared wall is legal — real neighbouring
|
||||||
|
walls overlap collinearly rather than match exactly). **Merge/Split** use boolean geometry from
|
||||||
|
**polyclip-ts** (chosen over `polygon-clipping`, whose ESM build exports only a default while
|
||||||
|
its types declare named exports — breaking either tsc or the runtime): merge accepts a pair only
|
||||||
|
when the union collapses into one hole-free outline; split cuts wall-to-wall with a chord, the
|
||||||
|
bigger part keeps the room identity (name/area/devices).
|
||||||
|
|
||||||
## Markup editor (v1.4.0+)
|
## Markup editor (v1.4.0+)
|
||||||
|
|
||||||
State inside the card: `_markup` (mode), `_tool` (draw/delroom), `_path` (the current outline,
|
State inside the card: `_markup` (mode), `_tool` (draw/delroom), `_path` (the current outline,
|
||||||
@@ -127,6 +148,26 @@ While drawing, the length of the current segment follows the cursor (`_fmtLen`
|
|||||||
`formatLength`): metres, or feet+inches when `hass.config.unit_system` is imperial. The scale is
|
`formatLength`): metres, or feet+inches when `hass.config.unit_system` is imperial. The scale is
|
||||||
per-space `cell_cm` — cm represented by one grid cell (default 5, so 240 cells ≈ 12 m).
|
per-space `cell_cm` — cm represented by one grid cell (default 5, so 240 cells ≈ 12 m).
|
||||||
|
|
||||||
|
## Doors & windows (v1.23.0+)
|
||||||
|
|
||||||
|
`space.openings[]` — plan geometry, **not** markers: an opening needs an angle, a length and a
|
||||||
|
wall, while markers are free points whose positions live in the layout store. Model:
|
||||||
|
`{id, type: door|window, x, y, angle, length, contact?, lock?, invert?, flip_h?, flip_v?}`
|
||||||
|
(normalized coords; `length` normalized by plan width). Placement snaps onto the nearest
|
||||||
|
**derived** wall via `snapToWall` (logic.ts) — the angle is normalized to [-90, 90) because two
|
||||||
|
rooms share a wall with opposite edge directions, and without that a drag across segment
|
||||||
|
boundaries flips the hinge. The opening then keeps **absolute coordinates**, so editing, merging
|
||||||
|
or deleting rooms never breaks it.
|
||||||
|
|
||||||
|
Rendering (after easy-floorplan, MIT): SVG symbol at the origin (jambs + hinged leaf + a
|
||||||
|
quarter-circle arc revealed via `stroke-dashoffset`), translated/rotated onto the wall; windows
|
||||||
|
are two casement leaves. `openingAmount` (pure) maps the contact state to 0..1: no sensor →
|
||||||
|
door drawn open / window closed (static-plan convention); `unavailable`/`unknown` freeze that
|
||||||
|
default. The lock renders as an HTML padlock badge (`.oplock`) in the device layer; a lock is
|
||||||
|
**never** toggled from the plan (TOGGLE_FORBIDDEN_DOMAINS rule). View-mode UX: hover outline,
|
||||||
|
drag along walls (continuous re-snap, saved on release), click → status card (250 ms timer),
|
||||||
|
double click → properties dialog. In markup mode the "Opening" tool handles clicks instead.
|
||||||
|
|
||||||
## Integration WS API
|
## Integration WS API
|
||||||
|
|
||||||
| Command | Parameters | Response |
|
| Command | Parameters | Response |
|
||||||
|
|||||||
@@ -69,6 +69,15 @@ cp dist/houseplan-card.js custom_components/houseplan/frontend/
|
|||||||
("InvalidStateError: Transition was aborted", hui-view is not created for 1–2 min).
|
("InvalidStateError: Transition was aborted", hui-view is not created for 1–2 min).
|
||||||
Cured by repeating the SPA navigation: pushState + a location-changed event, or just waiting.
|
Cured by repeating the SPA navigation: pushState + a location-changed event, or just waiting.
|
||||||
|
|
||||||
|
## Dependency and cache gotchas
|
||||||
|
|
||||||
|
- **polygon-clipping is a trap**: its `.d.ts` declares named exports but the ESM build has only
|
||||||
|
a default export — tsc or the runtime breaks, whichever you appease. Use **polyclip-ts**
|
||||||
|
(proper ESM + native types; same results, +~50 KB bundle via bignumber.js).
|
||||||
|
- **Redeploying the same version keeps the resource URL** (`/houseplan_files/houseplan-card.js?v=X`),
|
||||||
|
so browsers may serve the previous bundle from cache. Bump the version for anything users must
|
||||||
|
pick up, or hard-refresh (Ctrl+Shift+R) when testing a hotfix redeploy.
|
||||||
|
|
||||||
## Release
|
## Release
|
||||||
|
|
||||||
Tag `vX.Y.Z` + GitHub Release → the workflow `.github/workflows/release.yml` builds and attaches
|
Tag `vX.Y.Z` + GitHub Release → the workflow `.github/workflows/release.yml` builds and attaches
|
||||||
|
|||||||
+8
-8
@@ -14,27 +14,27 @@ This roadmap replaces them.
|
|||||||
|
|
||||||
Track progress in `custom_components/houseplan/quality_scale.yaml` (done/exempt + comment).
|
Track progress in `custom_components/houseplan/quality_scale.yaml` (done/exempt + comment).
|
||||||
|
|
||||||
- [ ] `runtime-data`: move `hass.data[DOMAIN]` (stores, entry, write lock) to typed
|
- [x] `runtime-data`: move `hass.data[DOMAIN]` (stores, entry, write lock) to typed
|
||||||
`entry.runtime_data` (`type HouseplanConfigEntry = ConfigEntry[HouseplanData]`).
|
`entry.runtime_data` (`type HouseplanConfigEntry = ConfigEntry[HouseplanData]`).
|
||||||
Keep WS command registration in `async_setup` (commands must survive entry reloads).
|
Keep WS command registration in `async_setup` (commands must survive entry reloads).
|
||||||
- [ ] `config-entry-unloading` (Silver, do it now): real `async_unload_entry` — unregister
|
- [x] `config-entry-unloading` (Silver, do it now): real `async_unload_entry` — unregister
|
||||||
update listeners via `entry.async_on_unload`; document what stays (static paths cannot
|
update listeners via `entry.async_on_unload`; document what stays (static paths cannot
|
||||||
be unregistered — exempt comment).
|
be unregistered — exempt comment).
|
||||||
- [ ] `test-before-setup`: verify storage is loadable/writable in `async_setup_entry`,
|
- [x] `test-before-setup`: verify storage is loadable/writable in `async_setup_entry`,
|
||||||
raise `ConfigEntryNotReady` on failure.
|
raise `ConfigEntryNotReady` on failure.
|
||||||
- [ ] `unique-config-entry`: replace the manual `_async_current_entries()` check with
|
- [x] `unique-config-entry`: replace the manual `_async_current_entries()` check with
|
||||||
`single_config_entry: true` in manifest.
|
`single_config_entry: true` in manifest.
|
||||||
- [ ] `config-flow-test-coverage` + backend tests for websocket_api (pytest-homeassistant-custom-component:
|
- [x] `config-flow-test-coverage` + backend tests for websocket_api (pytest-homeassistant-custom-component:
|
||||||
conflict/rev, admin_only enforcement, layout point ops, upload limits).
|
conflict/rev, admin_only enforcement, layout point ops, upload limits).
|
||||||
- [ ] Storage versioning: `Store(minor_version=...)` + `_async_migrate_func` skeleton **now**,
|
- [x] Storage versioning: `Store(minor_version=...)` + `_async_migrate_func` skeleton **now**,
|
||||||
before the config schema evolves further (Bronze-adjacent, cheap while schema is stable).
|
before the config schema evolves further (Bronze-adjacent, cheap while schema is stable).
|
||||||
- [ ] `quality_scale.yaml` with honest exempt list (no entities ⇒ entity rules N/A, no polling, no deps).
|
- [x] `quality_scale.yaml` with honest exempt list (no entities ⇒ entity rules N/A, no polling, no deps).
|
||||||
|
|
||||||
## Phase 8 — Quality Scale: Silver + selected Gold
|
## Phase 8 — Quality Scale: Silver + selected Gold
|
||||||
|
|
||||||
- [ ] `test-coverage` ≥95% backend; frontend: extract remaining pure logic (view math,
|
- [ ] `test-coverage` ≥95% backend; frontend: extract remaining pure logic (view math,
|
||||||
marker resolution) into `logic.ts`/`devices.ts` and cover with node:test.
|
marker resolution) into `logic.ts`/`devices.ts` and cover with node:test.
|
||||||
- [ ] `diagnostics.py`: config + layout dump with `async_redact_data` (redact names/links/PDF paths).
|
- [x] `diagnostics.py`: config + layout dump with `async_redact_data` (redact names/links/PDF paths).
|
||||||
- [ ] `reconfiguration-flow` + richer **options flow**: admin_only, curation defaults
|
- [ ] `reconfiguration-flow` + richer **options flow**: admin_only, curation defaults
|
||||||
(exclude domains — UI editable, replacing the hardcoded EXCLUDED_DOMAINS fallback),
|
(exclude domains — UI editable, replacing the hardcoded EXCLUDED_DOMAINS fallback),
|
||||||
LQI thresholds, group_lights default.
|
LQI thresholds, group_lights default.
|
||||||
|
|||||||
+24
-3
@@ -9,16 +9,16 @@
|
|||||||
> (versions, publication, infrastructure), DEVELOPMENT.md for new gotchas,
|
> (versions, publication, infrastructure), DEVELOPMENT.md for new gotchas,
|
||||||
> ARCHITECTURE.md for design changes, ROADMAP.md when plans move.
|
> ARCHITECTURE.md for design changes, ROADMAP.md when plans move.
|
||||||
|
|
||||||
## Snapshot (2026-07-05)
|
## Snapshot (2026-07-17)
|
||||||
|
|
||||||
| Item | State |
|
| Item | State |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Version | **v1.23.1** everywhere (manifest, const.py, package.json, CARD_VERSION) |
|
| Version | **v1.23.1** everywhere (manifest, const.py, package.json, CARD_VERSION) |
|
||||||
| GitHub | https://github.com/Matysh/houseplan-card — branch `main`, releases v1.9.3…v1.11.2 |
|
| GitHub | https://github.com/Matysh/houseplan-card — branch `main`, releases v1.9.3…**v1.23.1** (latest published 2026-07-17, bundle auto-attached by release.yml) |
|
||||||
| CI | `.github/workflows/validate.yml` (hacs + hassfest + frontend + backend) — **fully green** since v1.11.1; `release.yml` auto-attaches the card bundle (needs `permissions: contents: write`, fixed) |
|
| CI | `.github/workflows/validate.yml` (hacs + hassfest + frontend + backend) — **fully green** since v1.11.1; `release.yml` auto-attaches the card bundle (needs `permissions: contents: write`, fixed) |
|
||||||
| HACS | Works as custom repository (id 1290210112 on the home instance). **Inclusion PR: https://github.com/hacs/default/pull/9004** (queue ≈2 months as of 2026-07). Lesson: #8995 was auto-closed by hacs-bot — the PR body MUST be their exact template with every checkbox ticked and all 3 links (release, HACS action run, hassfest run); a custom body gets closed without discussion |
|
| HACS | Works as custom repository (id 1290210112 on the home instance). **Inclusion PR: https://github.com/hacs/default/pull/9004** (queue ≈2 months as of 2026-07). Lesson: #8995 was auto-closed by hacs-bot — the PR body MUST be their exact template with every checkbox ticked and all 3 links (release, HACS action run, hassfest run); a custom body gets closed without discussion |
|
||||||
| Brands | Ships **inside the integration**: `custom_components/houseplan/brand/{icon,icon@2x,logo,logo@2x}.png` (HA ≥2026.3 local-brands mechanism). home-assistant/brands PR #10700 was auto-closed — that repo no longer accepts custom integrations |
|
| Brands | Ships **inside the integration**: `custom_components/houseplan/brand/{icon,icon@2x,logo,logo@2x}.png` (HA ≥2026.3 local-brands mechanism). home-assistant/brands PR #10700 was auto-closed — that repo no longer accepts custom integrations |
|
||||||
| Home instance | ha.jbstudio.pro (SSH port 323, key `ha_jb`), deployed v1.11.2, installed *via HACS* (custom repo) — updates flow through HACS now |
|
| Home instance | ha.jbstudio.pro (SSH port 323, key `ha_jb`), deployed **v1.23.1**, installed *via HACS* (custom repo). The user has real rooms, 12 openings (doors/windows with TTLock locks and contact sensors) and live fills configured |
|
||||||
| Localization | UI en/ru (`src/i18n.ts`), auto by `hass.locale` + `language` card option; codebase and docs are English-first (`README.ru.md` is the Russian copy) |
|
| Localization | UI en/ru (`src/i18n.ts`), auto by `hass.locale` + `language` card option; codebase and docs are English-first (`README.ru.md` is the Russian copy) |
|
||||||
| Tests | 77 frontend (node:test, incl. a 12-test buildDevices suite on a fake hass) + 10 pure backend (anywhere) + 12 HA-harness backend (CI only, py3.13; skipped locally — sandbox has py3.10) |
|
| Tests | 77 frontend (node:test, incl. a 12-test buildDevices suite on a fake hass) + 10 pure backend (anywhere) + 12 HA-harness backend (CI only, py3.13; skipped locally — sandbox has py3.10) |
|
||||||
|
|
||||||
@@ -67,6 +67,27 @@
|
|||||||
space-geometry/space-render + module-level config cache (config-store).
|
space-geometry/space-render + module-level config cache (config-store).
|
||||||
- **v1.16.1** — space-card renders room fills as configured on the full card (snapshot),
|
- **v1.16.1** — space-card renders room fills as configured on the full card (snapshot),
|
||||||
no longer omitted; +shared areaLqi().
|
no longer omitted; +shared areaLqi().
|
||||||
|
- **v1.17.x** — entity markers get auto icon/temp (issue #1); correct resource URL documented
|
||||||
|
(issue #2); humidity badge (gated on device_class, not the icon).
|
||||||
|
- **v1.18.x** — live ruler while drawing rooms (metres / feet+inches) + per-space scale
|
||||||
|
`cell_cm`; visibility fix (the badge lived in the markup-hidden devlayer).
|
||||||
|
- **v1.19.0** — a line is never an entity of its own: walls derived from room outlines
|
||||||
|
(`roomEdges`), unfinished contours persist nothing, Erase tool removed, `space.segments`
|
||||||
|
stripped on save.
|
||||||
|
- **v1.20.0** — rooms may not overlap (strictly-inside clicks refused, overlapping contours
|
||||||
|
refused at close; shared walls stay legal).
|
||||||
|
- **v1.21.x** — merge & split rooms (boolean geometry via polyclip-ts; merge = union collapses
|
||||||
|
to one hole-free outline; split = wall-to-wall chord, bigger part keeps identity) + UX fixes.
|
||||||
|
- **v1.22.0** — presence ripples (badge/ripple/icon_ripple + colour/size, `isActiveState`),
|
||||||
|
per-device icon size/rotation (`--dev-size`), one-click HACS badge. NOTE: sources were lost
|
||||||
|
in a sandbox reset after deploy and restored from conversation patches — push immediately
|
||||||
|
after building, never wait for verification.
|
||||||
|
- **v1.23.0** — doors & windows: "Opening" markup tool (snap onto derived walls, absolute
|
||||||
|
coords), length in real cm, contact sensor + lock, animated leaf/arc, padlock badge, status
|
||||||
|
card; lock never toggled from the plan.
|
||||||
|
- **v1.23.1** — openings UX: hover outline + grab cursor, drag along walls (angle normalized
|
||||||
|
to [-90,90) so the hinge never flips), click=status / double-click=properties, thicker hit
|
||||||
|
strip. Release v1.23.1 published on GitHub (covers v1.22.0–v1.23.1).
|
||||||
|
|
||||||
## Where things live
|
## Where things live
|
||||||
|
|
||||||
|
|||||||
@@ -210,6 +210,18 @@ require hands on real hardware — they remain for the human pass.
|
|||||||
- [ ] `show_button: false` hides the footer
|
- [ ] `show_button: false` hides the footer
|
||||||
- [ ] Full card honours `#space=<id>` on load and on hashchange; invalid id ignored [auto]
|
- [ ] Full card honours `#space=<id>` on load and on hashchange; invalid id ignored [auto]
|
||||||
|
|
||||||
|
## Presence ripples / per-device icon (v1.22.0)
|
||||||
|
|
||||||
|
- [ ] Marker dialog → Display = "Ripple only": the icon badge disappears, rings pulse while the
|
||||||
|
entity is on, and collapse to a faint dot when it goes off
|
||||||
|
- [ ] Display = "Icon + ripple": both the icon and the rings are drawn
|
||||||
|
- [ ] Ripple colour and size (×2..×8) apply per device
|
||||||
|
- [ ] An entity going `unavailable` stops the pulsing (idle dot), never leaves it running
|
||||||
|
- [ ] Icon size ×0.5..×3 and rotation 0..350° apply per device; the temp/humidity badges
|
||||||
|
scale with the icon
|
||||||
|
- [ ] Ripples still work with the card-wide "live states" toggle OFF (they are opt-in per device)
|
||||||
|
- [ ] With OS "reduce motion" enabled, rings do not animate
|
||||||
|
|
||||||
## Doors & windows (v1.23.0)
|
## Doors & windows (v1.23.0)
|
||||||
|
|
||||||
- [ ] Markup → "Opening": a click away from any wall shows a toast; near a wall — the dialog
|
- [ ] Markup → "Opening": a click away from any wall shows a toast; near a wall — the dialog
|
||||||
|
|||||||
Reference in New Issue
Block a user