Files
Panama/docs/superpowers/specs/2026-08-23-home-category-redesign.md
T
Gabriel Brown 7578348db1 Merge Home & Phone into a three-tab Home that knows your house
Home is now Overview | My Home | Phone. Overview leads with quick-action
tiles (focus, Do Not Disturb, health, snapshots, storage), keeps the
findings card — updates fold in, the reclaim-space prompt is gone on
purpose — and adds glance cards, the next calendar event, and weather.

My Home groups every light by Home Assistant area: the helper gained an
`areas` command (one REST template render, no websocket), and the rooms
degrade to a flat list on setups without areas. The favorites editor and
connection card moved intact. Phone gains a vitals strip — battery and
cell signal read from KDE Connect's plugin D-Bus objects, where absence
is data, not an error — beside ring, clipboard, send-a-file, and the
BlueBubbles handoff.

The retired home-phone id resolves to my-home forever via a new alias
map in SettingsRoutes (with a hasOwnProperty guard so prototype names
cannot leak into settingsPage). Storage no longer claims 0 B free — the
old page read a field the disks helper never emitted.

Contracts updated alongside; per the new workflow, the full suite runs
once at the end of the redesign (see the test backlog note).

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
2026-08-23 22:06:18 -04:00

6.2 KiB

Home category redesign — Overview | My Home | Phone

Approved 2026-08-23 (mock B, "Rooms & Tabs"). Home absorbs Home & Phone and becomes a three-tab category. Phase-2 feature picks: rooms grouping, phone vitals, Today card. The reclaim-space prompt is removed. Deferred with reserved slots: Assist command box, phone notification inbox, scenes/climate/cameras, now-playing, HA todos.

Taxonomy

SettingsRoutes home category gains tabs; the home-phone category is deleted:

{ page: "home", label: "Home", tabs: [
    { page: "home",    label: "Overview" },
    { page: "my-home", label: "My Home" },
    { page: "phone",   label: "Phone" }
] }

home doubles as category id and first tab (the applications/users/privacy pattern). New leaf ids my-home, phone. A new alias map in SettingsRoutes.resolve() sends the retired home-phone id to my-home so muscle memory, old Vicinae commands, and panama-action settings-page home-phone keep landing correctly. In-repo callers are updated to the new ids anyway: HomeControls.qml, panama-doctor's HA-warning target, Health.qml's settingsTargets.

Pages

HomePage.qml (Overview) — rebuilt. Greeting header and weather lede stay. Then:

  • A five-tile quick-action grid (new HomeQuickTile.qml): Focus session (start/end), Do Not Disturb (live toggle state), Health (→ services), Snapshots (→ snapshots), Storage (→ storage). Fixed set, per the phase decision.
  • "This machine": the existing findings array unchanged (firewall exposure, security advisories, reboot-needed, health attention) plus the "Install N updates" row folded in as a finding when Updates.total > 0. The reclaim-space row is gone entirely.
  • Two glance cards linking into the sibling tabs: My Home ("2 lights on · Living Room, Kitchen") and Phone ("iPhone · 82% · nearby"), each openSettings("my-home"/"phone").
  • "Today": CalendarAgenda.nextEvent with Join/Open; hidden when nothing upcoming or no calendar. Zero new plumbing — the service already streams.
  • "Weather": the existing card, unchanged.
  • The old Focus card and "Right now" containers card are retired (tiles and the System category cover them).

MyHomePage.qml (new, objectName: "my-home-page"). Absorbs the Home-Assistant half of HomePhonePage:

  • "Rooms" card: every catalog light grouped by HA area, rendered as interactive tiles (new HomeLightTile.qml: power square, name, state, brightness track for dimmables, "Control Center" pill on the first four favorites). Toggle → HomeAssistant.toggleEntity, brightness → setBrightness (commit-on-release, like HomeBrightnessSlider). Falls back to a single flat "Lights" section when areas are unavailable.
  • "Accessories" card: the existing favorites editor (HomeFavoriteCard grid — alias, reorder, remove, Control Center badge) and the existing Available-lights search (AvailableLightRow), moved intact.
  • "Home Assistant" card: the existing connection card (URL, token, save/clear, refresh, open) moved intact.
  • Exposes pageDiagnostics (same shape as HomePhonePage's plus rooms summary); the IPC key in settings status renames homePhonemyHome.

PhonePage.qml (new, objectName: "phone-page").

  • Vitals strip: three stat blocks — Battery (% + charging), Signal (type + strength), Reachability — from the extended KdeConnect service. A stat whose datum is absent (unpaired, plugin missing) shows an em-dash, never an error.
  • "Reach it" card: Ring, Send clipboard, Send file (FileDialog, the quicksettings pattern) via existing service functions; transfer progress/cancel as in Control Center.
  • "Messages" card: BlueBubbles status + open (moved from HomePhonePage).
  • "Device" card: pairing/plugins handoff to connectivity (as Control Center does).

HomePhonePage.qml is deleted. HomeFavoriteCard/AvailableLightRow survive under MyHomePage.

Service contracts (pages are written against these; helpers implement them)

panama-home-assistant areas (new command). REST-only: POST /api/template rendering a Jinja template that emits [{ "id", "name", "entities": [...] }] via areas() / area_name() / area_entities() / tojson. Same redacted error codes as the other commands. HomeAssistant.qml gains areas: [] (fetched with refresh) and rooms: [{ id, name, lights: [entity] }] — catalog lights joined to areas, un-areaed lights in a trailing "Other" bucket; empty areasrooms is one unnamed bucket.

panama-kdeconnect status (extended). Per reachable paired device, read via busctl get-property from the plugin objects (paths exist only when paired+reachable — absence is data, not an error): battery: { charge: int, charging: bool } | null from org.kde.kdeconnect.device.battery, signal: { networkType: string, strength: 0-4 } | null from ...device.connectivity_report. KdeConnect.qml surfaces phoneBattery, phoneSignal (null when absent). Unit tests extend the two bridge test files' fake busctl/CLI fixtures.

Blast radius owned by this change

  • SettingsShell.qml: my-home/phone cases + components; homePhoneDiagnostics plumbing renamed and repointed at MyHomePage (SettingsWindow.qml, shell.qml status JSON key myHome).
  • SettingsSearch.qml: home-phone extraEntries re-pointed (my-home for Home Assistant entries, phone for phone entries); new entries for rooms, phone battery, ring, clipboard, Today.
  • Generators re-run: Vicinae commands (settings-home-phonesettings-my-home + settings-phone; home still skipped so Overview adds no command), docs/settings.md.
  • Contracts: home-phone-settings-contract rewritten as my-home-settings-contract (+ phone coverage), control-center-contract (Manage target), health-ui-contract / panama-doctor-contract (settings target), nav/jump/search/gnome-handoff/ panama-commands re-verified against the new route table. home-preferences-contract and phone-messages-contract unchanged.
  • Docs: settings README, manual chapter 05 (Home description), Welcome comment (fourteen categories).

Non-goals (reserved slots, later phases)

Assist box, notification mirror/reply, scenes, climate, cameras, now-playing, todos, HA WebSocket --watch streaming, customizable quick actions.