v2 review: page freeze, broken controls, and the proposal design across every page #53

Merged
Breadway merged 13 commits from fix/v2-review-gaps into feature/bos-settings-v2 2026-10-13 19:05:05 +08:00
Owner

Stacked on #46. Found by driving release builds in a hidden nested Hyprland session: sandboxed config, a refusing pkexec stub, every page visited from the sidebar with an on-screen error overlay, and safe controls clicked. Closes BSET-51. Closes BSET-54. Closes BSET-55. Closes BSET-56. Closes BSET-57. Closes BSET-58. Closes BSET-59. Closes BSET-60.

Note on Hyprland: BOS runs stock upstream Hyprland (0.56.2), configured with hyprland.lua instead of hyprland.conf. In that mode, upstream Hyprland rejects hyprctl keyword and the legacy hyprctl dispatch <args> syntax. BSET-57 and BSET-58 come from that, not from any change to Hyprland.

Round 2 (2026-10-09)

Bugs fixed

  • BSET-54, data loss: saving Wi-Fi settings rewrote networks.toml with only ssid, password and hidden, deleting per-network dns and every 802.1x key (eap, identity, ca_cert, ...). Places lost learn. Unmanaged keys are now carried over, with a regression test.
  • BSET-57: Accessibility zoom never applied. With Hyprland running from hyprland.lua, hyprctl keyword is refused ("keyword can't work with non-legacy parsers") but still exits 0. It now uses hyprctl eval and checks for the ok reply.
  • BSET-58: idle screen-off never fired. Power wrote hyprctl dispatch dpms off, which Hyprland running from hyprland.lua parses as Lua and rejects (exit 7). It now writes hl.dsp.dpms through hyprctl eval and migrates the old spelling, which BOS's skel hypridle.conf also ships (filed as BOS-87). Verified with a real hypridle in the nested session.
  • BSET-60: Storage "Measure" showed Unavailable plus a wall of du permission errors. Partial totals are used, and measuring no longer locks the cleanup buttons.
  • BSET-55: Bluetooth listed address-only devices as names ("7D-70-3F-..."). They are folded away in the new Add device sheet.
  • BSET-56: shortcuts using the default modifier showed "B" instead of "Super + B".
  • BSET-59 / nightlight: the hyprsunset liveness probe used gamma 1.0 (1%, blacked out the display), and the daemon was never reaped (one zombie per toggle).
  • 43 search entries pointed at labels that no longer exist.
  • The Wi-Fi hero said "Not connected" while the first scan was still running.

One save model

Every settings form saves itself. Toggles, pickers and sliders save shortly after a change; text fields save when you leave them, so a half-typed password is never written. All Save buttons are gone. Leaving a page writes anything still waiting, and only a failed save stops you, with Try again or Leave without it.

Proposal design, page by page

  • Wi-Fi & network: connection hero, then Places as chips (click to switch place via breadcrumbs profile set), one sentence each, and an Edit sheet (exit node and sign-in network only appear when Tailscale is on, matching breadcrumbs). A note shows when a place has a sign-in network or exit node that breadcrumbs skips. Leftover empty places get Tidy up with Undo. Saved networks sit in a searchable list with Edit and Forget (with Undo). VPN becomes Other connections. The breadcrumbs tunables move to Advanced in plain words (DNS presets, seconds pickers).
  • Bluetooth: hero with Add device, device cards with type icons, battery, and last address digits for identical names.
  • Power: battery hero ("7 h 24 m left · drawing 8.5 W · battery health 96%"), segmented mode/lid/button choices.
  • Updates: count plus Update everything, live steps, package lists folded, one firmware section, plain channel names.
  • Backup & restore: snapshot timeline (newest five) with a restore sheet that says what happens. File backups pick a folder or another computer, set up the store on first use, and restore through a sheet.
  • Startup, Lock screen, Accessibility, Desktop & bar, Sound, Printers, Sharing, About, Storage, Users, Firewall (apps by name), Date & language, Displays all follow the proposal: segmented choices, sheets for editing, technical settings behind Advanced or More.

Capability changes (needs your decision)

