v0.3.1a1
Pre-releaseFirst alpha of the v0.3.1 line. Two threads of work: a code-review
sweep that tightens the integration's robustness without changing
user-visible behavior, and two UX fixes for the rule editor that
came out of dogfooding the v0.3.0 GA.
What's new
-
Panel YAML view: Save / "Show visual editor" are visible again
on long configs.ha-code-editor's hostmax-heightdoesn't
constrain the internal CodeMirror surface — the editor grew with
content and pushed the action row off-screen. Switched to
--code-mirror-max-height(the CSS variable HA's own
automation editor uses), which makes the editor scroll
internally and keeps the action row visible. Same fix applied
to the per-rule code-mode editor. -
Rule editor: backdrop click and ESC no longer silently throw
away unsaved edits. The editor now tracks a dirty flag; when
the user has unsaved work and clicks off the dialog (or presses
ESC), a "Discard changes? [Keep editing] [Discard]" confirm
appears. Save success and clean dismissal pass through
unchanged. Implementation note: HA's modernha-dialogwraps
a native<dialog>and bindspointerdown(notclick) for
backdrop close, so the guard is a document-capture
pointerdownlistener — bubble-phase listeners on the element
are too late.
Internal hardening (from code-review sweep)
- Validation size caps: mapping at 200 entries, thresholds at
50,source_attributelength at 255,replace_allbatch at
1000. Bounds the synchronous validation/scan loops against
pathologically large payloads. - Validation tightening: empty
thresholdslists explicitly
rejected; non-string mapping keys rejected (YAML's bare1:
was silently coerced viastr(), producing rules that didn't
fire); non-stringsource_attributerejected (used to be
vol.Any(str, None)which accepted weird types via voluptuous
coercion). - Setup race fix:
hass.data[DOMAIN]and the store/injector
pointers are now wired beforeinjector.async_start()and WS
command registration, so a WS client racing setup can't see a
partially-populatedhass.data. - Injector attr pre-check: state-update attribute writes only
allocate a new dict when at least one of color / icon /
background actually changed. Eliminates a per-event allocation
for the common no-op case. - Painter memory hygiene: light-DOM and shadow-DOM
removedNodesfrom the MutationObserver now prune
knownHostsimmediately, instead of letting the set grow
until the next full sweep. Fixes a slow leak in busy
Lovelace dashboards with cards rotating in and out. - State watcher:
repaintAll()now only fires when the
smart_icons:decoration attrs were involved (either present
on the old state or present on the new). Filters out the long
tail of unrelated entity updates. - Frontend glob matching parity:
matchGlobnow translates
fnmatch's[!abc]negation to JS regex[^abc], matching the
backendfnmatch.translatesemantics. Previously a glob
pattern with[!rendered targets visually mismatched between
the table and the live injector. - Frontend source-default parity: serialize matches backend's
rule of "only a pure single-literal target defaultssourceto
the target." Multi-target rules with blank source no longer
collapse to a single-source rule on save. - Version-from-manifest:
INTEGRATION_VERSIONis now read
frommanifest.jsonat import time instead of duplicated as a
hardcoded string inwebsocket_api.py. A regression test
locks the two together.
Internal
- Build-time banner in the panel bundle (
[smart-icons] panel bundle build <timestamp>) prints to the browser console on
mount, so future "did my rebuild land?" investigations end with
one console line instead of a guess.
Full changelog: v0.3.0...v0.3.1a1