12 KiB
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.
- Home Assistant shows connection health, discovered-light count, Refresh, and Open Home Assistant.
- 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.
- 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:
catalogreturns everylight.*entity withid,sourceName,state,available,active,dimmable, andbrightnessPct;brightness ENTITY_ID PERCENTvalidates a 0–100 integer and calls the appropriate light service; and- the existing
toggle ENTITY_IDremains 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 requiredwithout 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.qmlandSettingsShell.qml— page registration and routing.config/dot/quickshell/services/ShellState.qmlandshell.qml— allow the Control Center and tests to open the Home & Phone page directly.
Testing and verification
Focused automated coverage will prove:
- Catalog filtering returns all valid lights, excludes other domains and raw attributes, normalizes 0–255 brightness, and tolerates malformed entities.
- Brightness validates entity membership and 0–100 bounds, uses
light.turn_onfor 1–100, and useslight.turn_offfor zero. - First-run migration seeds the legacy order once; selection, aliases, reordering, removal, and intentionally empty state survive a shell restart.
- The first four selected lights form the resting shelf and the expanded grid contains every selected light in order.
- Slider preview does not issue an action until release; success refreshes; failure restores the confirmed value and remains local to one tile.
- Settings routes to Home & Phone, searches the complete catalog, and exposes source names separately from aliases.
- Messages maps only to the allow-listed BlueBubbles command and remains independent of KDE Connect reachability.
- Existing Control Center, Settings, Home Assistant, KDE Connect, Ongoing, notification, and shell contracts remain green.
- 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.