Design Home accessory customization
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user