aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-15 11:22:49 +0200
committerDanilo M. <danix@danix.xyz>2026-10-15 11:22:49 +0200
commit021c2d42271cdda15a4fdf129ce162d8af8a9ab5 (patch)
treec39945bde94f6f656525353c3b929618111b85e7 /docs/superpowers
parent6cfda76ee4a859a068d10c457a21d67635f06386 (diff)
downloadquickshell-021c2d42271cdda15a4fdf129ce162d8af8a9ab5.tar.gz
quickshell-021c2d42271cdda15a4fdf129ce162d8af8a9ab5.zip
docs(spec): the drawer as the control center
The drawer keeps its look and takes over: the island's controls panel goes, since each of its tiles opened a drawer page that already existed, and SUPER alone opens the drawer instead. The tile grid scrolls inside a three-row box so new tiles do not eat the notification space. New: a performance page reusing the island's Perf service, a cliphist clipboard page replacing the rofi list, and a quiet mode in the status registry that mutes Claude and opencode sounds through one notify-sound script while their popups stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers')
-rw-r--r--docs/superpowers/specs/2026-10-15-drawer-control-center-design.md129
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.