Switches sat with the default FILL vertical alignment, so in taller rows (e.g. the
Bluetooth Power switch in the expanded card's header) they stretched to the row
height and rendered as a squared/vertical blob. Give every Gtk.Switch
valign=CENTER so it keeps its fixed pill height regardless of the row.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUWCXM4KhjRkwheaA3X7bP
- Switches: give them a fixed pill with a bordered round knob (the reset theme
left them shapeless).
- Close (x) button: inset with a margin so it no longer overlaps the drawn border.
- Height: the panel overflowed the monitor. Trim the map compact height, quad
min-height, card padding, grid/panel spacing, top margin, and drawer strip so it
fits (≈1600 -> ≈1310 logical on a 1440 display).
- App drawer expand button: use the same nf-fa-expand/compress glyphs as the module
expand buttons instead of chevrons, so all expand controls look uniform.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUWCXM4KhjRkwheaA3X7bP
Network expanded view is rewritten into four tabs over a new nmcli backend
(backend/nm.py, JSON in/out):
- Adapters: each device foldout with editable IPv4 and IPv6 — Automatic/DHCP
toggle, address, a linked subnet-mask <-> CIDR pair (edit either, the other
follows), gateway; applied via `nmcli connection modify/up`. Manual fields dim
when DHCP is on.
- Routes: the kernel routing table (read-only; editing kernel routes needs root).
- VLAN: pick a parent device + ID to create/bring up a VLAN, list + activate/delete.
- DNS: effective servers per device + a per-connection override (servers +
ignore-automatic).
Verified reads and the write path end-to-end (VLAN add/delete via nmcli; each tab
rendered in a harness).
Also: flatten the settings-cog MenuButton's inner `button` node so it shows one
ring instead of two, and drop the border on the close (x) button.
Weather keeps its wttr.in 3-day forecast (unchanged, per request).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUWCXM4KhjRkwheaA3X7bP
- Borders: with the app stylesheet now above the theme, the CSS `.quad-card`
border rendered a second ring concentric with the Cairo bordered() ring. Drop the
CSS border/background/radius from the card boxes so only the Cairo card shows.
- Bluetooth: the power/scan/connect controls were correctly wired to AstalBluetooth,
but the adapter was rfkill soft-blocked, making set_powered a silent no-op. The
power toggle now runs `rfkill unblock bluetooth` before powering on.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUWCXM4KhjRkwheaA3X7bP
Widget settings popover toggles now take effect immediately. QuadCard only
rebuilt a card when its Enabled state flipped, so per-module feature toggles
(Wi-Fi, discovery, routes, CLI art, …) were persisted but never applied. The
card now rebuilds whenever any of its own feature values change, and the
incomplete partial per-module refresh callbacks (which also leaked a dead
subscription per rebuild) are dropped in favour of that single path.
Make the backmost surface transparent so each module floats on its own drawn
border/background: force `window`/`.background`/`.panel` transparent, since a
plain `.menu-window` rule did not override the GTK theme's solid window node.
Locate via IP now works and uses traceroute: geolocate.py traceroutes to
1.1.1.1, takes the first globally-routable hop (the ISP egress) and resolves it
through a public geolocation API, falling back to self-IP when traceroute is
missing or finds no public hop. The ip_locate toggle gates the lookup entirely
(placeholder when off). Adds `traceroute` to the hyprlua package list.
Autostart: `sleep 1 && hyprctl reload` after all spawns so layer-shell clients
settle on the final config.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUWCXM4KhjRkwheaA3X7bP
A touch-friendly GTK4 popup control centre (Python + PyGObject, wlr-layer-shell)
launched from the EWW bar or Super+D. Replaces nwg-dock and nwg-drawer.
Layout: a floating, drawn-bordered panel (anchored top-centre so it never blocks
the rest of the screen) with a 2x2 quad grid over a full-width app drawer, plus a
top taskbar. Any quad expands over the others; the drawer expands to the bottom.
Modules:
- Location — static OSM map (backend/staticmap.py) on IP geolocation
(libshumate won't paint tiles in this env; shumate-demo is blank too)
- Weather — wttr.in ANSI art rendered via an SGR parser into a TextView
- Bluetooth — AstalBluetooth: discovery/connect/disconnect + local history
- Network — AstalNetwork wifi + nmcli/ip/ss for IP, DHCP/manual, routes, ports,
public IP; per-feature toggles
- Taskbar — open windows from hyprctl, grouped by app with pop-out per instance
- Favorites — pinned apps (right-click/long-press to pin) atop the app drawer
Notes:
- Frontend is Python/GTK4, not Lua: lgi/Astal-Lua are GTK3-only.
- Module borders are drawn with a Cairo overlay (lib/border.py); this GTK build's
renderer skips CSS border/background on plain container widgets.
- Consumes Astal GObject libs (io/apps/network/bluetooth) via introspection.
Wiring: autostart + Super+D/Super+Shift+A binds, EWW launcher button in all three
bar variants, apply-theme.sh (_colors.css), installer packages, config-updater.
drawer.sh moved to scripts/deprecated/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>