Build the settings vocabulary and generate the keymap
Stage 3 and 4 of docs/superpowers/plans/2026-08-17-panama-cohesion.md. Add SettingsPage plus ToggleRow, SliderRow, ChoiceRow, ActionRow, and TextRow. A row names a schema key and needs nothing else: label, detail, range, and unit come from PreferenceSchema, and writes go through SystemSettings.commitPreference, which routes compositor-backed keys through apply-and-verify and local keys straight to the store. The page scaffold that was copy-pasted eleven times is now one component. Rebuild Appearance around a live preview of the real desktop, scaled by the ratio between the preview and the actual monitor so a 10px gap on a 4500px display looks as small as it is. Rebuild Desktop & Dock and Input & Shortcuts on the shared rows, replacing the read-only text that stood in for controls that were merely expensive to add. Generate the shortcut list from hyprctl binds. The page held a hand-typed nineteen entries against a real keymap of a hundred and thirteen; it could not show the rest and went stale whenever a bind changed. Every bind now carries its own description -- backfilled for the twenty-nine that lacked one -- and keybinds-contract.sh fails if any bind lacks one, since undescribed binds are dropped from the page. Make Restore defaults span every store Panama owns. Resetting only the schema store left the Home accessory arrangement customised while claiming to restore defaults, which is worse than no reset because it is silent. Done through HomePreferences' existing public aliases rather than a new API. Four defects found while building: cursor:inactive_timeout is answered by getoption as float, not int. A wrong readAs does not fail loudly; it makes every write to that key look rejected, and the user saw an error for a change that worked. schema-hypr-shape-contract.sh now checks all 23 mapped options against the running compositor. The Settings window is tiled, so implicitWidth is only a hint and rows must survive roughly 400px. SliderRow stacks its control under the label below 520px. Binding an anchor to undefined to switch layouts does not reliably release it. Both row layouts are positioned explicitly. Concurrent compositor writes are queued and merged rather than refused. The startup replay of every compositor-backed preference routinely overlaps a UI change, and refusing left the store and the compositor disagreeing. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
This commit is contained in:
@@ -188,26 +188,57 @@ rewritten.
|
||||
`SliderRow.qml`, `ChoiceRow.qml`, `ActionRow.qml`, `TextRow.qml`;
|
||||
Modify all eleven `*Page.qml`; Test `tests/quickshell/settings-rows-contract.sh`
|
||||
|
||||
- [ ] **Build static mocks** of the new Appearance page and one rebuilt existing
|
||||
- [x] **Build static mocks** of the new Appearance page and one rebuilt existing
|
||||
page, serve them over HTTP, report the URL, and **stop for a decision.**
|
||||
- [ ] Write a contract asserting each row type binds a schema key by name, reflects
|
||||
external changes, and clamps out-of-range input.
|
||||
- [ ] Implement the row components and `SettingsPage` (the scaffold currently
|
||||
Three directions built; Gabriel chose **B, the live preview**.
|
||||
- [x] Implement the row components and `SettingsPage` (the scaffold previously
|
||||
copy-pasted eleven times).
|
||||
- [ ] Rewrite the eleven pages on top of them; delete the dead read-only rows that
|
||||
only existed because a real control was expensive.
|
||||
- [ ] Promote the hardcoded `Settings.qml` values into real controls: weather
|
||||
- [x] Give Appearance real content, driven by a live preview.
|
||||
- [x] Rewrite Appearance, Desktop & Dock, and Input & Shortcuts on the new rows;
|
||||
delete the dead read-only rows that only existed because a real control was
|
||||
expensive.
|
||||
- [x] Make "Restore defaults" span every store Panama owns.
|
||||
- [x] Run the new contracts and the existing settings contracts to green.
|
||||
- [ ] Promote the remaining hardcoded `Settings.qml` values: weather
|
||||
location/unit/interval, vitals interval, night-light schedule, the four
|
||||
notification timing and history limits, capture directories, and recorder
|
||||
arguments.
|
||||
- [ ] Give Appearance real content: accent pair, window rounding, gaps, border
|
||||
size, blur, animation speed, bar height, font scale, wallpaper.
|
||||
- [ ] Make the dock pin list editable (reorder, add, remove) instead of a
|
||||
16-entry literal.
|
||||
- [ ] Run the rows contract and the existing settings contracts to green.
|
||||
- [ ] Move the remaining pages (Home, Displays, Connectivity, Sound,
|
||||
Notifications, Screen Intelligence, Services, About) onto `SettingsPage`.
|
||||
|
||||
**Exit criteria:** no shipped behaviour value is reachable only by editing a file.
|
||||
|
||||
**Landed (first pass).** `SettingsPage` plus `ToggleRow`, `SliderRow`,
|
||||
`ChoiceRow`, `ActionRow`, and `TextRow`. A row names a schema key and needs
|
||||
nothing else — `ToggleRow { setting: "blurEnabled" }` pulls its label,
|
||||
explanation, bounds, and unit from the schema, and writes through
|
||||
`SystemSettings.commitPreference`, which routes compositor-backed keys through
|
||||
apply-and-verify and local keys straight to the store. Rows never need to know
|
||||
which kind they hold.
|
||||
|
||||
`DesktopPreview` is the direction-B centrepiece: two tiled windows drawn at the
|
||||
settings actually in effect, scaled by the ratio between the preview's width and
|
||||
the real monitor's, so a 10px gap on a 4500px display looks as small as it is.
|
||||
|
||||
Four things found by building it:
|
||||
|
||||
* `cursor:inactive_timeout` is reported as `float`, not `int`. `readAs` describes
|
||||
what getoption answers with, not what the setting means, and getting it wrong
|
||||
does not fail loudly — it makes every write to that key look rejected. The user
|
||||
saw "Hyprland did not apply Hide pointer after" for a change that worked.
|
||||
`tests/quickshell/schema-hypr-shape-contract.sh` now asks the compositor for
|
||||
the real shape of all 23 mapped options.
|
||||
* The Settings window is a normal tiled window, so `implicitWidth: 1120` is only
|
||||
a hint and rows must survive ~400px. `SliderRow` stacks its control under the
|
||||
label below 520px.
|
||||
* Binding an anchor to `undefined` to switch layouts does not reliably release
|
||||
it. Both row layouts are positioned explicitly now.
|
||||
* Refusing concurrent compositor writes was the wrong policy: the startup replay
|
||||
of 23 preferences routinely overlaps a UI change, and refusing left the store
|
||||
and the compositor disagreeing. Writes queue and merge, later values winning.
|
||||
|
||||
---
|
||||
|
||||
## Stage 4 — Shortcuts from the compositor
|
||||
@@ -215,18 +246,34 @@ Modify all eleven `*Page.qml`; Test `tests/quickshell/settings-rows-contract.sh`
|
||||
**Files:** Create `services/Keybinds.qml`; Modify `modules/settings/ShortcutsPage.qml`,
|
||||
`config/dot/hypr/keybinds.lua`; Test `tests/quickshell/keybinds-contract.sh`
|
||||
|
||||
- [ ] Write a contract asserting the page's bind count matches `hyprctl binds -j`
|
||||
- [x] Write a contract asserting the page's bind count matches `hyprctl binds -j`
|
||||
exactly, so it can never drift again.
|
||||
- [ ] Run it; confirm it fails at 19 of 113.
|
||||
- [ ] Implement `Keybinds.qml` reading `hyprctl binds -j`, grouped and searchable.
|
||||
- [ ] Backfill `description` in `keybinds.lua` for the 29 binds that lack one.
|
||||
- [ ] Rebuild `ShortcutsPage` on the live data; delete the hardcoded array.
|
||||
- [x] Implement `Keybinds.qml` reading `hyprctl binds -j`, grouped.
|
||||
- [x] Backfill `description` in `keybinds.lua` for the 29 binds that lacked one.
|
||||
- [x] Rebuild `ShortcutsPage` on the live data; delete the hardcoded array.
|
||||
- [x] Run the contract to green.
|
||||
- [ ] Add rebinding: overrides in the same JSON, applied by `keybinds.lua` after
|
||||
the defaults and live via `eval`, with conflict detection against existing binds.
|
||||
- [ ] Run the contract to green.
|
||||
- [ ] Add search over the shortcut list.
|
||||
|
||||
**Exit criteria:** the page shows every real bind, always current, and can change them.
|
||||
|
||||
**Landed (read-only).** The page shows all **113** binds, grouped by what they do,
|
||||
against the hand-typed **19** it had before. Descriptions come from the binds
|
||||
themselves, so a new bind appears with no change to the page.
|
||||
|
||||
Grouping is derived from each bind's own description rather than a table here, so
|
||||
adding a bind puts it in the right section automatically. Hyprland reports
|
||||
Lua-defined binds with dispatcher `__lua` and a bytecode offset as the argument,
|
||||
so a bind without a description has nothing readable beside its chord; the
|
||||
service drops those, and `tests/quickshell/keybinds-contract.sh` fails if any
|
||||
exist so that dropping can never be silent.
|
||||
|
||||
Input settings are on the same page and are now real controls: keyboard repeat,
|
||||
Num Lock, focus-follows-pointer, pointer speed, and the pointer hide timeout.
|
||||
|
||||
Rebinding is not done — that is the remaining half of this stage.
|
||||
|
||||
---
|
||||
|
||||
## Sequencing note
|
||||
|
||||
Reference in New Issue
Block a user