# 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 favorites** 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.