From 15fb008954a1f10d4037b63ca4fb2d34609755af Mon Sep 17 00:00:00 2001 From: Gabriel Brown Date: Mon, 17 Aug 2026 14:36:30 -0400 Subject: [PATCH] Design Home accessory customization --- ...7-home-accessories-customization-design.md | 245 ++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-17-home-accessories-customization-design.md diff --git a/docs/superpowers/specs/2026-08-17-home-accessories-customization-design.md b/docs/superpowers/specs/2026-08-17-home-accessories-customization-design.md new file mode 100644 index 0000000..dd9762c --- /dev/null +++ b/docs/superpowers/specs/2026-08-17-home-accessories-customization-design.md @@ -0,0 +1,245 @@ +# Panama Home accessories customization design + +## Summary + +Panama will turn the existing Home Assistant card into the approved +**A · Accessory shelf**: a two-column grid of larger light controls with an +always-visible brightness slider on every tile. Panama Settings will gain a +first-class **Home & Phone** page where the user can discover all Home +Assistant lights, choose which ones appear, reorder them, and assign concise +Panama-only aliases. + +The Phone card will add **Messages**, which opens the installed BlueBubbles +desktop application. Messages remains available when KDE Connect is asleep +because it is a local application handoff rather than a KDE Connect action. + +## Goals + +- Discover every Home Assistant light instead of limiting Panama to the old + GNOME extension selection. +- Let the user choose any number of lights, order them, and give them readable + local names without changing Home Assistant itself. +- Show the first four selected lights in Control Center's resting state and + all selected lights in its expanded state. +- Make brightness directly adjustable on every visible light tile. +- Preserve quick on/off control, stale-state handling, and per-light failure + isolation. +- Add a Messages action that opens BlueBubbles from the Phone card. +- Keep credentials, Home Assistant response bodies, and private preferences + out of Git and logs. + +## Non-goals + +- Panama will not rename Home Assistant entities or friendly names globally. +- This release will not add color, color-temperature, scenes, automations, + rooms, dashboards, or non-light domains. +- Panama will not send or read messages itself. BlueBubbles remains the + complete messaging client. +- Panama will not make BlueBubbles availability depend on KDE Connect or the + iPhone's local-network reachability. +- Panama will not continuously send brightness updates while the pointer is + moving. + +## Verified system state + +The live Home Assistant instance currently exposes 22 light entities. All 22 +advertise a brightness-capable color mode. The current compatibility selection +contains seven lights and omits the available Living Room group. Several source +friendly names begin with `Generic Zigbee Coordinator (EZSP)`, which is why +Panama needs local aliases rather than additional truncation rules in the +Control Center. + +BlueBubbles is installed as the Flatpak desktop application +`app.bluebubbles.BlueBubbles`. + +## Control Center interaction + +### Accessory shelf + +The resting Home section uses a two-column, two-row grid. Each selected light +tile contains: + +- a bulb power control; +- the Panama alias, falling back to the Home Assistant friendly name; +- `On`, `Off`, `Unavailable`, or a concise busy/error state; +- the confirmed brightness percentage; and +- a full-width amber brightness slider. + +The first four selected lights appear in the resting grid. The existing +`N accessories` action expands the Home section to a scrollable two-column grid +of every selected light in preference order. A **Manage in Settings** row at +the end opens Panama Settings directly to Home & Phone. + +The tile body and bulb toggle power, except for the slider's own hit area. +Dragging a slider updates only its visual preview. Releasing it sends one Home +Assistant request. A value from 1–100 calls `light.turn_on` with +`brightness_pct`; zero calls `light.turn_off`. Dragging an off light above zero +turns it on at the chosen brightness. This avoids network chatter and makes the +final value deterministic. + +Brightness displayed in Panama is derived from Home Assistant's 0–255 value +and rounded to a percentage. An off light whose current state has no brightness +attribute displays zero. A normal power toggle lets Home Assistant restore its +own previous brightness. + +Only the affected light becomes busy. A successful action refreshes the +catalog and remains globally quiet. A failed action restores the last confirmed +value and shows a concise inline error on that tile; it does not make unrelated +lights stale or emit a global toast. + +### Phone Messages action + +The Phone action grid becomes four equal controls: Send File, Clipboard, Ring, +and Messages. The first three retain their capability and reachability checks. +Messages is enabled whenever BlueBubbles is installed, even if the phone is not +nearby, and launches the allow-listed desktop application without a shell. + +If BlueBubbles is unavailable, the Messages action is visibly disabled and the +Phone detail section offers a plain `BlueBubbles is not installed` explanation. +Opening BlueBubbles is globally quiet. + +## Panama Settings + +### Home & Phone page + +Panama Settings gains a **Home & Phone** sidebar destination between Network & +Devices and Desktop & Dock. Its page contains three cards. + +1. **Home Assistant** shows connection health, discovered-light count, Refresh, + and Open Home Assistant. +2. **Control Center favourites** shows selected accessories as a two-column + card shelf. Each item exposes a drag handle, editable alias, source friendly + name, and Remove action. Dragging reorders the list; the first four are + explicitly marked as the resting Control Center shelf. +3. **Available lights** is a searchable list of the remaining discovered + lights. Add appends a light to the selected list. Source names are always + visible here so similarly named physical devices remain distinguishable. + +A short **Phone continuity** row reports that Messages opens BlueBubbles and +provides an Open action. There is no redundant enable switch: if BlueBubbles is +installed, the button is useful. + +Changes save automatically after a short debounce. Alias input is trimmed; +an empty alias falls back to the source friendly name. Duplicate aliases are +allowed because households can legitimately contain similarly named lights. +Selection may be empty, in which case Control Center shows a setup row that +opens this page. + +## Persistence and migration + +Add `config/HomePreferences.qml` as the durable owner of selected entity IDs, +order, aliases, and an initialization marker. It uses an atomically written +JSON adapter under Quickshell's per-shell state directory, beside the existing +Panama Settings preferences. The file contains no token, URL, or Home Assistant +response data. + +On first launch only, Panama seeds the preference order from the existing +GNOME-extension-compatible selection so the current Control Center does not +reset. After initialization, an intentionally empty selection remains empty and +is never reseeded. New Home Assistant entities appear only in Available lights; +Panama does not silently add them to Control Center. + +Aliases affect Panama only. Home Assistant's current friendly name is retained +as `sourceName` and shown in Settings. If a selected entity disappears from the +catalog, its preference remains in place as unavailable until the user removes +it, preventing temporary Home Assistant outages from destroying configuration. + +## Home Assistant boundary + +Extend `panama-home-assistant` with these normalized interfaces: + +- `catalog` returns every `light.*` entity with `id`, `sourceName`, `state`, + `available`, `active`, `dimmable`, and `brightnessPct`; +- `brightness ENTITY_ID PERCENT` validates a 0–100 integer and calls the + appropriate light service; and +- the existing `toggle ENTITY_ID` remains the on/off action. + +The helper authorizes actions against the current discovered light catalog, +not against arbitrary entity IDs supplied by QML. It never returns unrelated +Home Assistant domains or arbitrary attributes. Action requests use +`homeassistant.toggle`, `light.turn_on`, and `light.turn_off` with an exact +entity ID and, when relevant, `brightness_pct`. + +The existing URL/token precedence remains unchanged: private Panama +environment values first, then the GNOME extension URL and Secret Service +token. The legacy entity list is used only for first-run preference migration. + +`services/HomeAssistant.qml` owns the live catalog, resolves it against +`HomePreferences`, exposes ordered selected entities and the first four shelf +items, and tracks per-entity pending values and errors. Settings and Control +Center consume this one service rather than maintaining separate copies. + +## BlueBubbles boundary + +Extend `SystemSettings.openApplication()` with an allow-listed `bluebubbles` +entry that launches `flatpak run app.bluebubbles.BlueBubbles` as separate +arguments. Add a read-only `bluebubblesAvailable` property based on the +installed desktop application or Flatpak metadata. PhoneControls and the +Settings page consume those interfaces; neither constructs a command string. + +## Failure behavior + +- Home Assistant unreachable: retain the last catalog and selected states, + mark them stale, and offer Retry. +- Authentication rejected: show `Authentication required` without exposing the + response body. +- Catalog contains a malformed entity: omit that entity and keep healthy lights. +- Selected entity temporarily missing: keep its alias/order and show it as + unavailable. +- Preference write fails: retain the in-memory edit, show an inline Settings + error, and allow Retry; do not overwrite the previous valid file. +- Brightness request fails: snap the tile to its last confirmed value and show + the error on that tile only. +- BlueBubbles missing: disable Messages without affecting KDE Connect actions. + +## Files and components + +- `config/dot/quickshell/config/HomePreferences.qml` — private selected-light + order and aliases. +- `config/dot/quickshell/config/qmldir` — register the preference singleton. +- `config/dot/quickshell/scripts/panama-home-assistant` — catalog and brightness + contracts. +- `config/dot/quickshell/services/HomeAssistant.qml` — catalog/preference/action + composition. +- `config/dot/quickshell/services/SystemSettings.qml` — BlueBubbles detection + and allow-listed launch. +- `config/dot/quickshell/modules/quicksettings/HomeControls.qml` — two-column + accessory shelf and expanded selected grid. +- `config/dot/quickshell/modules/quicksettings/HomeTile.qml` — power, + percentage, busy/error state, and slider. +- `config/dot/quickshell/modules/quicksettings/PhoneControls.qml` — Messages + action and independent enablement. +- `config/dot/quickshell/modules/settings/HomePhonePage.qml` — discovery, + selection, aliases, ordering, and phone handoff. +- `config/dot/quickshell/modules/settings/SettingsSidebar.qml` and + `SettingsShell.qml` — page registration and routing. +- `config/dot/quickshell/services/ShellState.qml` and `shell.qml` — allow the + Control Center and tests to open the Home & Phone page directly. + +## Testing and verification + +Focused automated coverage will prove: + +1. Catalog filtering returns all valid lights, excludes other domains and raw + attributes, normalizes 0–255 brightness, and tolerates malformed entities. +2. Brightness validates entity membership and 0–100 bounds, uses + `light.turn_on` for 1–100, and uses `light.turn_off` for zero. +3. First-run migration seeds the legacy order once; selection, aliases, + reordering, removal, and intentionally empty state survive a shell restart. +4. The first four selected lights form the resting shelf and the expanded grid + contains every selected light in order. +5. Slider preview does not issue an action until release; success refreshes; + failure restores the confirmed value and remains local to one tile. +6. Settings routes to Home & Phone, searches the complete catalog, and exposes + source names separately from aliases. +7. Messages maps only to the allow-listed BlueBubbles command and remains + independent of KDE Connect reachability. +8. Existing Control Center, Settings, Home Assistant, KDE Connect, Ongoing, + notification, and shell contracts remain green. +9. Fresh Quickshell construction has no QML errors, Hyprland configuration is + valid, and visual captures cover resting, expanded, off-light drag, + unavailable light, and Settings states. + +Automated tests will not toggle or dim a real light and will not open +BlueBubbles. Those final checks require explicit user actions in the finished +interfaces.