Feat/widgets settings#79
Conversation
entity_id.split('.').nth(1).unwrap_or(entity_id)
}
Introduce widget_visibility module with VisibilityRule/Condition to gate widgets by a trigger entity's state. Wire config.widget_visibility and add settings UI to create/edit rules. Add runtime evaluation and update_widget_visibility to open/close windows accordingly, and track entity_windows_opening to avoid duplicate opens during races/boot; gated widgets remain closed until their trigger is known.
Per-widget visibility rules — gate a widget by another HA entity's state
so widgets only appear when they're actually meaningful (washer time
remaining only while the washer is running, etc).
- VisibilityRule { trigger, condition } in widget_visibility module;
conditions: StateEquals, StateNotEquals, IsAvailable, NumericGt,
NumericLt (numeric stored as raw string for easier UI binding; invalid
values fail-closed and hide the widget).
- Snapdash::reconcile_visibility re-evaluates every rule-gated widget on
HaEvent::InitialState / StateChanged and emits OpenEntity /
CloseWindow tasks for the deltas. Widgets without a rule are left
alone — user controls those.
- entity_windows_opening race-guard so a flurry of HA events doesn't
double-open the same widget while window::open is async-in-flight.
- Bulk boot-open filters by is_widget_visible — gated widgets wait for
the first state snapshot.
- "Show only when…" section in the widget settings dialog: enable
toggle, trigger entity input with live ✓/⚠ hint, condition picker,
value input, and a live "Currently visible/hidden" preview.
- "Hidden by rule" badge in Settings → Sensors so a
gated-and-currently-invisible widget is still findable.
case ("hide this sensor when it's unknown/unavailable") is one click.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aff94fc666
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
| } else if let Some(&id) = self.entity_windows.get(entity_id) { | ||
| tracing::debug!(entity = %entity_id, "visibility rule: closing widget"); | ||
| tasks.push(Task::done(Message::CloseWindow(id))); |
There was a problem hiding this comment.
Keep the app alive when a rule hides the last widget
When the only open window is an entity widget and its visibility rule becomes false, this new reconciliation path emits CloseWindow; the existing WindowClosed handler then sees self.windows.is_empty() and calls iced::exit() at src/app/snapdash.rs:1076. In that single-widget/all-widgets-hidden case the process exits instead of staying connected to HA and reopening the widget when the rule becomes true, so conditional visibility can terminate Snapdash.
Useful? React with 👍 / 👎.
| .cloned() | ||
| .collect() | ||
| } else { | ||
| vec![entity_id] |
There was a problem hiding this comment.
Honor visibility rules for direct widget opens
When a widget has a saved visibility rule that is currently false, removing and then re-adding it from Settings dispatches OpenEntity(entity_id), but this direct-open branch bypasses the is_widget_visible filter that only runs for the bulk boot-open path. Because ToggleWidget leaves the rule in config.widget_visibility and no HA event is required immediately afterward, a hidden-by-rule widget can remain visible after being re-added.
Useful? React with 👍 / 👎.
Summary
Adds a per-widget settings dialog for per-widget tweaks, and ships two issue-driven features inside it: custom widget
names (#78) and conditional visibility rules (#77).
Per-widget settings dialog
WindowKind::WidgetSettings { entity_id }— a small dedicated window per widget, mirroring the main Settings shape (chrome + sections + footer with the entity_id hint).settings_componentsset —page_with_sections,section,item_with_picker,item_with_input,item_with_toggle— so it stays consistent with every other settings page.widget_prioritiesmap.Custom widget names (closes #78)
widget_names: HashMap<String, String>on Config; empty value drops the override.Snapdash::display_name(entity_id)resolves: override → HAfriendly_name→ bare entity_id without the domain prefix. Used by both widget title and dialog title.Conditional visibility rules (closes #77)
widget_visibilitymodule withVisibilityRule { trigger, condition }and 5 condition types:StateEquals,StateNotEquals,IsAvailable,NumericGt,NumericLt. Cross-entity or self-triggering, state-only. Numeric thresholds stored as rawStringso the UI can bind them directly; invalid numbers fail-closed and hide the widget.Snapdash::reconcile_visibilityre-evaluates every rule-gated widget onHaEvent::InitialState/StateChangedand emitsOpenEntity/CloseWindowfor the deltas. Widgets without a rule are left alone — user controls those, otherwise manual close would bounce right back.entity_windows_openingrace-guard set so a flurry of HA events during the asyncwindow::openround-trip doesn't double-open the same widget.is_widget_visible— gated widgets wait for the first HA snapshot. Hide-until-known by default.(variant-dependent), and a live Currently visible/hidden preview. Toggle-off explicitly re-opens the widget (reconcile only iterates rules that exist).
Notable extras
Icon::Slidersglyph (lucidesliders-horizontal) — used by boththe on-widget trigger and the active-sensors-list shortcut so they
visually pair.
widget_visibilityships with unit tests covering every conditionbranch + unknown-trigger / non-numeric fallthrough.
always sit at the right edge regardless of friendly_name / entity_id
wrapping.
Closes