Keep the Wi-Fi icon steady on OWE transition-mode networks (#14133)

* Keep the Wi-Fi icon steady on OWE transition-mode networks

An OWE transition-mode network pairs an open SSID with a hidden "_owetm_"
twin on the same BSSID. Between scans NetworkManager reports the in-use
access point under the hidden SSID and drops the active profile from the
device's AvailableConnections, which is the only place Quickshell builds
known networks from. No listed network is then connected, so the bar fell
back to the disconnected icon until the next scan brought the open SSID
back, flickering on and off while the link stayed up.

Fall back to the Wi-Fi device's own connected state when no listed network
is connected, and read the in-use access point's strength from nmcli
(without a rescan) while the connected network has none of its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Discard stale in-use AP reads and key Wi-Fi checks on the device

Bump a generation whenever the cached in-use access point strength stops
describing the link (leaving Wi-Fi or a device change), and drop any nmcli
read started before it, re-reading immediately instead of a full interval
later.

Key Wi-Fi connectivity checks on the device rather than the SSID, so the
listed network coming and going with each scan on an OWE transition-mode
network no longer schedules a check. A real network switch still passes
through "disconnected".

Add a QML fixture that runs the panel against a mocked device through the
scan churn, a mid-read disconnect, and a final disconnect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier HanssonandClaude Opus 5.5 authored and GitHub committed 2026-10-03 20:05:32 -04:00
1 parent 8e02fc84f5
commit 18328559b9
5 files changed
+289 -4

No files matched your search

+24
View File
@@ -14,6 +14,28 @@ function wifiIconFor(strength) {
return icons[index]
}
// The connected network's own strength comes from the access points
// Quickshell grouped under its SSID. When it has none (an OWE transition-mode
// network between scans files the in-use access point under its hidden
// "_owetm_" twin), fall back to the strength NetworkManager reports for the
// access point in use.
function connectedSignalStrength(networkStrength, activeApSignal) {
var strength = Math.round((networkStrength || 0) * 100)
if (strength > 0) return strength
return activeApSignal > 0 ? activeApSignal : strength
}
// Reads `nmcli -t -f IN-USE,SIGNAL device wifi list` output, where the in-use
// access point is the row marked "*".
function parseActiveApSignal(raw) {
var lines = String(raw || "").split(/\r?\n/)
for (var i = 0; i < lines.length; i++) {
var match = /^\*:(\d+)$/.exec(lines[i].trim())
if (match) return parseInt(match[1], 10)
}
return -1
}
// A known plain-HTTP endpoint lets the network redirect the browser to its
// login page. Never execute or automatically open an untrusted Location header.
var captivePortalUrl = "http://ping.archlinux.org/nm-check.txt"
@@ -368,6 +390,8 @@ if (typeof module !== "undefined") {
parseNetworkStatus: parseNetworkStatus,
wifiIconFor: wifiIconFor,
connectionIcon: connectionIcon,
connectedSignalStrength: connectedSignalStrength,
parseActiveApSignal: parseActiveApSignal,
connectivityState: connectivityState,
captivePortalUrl: captivePortalUrl,
formatHeaderSpeed: formatHeaderSpeed,