Skip to content

v0.2.2b2 — get_states bootstrap + ha-state-icon stateObj patch (beta)

Pre-release
Pre-release

Choose a tag to compare

@jpettitt jpettitt released this 22 May 16:25

Second beta on the v0.2.2 line. Closes out the remaining "icons not painted" reports from b1. Drop-in upgrade from b1 or v0.2.1 — no schema change.

Bug fixes

Empty watcher cache after bootstrap on slow-loading dashboards

The watcher was copying initial state from `.hass.states` inside `start()`. That map is populated asynchronously by HA's connection layer; on slower setups it was empty when our bundle reached `start()`, and any `state_changed` events that arrived during the subscribe-handshake await were lost. The result was slow-moving entities (temperatures, locks — anything that doesn't fire another state_changed for hours) staying permanently invisible to the cache.

The watcher now fetches authoritative initial state via the `get_states` WS command (same one HA's own connection extension uses), buffers any events that arrive during the fetch, and drains them on top of the snapshot. No race, no lost events, regardless of when `hass.states` happens to populate.

Icons un-painted after Lovelace view switches

The MutationObserver crawler was firing thousands of times during a view swap (~3400 callbacks for a 100-icon dashboard) but our scan logic walked past the new `` elements before Lit rendered into their shadow roots, so they never landed in `knownHosts` and never got painted. Symptom: a 133-icon view would drop to 7 known hosts after switching views.

The painter now also patches `ha-state-icon`'s `stateObj` property setter at bootstrap. Every entity binding HA establishes — in any card, in any surface, regardless of which wrapper holds the entity — flows through the patched setter and applies `smart_icons_color` synchronously, inside Lit's property pipeline. No DOM walking, no MutationObserver chain, no race against Lit's render.

The patch is idempotent (a `Symbol.for(...)` marker prevents double-wrapping) and walks the prototype chain so it works regardless of whether HA places the accessor on the class itself or a base. The DOM-crawler stays as a defensive fallback for HA versions where the prototype shape may change; a one-line `console.warn` is emitted if we can't find the accessor to wrap.

Internals

  • Drop the unused `StateWatcher.getState()` method and `IconHost` re-export from painter.ts — both were artifacts of earlier iterations.
  • New `applyStateObjPatch(klass)` exported from painter.ts (pure form of `patchHaStateIcon`) for unit-testing against a fake Lit-shaped class without touching the global `customElements` registry.
  • 96 pytest + 73 Web Test Runner tests green (+5 new for `applyStateObjPatch`); typecheck clean.
  • Painter bundle: 3.6 KB → 5.0 KB. Panel bundle unchanged.

Upgrade

Drop-in from v0.2.2b1 or v0.2.1. Enable Show beta versions in HACS to pick it up.

Full Changelog: v0.2.2b1...v0.2.2b2