diff options
| -rw-r--r-- | docs/superpowers/specs/2026-10-15-drawer-control-center-design.md | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-10-15-drawer-control-center-design.md b/docs/superpowers/specs/2026-10-15-drawer-control-center-design.md new file mode 100644 index 0000000..47eda76 --- /dev/null +++ b/docs/superpowers/specs/2026-10-15-drawer-control-center-design.md @@ -0,0 +1,129 @@ +# Drawer as the control center + +Sub-project 6 of the roadmap in `2026-10-07-island-core-design.md`. The +drawer keeps its look, a notification space above a tile grid, and becomes +the one control surface: the island's controls panel goes, the drawer takes +its SUPER bind, and three things it lacked arrive as a performance page, a +clipboard page and a quiet mode. + +## Drawer shell + +**Keybinds**, in the live `~/.config/hypr/sections/keybindings.lua`, outside +this repo, shown to the user before editing: + +- SUPER alone (the existing `SUPER + Super_L` release bind) runs `ipc call + drawer toggle`. +- SUPER+Return is removed and left free. +- CTRL+SHIFT+L runs `ipc call drawer open clipboard`, replacing the + `cliphist-rofi` command. + +**The controls panel goes.** Its seven tiles each opened a drawer page that +already exists, and the user does not use it. Removed: `ControlsPanel.qml`, +`ControlTile.qml`, `Controls.js`, `test_controls.js`, the controls icon and +`openControls` in `StatusPill.qml`, `toggleControls` and the `"controls"` +panel in `Island.qml`, the `island` IPC target in `shell.qml`, and the +controls list in `Prefs.qml` (`pinnedIp` stays). The island README loses its +controls section; `AGENTS.md` notes where SUPER alone now goes. + +**The tile grid scrolls on its own.** The `Flow` sits inside a `Flickable` +whose height is capped at three rows. Past that, the tiles scroll inside the +box and the notification space above keeps its size. A thin accent scrollbar +shows only when there is overflow, so a fourth row is discoverable. + +**Order:** Sound, Network, Bluetooth, KDE Connect, Mail, Status, Performance, +Clipboard, VMs, AI, Appearance. The everyday ones fill the first three rows. + +## Performance module + +`modules/perf/PerfModule.qml`, name `perf`. + +- Tile line: `CPU 12% · RAM 45%`, with a dot coloured by `Perf.severity` + when it is not ok, as on the island icon. +- Page: the island's `PerfPanel` inside a `Page`. The page sets + `Perf.detailed` while loaded and clears it on destruction. +- `Perf.qml` and `PerfPanel.qml` stay in `island/perf/` and are imported + from there. + +Ceiling, as a `ponytail:` comment: `Perf.detailed` has one writer at a time. +The island panel and the drawer page both open, then one closed, would stop +the detailed sampling under the other. The drawer covers the screen, so the +two are not open together in practice. + +## Clipboard module + +`modules/clipboard/`, name `clipboard`, no service running while the drawer +is closed, no tile line. + +- Opening the page runs `cliphist list` once (750 entries measured, 42 of + them images). +- A search field holds focus on open and filters case-insensitively as you + type. +- A `ListView`, newest first. A text row is one elided line. An image row + (`[[ binary data ... ]]`) shows a thumbnail, decoded with `cliphist decode` + into `$XDG_RUNTIME_DIR/qs-clip/<id>.png` the first time the row is created + and reused after; the directory is tmpfs, cleared by a reboot. +- Up and Down move the highlight, Enter copies the highlighted entry, Escape + behaves as on every page. +- A click or Enter copies and closes the drawer: + `sh -c 'printf %s "$1" | cliphist decode | wl-copy' sh <line>`. The entry + is an argument, never part of the command string: clipboard text is + untrusted. +- An `x` on each row runs `cliphist delete` with the line on stdin the same + way, and the row goes. +- A "Clear all" button in the page header becomes "Confirm?" for 3 seconds; + the second click runs `cliphist wipe` and empties the list. + +## Quiet mode + +A new mode in the status registry: mutes the Claude and opencode sounds and +leaves their popups alone. + +- `shared/Status.qml`: a `ModeFile` on `status.quiet` and `Status.quiet`. + Presentation saves quiet and sets it on, and restores it when it ends, + like dnd and nolock. +- `statusctl`: `quiet` joins `MODES`. `test-statusctl.sh` gains a quiet check. +- Status page: a "Quiet" row, "Mutes Claude and opencode sounds. Popups still + appear." The presentation row's description becomes "Do not disturb, + quiet, no screen lock, breaktimer paused." + +`desktop/modules/status/notify-sound`, symlinked into `~/bin` like +`statusctl`. It exits at once when `statusctl quiet get` prints 1; otherwise +it maps its argument to a file under `~/Music/notify/` and plays it with +`paplay`: + +| argument | sound | +| --- | --- | +| `claude` | `claude-attention.opus` | +| `permission` | `opencode-perms.opus` | +| `complete`, `error`, `question` | `opencode-attention.opus` | +| anything else | nothing | + +Ignoring unknown arguments matters: the opencode notifier runs its command for +every event, `session_started` and `user_message` included. + +Live configs, outside this repo, shown to the user before editing: + +- `~/.claude/settings.json`: the `Notification` hook command becomes + `notify-sound claude`. +- `~/.config/opencode/opencode-notifier.json`: `"sound": false` on + permission, complete, error and question, and + `"command": { "enabled": true, "path": "notify-sound", "args": ["{event}"] }`. + The plugin reloads this file on every event, so no restart is needed. + Notifications stay as they are. + +Behaviour change: error and question played the plugin's bundled default +sound and now play `opencode-attention.opus`. + +## Testing + +- `desktop/modules/status/test-statusctl.sh`, with the quiet check. +- `desktop/modules/status/test-notify-sound.sh`: a fake `paplay` first on + `PATH` records its argument; asserts the file per argument, nothing for an + unknown one, nothing while quiet is 1. `XDG_RUNTIME_DIR` points at a temp + directory so the real mode is untouched. +- On screen, by the user: tile scrolling, SUPER alone, the performance page, + clipboard search, copy (text and image), delete and clear all, the quiet + row against a real Claude notification, presentation turning quiet on. + +New files and directories under `desktop/` need `./reload.sh desktop`, not a +hot reload, and so does the `shared/Status.qml` edit. |