Round 1 items 2, 3, 5, 6 and 7 still stand as described before. Changed or new:

  1. Lock, wait after a wrong password: now Half a second, 1 second or 2 seconds, plus the saved value (0.8 s on hermes). 0 and 3 s are no longer offered unless already set.
  2. Places edit in a sheet instead of inline forms (nothing lost).
  3. Backup: "Reboot to pick in GRUB" removed (it only restarted the computer). Restore and the boot menu are unchanged.
  4. Printers: adding by address names the printer automatically (Printer_<host>), instead of a typed name.
  5. Lock: the Blur toggle is hidden (breadlock doesn't draw blur). The stored value is kept.
  6. Accessibility: the dead sticky/slow keys switches are gone. Text size "Small" is still on Appearance only.
  7. Power: the duplicate battery table and the raw TLP profile readout ("balanced/BAT") are gone; everything else is in the hero.
  8. Displays: the "Position 0, 0" readout is gone (dragging still sets it).
  9. About: renaming moved to Sharing; About links there.
  10. Updates: Update everything only shows when updates exist. Firmware still installs from its own section.
  11. Notes: reminder time and model settings moved under disclosures. Calendar fields only show when calendar sync is on.

Not done

  • Firewall, user changes, updates, restores, pairing, Wi-Fi joins and Set up power modes were not pressed against the real system.
  • The breadbar notification settings API (BAR-56) is still unmerged, so Notifications explains that.

Verification

npm run check (0/0), npm test, npm run build, cargo fmt --check, cargo clippy --all-targets --locked -D warnings, cargo test --locked (143 passed). New tests cover breadcrumbs key preservation, the dpms migration, firewall ranges, and Bluetooth stand-in names. Every page was loaded with an error overlay and no errors; key pages were also checked floating at 760 and 480 px.

Stacked on #46. Found by driving release builds in a hidden nested Hyprland session: sandboxed config, a refusing `pkexec` stub, every page visited from the sidebar with an on-screen error overlay, and safe controls clicked. Closes BSET-51. Closes BSET-54. Closes BSET-55. Closes BSET-56. Closes BSET-57. Closes BSET-58. Closes BSET-59. Closes BSET-60. Note on Hyprland: BOS runs stock upstream Hyprland (0.56.2), configured with `hyprland.lua` instead of `hyprland.conf`. In that mode, upstream Hyprland rejects `hyprctl keyword` and the legacy `hyprctl dispatch <args>` syntax. BSET-57 and BSET-58 come from that, not from any change to Hyprland. ## Round 2 (2026-10-09) ### Bugs fixed - **BSET-54, data loss:** saving Wi-Fi settings rewrote networks.toml with only ssid, password and hidden, deleting per-network `dns` and every 802.1x key (`eap`, `identity`, `ca_cert`, ...). Places lost `learn`. Unmanaged keys are now carried over, with a regression test. - **BSET-57:** Accessibility zoom never applied. With Hyprland running from `hyprland.lua`, `hyprctl keyword` is refused ("keyword can't work with non-legacy parsers") but still exits 0. It now uses `hyprctl eval` and checks for the `ok` reply. - **BSET-58:** idle screen-off never fired. Power wrote `hyprctl dispatch dpms off`, which Hyprland running from `hyprland.lua` parses as Lua and rejects (exit 7). It now writes `hl.dsp.dpms` through `hyprctl eval` and migrates the old spelling, which BOS's skel hypridle.conf also ships (filed as BOS-87). Verified with a real hypridle in the nested session. - **BSET-60:** Storage "Measure" showed Unavailable plus a wall of `du` permission errors. Partial totals are used, and measuring no longer locks the cleanup buttons. - **BSET-55:** Bluetooth listed address-only devices as names ("7D-70-3F-..."). They are folded away in the new Add device sheet. - **BSET-56:** shortcuts using the default modifier showed "B" instead of "Super + B". - **BSET-59 / nightlight:** the hyprsunset liveness probe used gamma 1.0 (1%, blacked out the display), and the daemon was never reaped (one zombie per toggle). - 43 search entries pointed at labels that no longer exist. - The Wi-Fi hero said "Not connected" while the first scan was still running. ### One save model Every settings form saves itself. Toggles, pickers and sliders save shortly after a change; text fields save when you leave them, so a half-typed password is never written. All Save buttons are gone. Leaving a page writes anything still waiting, and only a failed save stops you, with Try again or Leave without it. ### Proposal design, page by page - **Wi-Fi & network:** connection hero, then Places as chips (click to switch place via `breadcrumbs profile set`), one sentence each, and an Edit sheet (exit node and sign-in network only appear when Tailscale is on, matching breadcrumbs). A note shows when a place has a sign-in network or exit node that breadcrumbs skips. Leftover empty places get Tidy up with Undo. Saved networks sit in a searchable list with Edit and Forget (with Undo). VPN becomes Other connections. The breadcrumbs tunables move to Advanced in plain words (DNS presets, seconds pickers). - **Bluetooth:** hero with Add device, device cards with type icons, battery, and last address digits for identical names. - **Power:** battery hero ("7 h 24 m left · drawing 8.5 W · battery health 96%"), segmented mode/lid/button choices. - **Updates:** count plus Update everything, live steps, package lists folded, one firmware section, plain channel names. - **Backup & restore:** snapshot timeline (newest five) with a restore sheet that says what happens. File backups pick a folder or another computer, set up the store on first use, and restore through a sheet. - **Startup, Lock screen, Accessibility, Desktop & bar, Sound, Printers, Sharing, About, Storage, Users, Firewall (apps by name), Date & language, Displays** all follow the proposal: segmented choices, sheets for editing, technical settings behind Advanced or More. ## Capability changes (needs your decision) Round 1 items 2, 3, 5, 6 and 7 still stand as described before. Changed or new: 1. **Lock, wait after a wrong password:** now Half a second, 1 second or 2 seconds, plus the saved value (0.8 s on hermes). 0 and 3 s are no longer offered unless already set. 4. **Places** edit in a sheet instead of inline forms (nothing lost). 8. **Backup:** "Reboot to pick in GRUB" removed (it only restarted the computer). Restore and the boot menu are unchanged. 9. **Printers:** adding by address names the printer automatically (`Printer_<host>`), instead of a typed name. 10. **Lock:** the Blur toggle is hidden (breadlock doesn't draw blur). The stored value is kept. 11. **Accessibility:** the dead sticky/slow keys switches are gone. Text size "Small" is still on Appearance only. 12. **Power:** the duplicate battery table and the raw TLP profile readout ("balanced/BAT") are gone; everything else is in the hero. 13. **Displays:** the "Position 0, 0" readout is gone (dragging still sets it). 14. **About:** renaming moved to Sharing; About links there. 15. **Updates:** Update everything only shows when updates exist. Firmware still installs from its own section. 16. **Notes:** reminder time and model settings moved under disclosures. Calendar fields only show when calendar sync is on. ## Not done - Firewall, user changes, updates, restores, pairing, Wi-Fi joins and Set up power modes were not pressed against the real system. - The breadbar notification settings API (BAR-56) is still unmerged, so Notifications explains that. ## Verification `npm run check` (0/0), `npm test`, `npm run build`, `cargo fmt --check`, `cargo clippy --all-targets --locked -D warnings`, `cargo test --locked` (143 passed). New tests cover breadcrumbs key preservation, the dpms migration, firewall ranges, and Bluetooth stand-in names. Every page was loaded with an error overlay and no errors; key pages were also checked floating at 760 and 480 px.
The shared drafts list was a deep $state array that forms push into on
mount and filter out of on unmount. Swapping pages could leave an
undefined hole in it, and DraftNotice's items.some(d => d.dirty) then
threw inside Svelte's flush. Every later update stopped: going from
Mouse & touchpad to Keyboard left Keyboard on Loading... with no
shortcuts or layout.

The list is now a $state.raw array replaced immutably, while each draft
stays its own reactive $state. Hub sections and pages also render
inside error boundaries, so one failing section shows its error and a
Try again button instead of blanking the rest of the page.
Found by driving the v2 build in a nested session:

- Updates: the firmware list was keyed by device name, so two "Hub"
  devices threw each_key_duplicate and the whole Updates section
  (including Update everything) failed to render.
- Battery: upower's time-to-empty was shown while plugged in and fully
  charged ("about 48.8 hours left"). Time remaining now only appears
  while discharging, "Time until full" while charging, and the status
  reads as words ("Fully charged") instead of upower's identifiers.
- Power modes: TLP users saw "No profile service". With TLP installed
  and no tlpctl, Power offers Set up power modes, which installs the
  allow-listed tlp-pd and enables tlp-pd.service through pkexec. The
  Home tile links there instead of sitting disabled.
- Idle timers saved outside the presets (240, 330 seconds) showed as raw
  numbers; any value now reads as minutes and seconds.
- Sidebar: native title tooltips only appear in the icon rail. At full
  width they repeated the label and their popup covered the next item,
  swallowing clicks. The footer shows the hostname instead of repeating
  the username.
- Home: status read failures collapse into one "Some status couldn't be
  read" disclosure with readable names instead of raw D-Bus errors on
  the page; Do not disturb says Not available with a tooltip.
- Pages open at the top: the content pane kept the previous page's scroll
  offset, so Desktop & bar opened halfway down after Appearance.
- Default apps: hidden xdg-mime entries (userapp-Zen-W24BP3.desktop) show
  their real Name instead of the raw desktop id.
- Date & language: locales read as "English (United States)" instead of
  en_US.utf8.
- Backup & restore: snap-pac descriptions read as sentences ("Before
  installing codex-update-manager") instead of pacman command lines;
  the raw text stays in the tooltip.
- Lock screen: clock format, wait after a wrong password and background
  are plain choices; a custom strftime format stays available under a
  disclosure, and the missing-example schema dump is gone.
- Notifications: when the running bar lacks the settings API, say so in
  words and keep the D-Bus error behind Details.
- Storage: one bar per filesystem (/ and /home on one Btrfs volume were
  shown twice).
- Short lists (firmware, firewall rules, users, nearby networks, backup
  snapshots) flow with the page instead of sitting in small inner scroll
  boxes; long package lists get a taller cap.
- Updates no longer lists Secure Boot certificate stores as firmware.
- Managed by BOS startup entries are styled rows; About's Help actions are
  rows with buttons instead of two full-width bars; Privacy & security no
  longer repeats the Users page; Printers page title matches the sidebar.
- Sound: per-app volume is inline (pactl sink-inputs, live via the
  existing subscribe watcher) with mute per app; the full mixer is still
  one click away. Monitor sources and loopback devices sit under a
  disclosure unless one is in use. The first device no longer hugs the
  section heading.
- Bluetooth: paired devices show a type icon from BlueZ's Icon property
  (headphones, controllers, mice, keyboards, phones, speakers).
- Shortcuts: bash -c wrappers are unwrapped before naming, screenshot
  bindings say what they capture, unknown apps read as "Open <App>",
  and directional actions include the direction (Move window left).
- Displays: modes read as "1920 x 1200 · 60 Hz" with the native mode
  marked recommended.
- Destructive buttons (Remove, Forget, Delete) are outlined in red
  instead of solid red fills across Saved networks, Launcher, Users,
  Firewall, Startup, Snapshots and Shortcuts.
feat(network): connection summary, inline join, places in words
All checks were successful
check / check (push) Successful in 2m39s
cff89550c3
- Wi-Fi & network opens with how you are online: the Wi-Fi network with
  signal, a wired connection, or not connected, with the Wi-Fi switch
  alongside. On Ethernet the page used to show only a small Connected
  label next to the radio switch.
- The password field opens under the network being joined, focused,
  with Enter to join, instead of at the bottom of the list.
- Location profiles are now Places, each with a one-sentence summary
  (joins, signs in through, picked automatically when, sends traffic
  through) and its form tucked under Edit.
- Empty places that only repeat another place's name in lowercase (the
  old breadcrumbs backfill) are flagged as removable.
- Fixes BSET-51: the field labelled "Run on connect / Optional command"
  is breadcrumbs' bootstrap SSID. It is now "Connect through first", a
  picker of saved networks.
Every settings form now writes itself: toggles, pickers and sliders shortly
after a change, text fields when you leave them. The mid-page Save buttons
are gone and a failed save shows the error with Try again.

Saving Wi-Fi settings rewrote networks.toml with only ssid, password and
hidden, deleting per-network DNS and all 802.1x login settings, and dropped
learn from places. Unmanaged keys are now carried over by SSID and place
name. Adds get_current_place and set_current_place over breadcrumbs profile.
Wi-Fi opens with how you are connected, then Places as chips plus one
sentence each with an Edit sheet, nearby networks, and saved networks in a
searchable list with Edit and Forget. VPN becomes Other connections and the
breadcrumbs tunables move into Advanced network settings in plain words.
A place that has a sign-in network or exit node while Tailscale is off now
says those settings are skipped. Leftover empty home/work/away places get
a Tidy up with Undo.

Bluetooth uses the hero card and device cards with type icons; identical
names show the last address digits. Add device scans in a sheet and folds
devices that only broadcast an address (shown as 7D-70-3F-...) away.

Shortcuts that rely on the default modifier now show it (Super + B, not B),
and the modifier is a picker. Toasts dismiss themselves.
feat: Power, Mouse, Startup, Updates and Backup in the proposal's style
All checks were successful
check / check (push) Successful in 2m28s
21bb9595d8
Power gets the battery hero (time left, draw to one decimal, health), mode
and lid choices as segmented picks, and drops the duplicate battery table
and raw TLP profile. Mouse shows Normal and percentages instead of raw
libinput numbers, with focus inline. Startup lists apps with switches and
edits them in a sheet; desktop services are folded away.

Updates leads with the update count and Update everything with live steps,
folds package lists away, shows one firmware section, and explains how to
go back. Snapshots restore through a sheet that says what happens; file
backups pick a folder or another computer, set up the store on first use,
and restore through a sheet.
Accessibility zoom used hyprctl keyword, which the Lua config refuses while
still exiting 0, so the zoom silently never applied. It now goes through
hyprctl eval. Power wrote 'hyprctl dispatch dpms off' into hypridle.conf,
a Lua syntax error under BOS, so the screen never turned off when idle;
it now writes hl.dsp.dpms through eval and migrates the old spelling
(BOS's skel ships it) whenever Power settings are saved. The listener
parser now skips braces inside quoted commands.

Desktop & bar, Lock screen and Accessibility follow the proposal: plain
labels and units, segmented choices, sheets for editing, and technical
settings behind Advanced or More. Dead sticky/slow keys and blur controls
are gone.
Sound picks devices from cards with friendly names (Speakers, Built-in)
and mutes from an icon next to the slider. Printers drops the CUPS/IPP
wording and adds by address. Renaming the computer lives in Sharing, with
KDE Connect installable there; About links to it and keeps hardware and
health checks plain. Storage leads with free space and warns when the disk
is nearly full. Users add people and change passwords in sheets. The
firewall allows apps by name (SSH, LocalSend, KDE Connect, Tailscale) with
raw rules under Advanced; it accepts port ranges and removes a rule by what
it allows. Date & language follows the proposal's Time / Language cards.
Displays use segmented choices; the Appearance window preview stays visible
at zero gaps; recommended apps lose the packaging jargon.
fix: storage measuring, stale search entries, and clicks found in the button pass
All checks were successful
check / check (push) Successful in 2m24s
416c9bc283
Measure folders failed whenever du met an unreadable folder (exit 1 with a
usable total), showing Unavailable and a wall of permission errors; app
cache review had the same check. Totals are now used, measuring no longer
locks the cleanup buttons, the snapshot figure that exceeded the disk says
it is shared, and empty caches are hidden.

43 search entries pointed at labels that no longer exist; they now target
the new names and keep the old words as keywords. The Wi-Fi hero says
Checking while the first scan runs instead of Not connected. Night light's
schedule uses the segmented style.
fix(nightlight): probe hyprsunset with gamma 100 and reap the daemon
All checks were successful
check / check (push) Successful in 2m24s
013588df0a
hyprctl hyprsunset gamma takes a percentage, so the liveness probe's 1.0
set 1% brightness and blacked out the display. The spawned hyprsunset is
now waited on, so turning night light off no longer leaves a defunct
process behind.
Breadway changed title from v2 review: fix the page freeze, Updates crash and remaining design gaps to v2 review: page freeze, broken controls, and the proposal design across every page 2026-10-09 15:47:15 +08:00
docs: say stock Hyprland configured with hyprland.lua, not a Lua Hyprland
All checks were successful
check / check (push) Successful in 2m22s
e08582db5a
Comments and two error messages read as if BOS ran a modified Hyprland.
It runs stock Hyprland; the keyword and dispatch limits come from its
hyprland.lua config mode.
Breadway merged commit d205513442 into feature/bos-settings-v2 2026-10-13 19:05:05 +08:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Breadway/bos-settings!53
No description provided.