Handle Wi-Fi and Bluetooth in Settings

Network & Devices was 92 lines and two buttons that opened GNOME. It now
scans, joins, and pairs directly through Quickshell.Networking and
Quickshell.Bluetooth -- NetworkManager and BlueZ over DBus, no shelling
out to nmcli or bluetoothctl. That was the founding requirement for this
desktop: never having to drop to a terminal to join a network.

Scanning follows the page being visible. Wi-Fi scanning and especially
Bluetooth discovery hold the radio, and running either for a list nobody
is looking at spends airtime on nothing.

Joining a secured network gets a real password field, not the clipboard
popover's search box with different placeholder text: a Wi-Fi key typed
into a field that echoes it is readable by anyone behind you, and a
search glyph in front of a password prompt is simply wrong.

Two bugs found by looking at the rendered page, both silent:

The device lookups used enum names that do not exist --
NetworkDeviceType.Wifi rather than DeviceType.Wifi -- so both returned
null and the page reported "No Wi-Fi adapter" on a machine whose Wi-Fi
was connected. Nothing was logged; QML resolves an unknown enum member
to undefined and compares happily.

signalStrength is 0.0-1.0, not a percentage, so thresholds written for
0-100 put every network including the connected one in the bottom
bucket. The labels now use the same buckets as the icons in
quicksettings/WifiList.qml so the two cannot disagree.

The contract compares what the service resolves against what nmcli
reports, rather than only checking that nothing crashed.

Also makes the Home Assistant bridge hermetic: resolve_config read the
user's private env file even when a caller supplied an explicit
environment, so adding a real PANAMA_HOME_ASSISTANT_ENTITIES to that
file silently overrode a fixture asserting the legacy fallback. An
explicit environment is now the whole environment; production still
reads the file. Its live contract skips when no token is configured --
an absent credential is not a defect, and a suite expected to be red
stops being read -- while a configured-but-broken bridge still fails.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
This commit is contained in:
Gabriel Brown
2026-08-18 05:50:07 -04:00
parent b9800bfbab
commit 3c521cf5fa
10 changed files with 750 additions and 44 deletions
@@ -1,92 +1,124 @@
// Network & Devices.
//
// Wi-Fi and Bluetooth are handled here rather than delegated. Everything goes
// through Quickshell.Networking and Quickshell.Bluetooth -- NetworkManager and
// BlueZ over DBus -- and nothing shells out to nmcli or bluetoothctl. That was
// the founding requirement for this desktop: never having to drop to a terminal
// to join a network.
//
// Scanning follows this page being on screen. Wi-Fi scanning and especially
// Bluetooth discovery hold the radio, and doing either for a list nobody is
// looking at is battery and airtime spent on nothing.
import QtQuick
import Quickshell
import Quickshell.Networking
import Quickshell.Bluetooth
import qs.config
import qs.services
import qs.modules.quicksettings
SettingsPage {
id: root
title: "Network & Devices"
lede: "Connect graphically—no terminal workflow required."
lede: Connectivity.activeNetwork
? "Connected to " + Connectivity.activeNetwork.name
: "Wi-Fi, Bluetooth, and the things Fedora owns."
readonly property var wifiDevice: {
for (const device of Networking.devices.values) {
if (device.type === DeviceType.Wifi)
return device;
}
return null;
}
readonly property var bluetoothAdapter: Bluetooth.defaultAdapter
// Drive the scanners only while this page is the one being shown.
Component.onCompleted: Connectivity.active = true
Component.onDestruction: Connectivity.active = false
SettingsCard {
title: "WiFi"
subtitle: Networking.wifiEnabled ? "Available networks" : "Wireless networking is off"
title: "Wired"
visible: Connectivity.wiredDevice !== null
TextRow {
label: "Ethernet"
detail: Connectivity.wiredDevice ? Connectivity.wiredDevice.name : ""
value: Connectivity.wiredDevice && Connectivity.wiredDevice.connected ? "Connected" : "Not connected"
divider: false
}
}
SettingsCard {
title: "Wi-Fi"
// A Wi-Fi switch reading "On" above the words "No Wi-Fi adapter" is a
// contradiction; with no radio the card simply does not belong.
visible: Connectivity.wifiDevice !== null
subtitle: "Networks are re-scanned while this page is open."
SettingRow {
label: "WiFi"
detail: root.wifiDevice ? "Managed by NetworkManager" : "No wireless adapter found"
label: "Wi-Fi"
detail: Connectivity.wifiEnabled ? "On" : "Off"
controlWidth: 48
divider: Connectivity.wifiEnabled
SettingsToggle {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
checked: Networking.wifiEnabled
enabled: Networking.wifiHardwareEnabled
checked: Connectivity.wifiEnabled
enabled: Connectivity.wifiAvailable
onToggled: value => Networking.wifiEnabled = value
}
}
WifiList {
WifiPanel {
width: parent.width
device: root.wifiDevice
active: true
maxHeight: 240
}
ActionRow {
label: "Advanced network settings"
detail: "VPN, wired profiles, DNS, and connection details"
divider: false
action: "Open panel"
onTriggered: SystemSettings.openGnomePanel("network")
visible: Connectivity.wifiEnabled
}
}
SettingsCard {
title: "Bluetooth"
subtitle: root.bluetoothAdapter?.enabled ? "Nearby and paired devices" : "Bluetooth is off"
visible: Connectivity.adapter !== null
subtitle: "Discovery runs while this page is open."
SettingRow {
label: "Bluetooth"
detail: root.bluetoothAdapter ? "Pair and reconnect without leaving Settings" : "No Bluetooth adapter found"
detail: Connectivity.adapter
? (Connectivity.adapter.enabled ? "On" : "Off")
: "Unavailable"
controlWidth: 48
divider: !!(Connectivity.adapter && Connectivity.adapter.enabled)
SettingsToggle {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
checked: root.bluetoothAdapter?.enabled ?? false
enabled: root.bluetoothAdapter !== null
checked: !!(Connectivity.adapter && Connectivity.adapter.enabled)
enabled: Connectivity.adapter !== null
onToggled: value => {
if (root.bluetoothAdapter)
root.bluetoothAdapter.enabled = value;
if (Connectivity.adapter)
Connectivity.adapter.enabled = value;
}
}
}
BluetoothList {
BluetoothPanel {
width: parent.width
active: true
maxHeight: 220
visible: !!(Connectivity.adapter && Connectivity.adapter.enabled)
}
}
SettingsCard {
title: "Owned by Fedora"
subtitle: "VPNs, per-connection routing, printers, and online accounts are configured by GNOME's panels, which are installed and searchable."
ActionRow {
label: "Advanced Bluetooth settings"
detail: "Device details and system-level options"
label: "Network connections"
detail: "VPN, proxies, and per-connection settings"
action: "Open"
onTriggered: SystemSettings.openGnomePanel("network")
}
ActionRow {
label: "Printers"
action: "Open"
onTriggered: SystemSettings.openGnomePanel("printers")
}
ActionRow {
label: "Online accounts"
action: "Open"
divider: false
action: "Open panel"
onTriggered: SystemSettings.openGnomePanel("bluetooth")
onTriggered: SystemSettings.openGnomePanel("online-accounts")
}
}
}