Extract the Wi-Fi QR share card into its own omarchy.wifiqr panel plugin (#6598)

* Extract the Wi-Fi QR share card into its own omarchy.wifiqr panel plugin

omarchy-network-qr now leads with an iface/security/ssid meta line, so a
bare summon self-detects the connection and the plugin owns the whole
share flow. The network panel loses its overlay lifecycle: with no
centered card left inside it, the shadowed open/close collapses back to
the stock panel behavior, and the QR button just summons the plugin --
which a clone or third-party plugin can replace, like the speed test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Keep canceled QR and password runs from leaking into their replacements

Copilot review: the cancellation guards dropped in onExited while the
canceled run's collectors were still allowed to fire, so a stale stderr
could shadow a successful regeneration and a stale password could be
revealed under a new network's card. The guards now stay up until the
next run launches, good output settles any earlier error, and a bare
re-summon no longer inherits the previous card's SSID.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-08-07 12:50:04 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 474d9dd4eb
commit 018f881840
12 changed files with 519 additions and 389 deletions
+37 -7
View File
@@ -33,13 +33,34 @@ chmod +x "$tmp/bin/nmcli" "$tmp/bin/qrencode"
run_success_case() {
local description=$1 fields=$2 expected_payload=$3
shift 3
local expected output payload
local output meta matrix payload arg with_meta=false
local expected_matrix expected_security expected_ssid expected_iface="*"
for arg in "$@"; do
[[ $arg == "--meta" ]] && with_meta=true || expected_iface=$arg
done
export QR_NMCLI_FIELDS=$fields
export QR_PAYLOAD_FILE="$tmp/payload"
output=$(PATH="$tmp/bin:$PATH" "$ROOT/bin/omarchy-network-qr" "$@")
expected=$'100\n010\n001'
[[ $output == "$expected" ]] || fail "$description emits a compact module matrix" "expected: $expected\nactual: $output"
expected_matrix=$'100\n010\n001'
if [[ $with_meta == "true" ]]; then
meta=$(head -n1 <<<"$output")
matrix=$(tail -n +2 <<<"$output")
# The meta line leads with the shared interface, security, and SSID. With
# no interface argument the helper detects one from the live host, so that
# field is only pinned when the case pinned it.
expected_security=${expected_payload#WIFI:T:}
expected_security=${expected_security%%;*}
expected_ssid=$(head -n1 <<<"$fields")
[[ $meta == meta$'\t'$expected_iface$'\t'"$expected_security"$'\t'"$expected_ssid" ]] \
|| fail "$description leads with the interface, security, and SSID" "actual: $meta"
else
matrix=$output
fi
[[ $matrix == "$expected_matrix" ]] || fail "$description emits a compact module matrix" "expected: $expected_matrix\nactual: $matrix"
payload=$(<"$QR_PAYLOAD_FILE")
[[ $payload == "$expected_payload" ]] || fail "$description generates the Wi-Fi payload" "expected: $expected_payload\nactual: $payload"
@@ -50,25 +71,34 @@ run_success_case \
"network QR helper escapes WPA credentials through stdin" \
$'Cafe;Guest\\5G\nwpa-psk\np,a:ss;word\\42\nno\n' \
'WIFI:T:WPA;S:Cafe\;Guest\\5G;P:p\,a\:ss\;word\\42;;' \
--meta wlan0
# Without --meta the output stays a bare matrix, which pre-plugin clones of
# the network widget still parse.
run_success_case \
"network QR helper keeps the bare matrix without --meta" \
$'Cafe;Guest\\5G\nwpa-psk\np,a:ss;word\\42\nno\n' \
'WIFI:T:WPA;S:Cafe\;Guest\\5G;P:p\,a\:ss\;word\\42;;' \
wlan0
# With no interface argument the helper finds the connected Wi-Fi device.
run_success_case \
"network QR helper detects the Wi-Fi interface" \
$'Cafe Detected\nwpa-psk\nsecret\nno\n' \
'WIFI:T:WPA;S:Cafe Detected;P:secret;;'
'WIFI:T:WPA;S:Cafe Detected;P:secret;;' \
--meta
run_success_case \
"network QR helper supports open networks" \
$'Cafe Open\nnone\n\nno\n' \
'WIFI:T:nopass;S:Cafe Open;P:;;' \
wlan0
--meta wlan0
run_success_case \
"network QR helper marks hidden networks" \
$'Hidden Network\nwpa-psk\nsecret\nyes\n' \
'WIFI:T:WPA;S:Hidden Network;P:secret;H:true;;' \
wlan0
--meta wlan0
# NetworkManager models WEP as key-mgmt "none" plus a wep-key, which must not
# be mistaken for an open network.
@@ -76,7 +106,7 @@ run_success_case \
"network QR helper encodes WEP networks" \
$'Old Router\nnone\n\nno\nwep-secret\n' \
'WIFI:T:WEP;S:Old Router;P:wep-secret;;' \
wlan0
--meta wlan0
export QR_NMCLI_FIELDS=$'Enterprise\nwpa-eap\nsecret\nno\n'
export QR_PAYLOAD_FILE="$tmp/enterprise-payload"
-9
View File
@@ -105,15 +105,6 @@ assertDeepEqual(rows.map(row => row.ssid), ['Connected', 'Known', 'Open'], 'netw
assertEqual(network.wifiSectionTitle(rows, 0), 'KNOWN NETWORKS', 'network labels known wifi section')
assertEqual(network.wifiSectionTitle(rows, 2), 'OTHER NETWORKS', 'network labels other wifi section')
assertDeepEqual(
network.parseQrMatrix('010\n111\n010\n'),
{ rows: ['010', '111', '010'], size: 3 },
'network parses a square QR matrix'
)
assertDeepEqual(network.parseQrMatrix('01\n111\n'), { rows: [], size: 0 }, 'network rejects ragged QR rows')
assertDeepEqual(network.parseQrMatrix('010\n101\n'), { rows: [], size: 0 }, 'network rejects a non-square QR matrix')
assertDeepEqual(network.parseQrMatrix('010\n1x1\n010\n'), { rows: [], size: 0 }, 'network rejects invalid QR modules')
const reasons = { NoSecrets: 1, WifiAuthTimeout: 2, WifiNetworkLost: 3, WifiClientDisconnected: 4, WifiClientFailed: 5 }
assertEqual(network.networkFailureReason(1, reasons), 'Passphrase required', 'network maps missing passphrase failures')
assertEqual(network.networkFailureReason(2, reasons), 'Wrong password', 'network maps auth timeout failures')
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
run_node_test <<'JS'
const wifiqr = requireFromRoot('shell/plugins/panels/wifiqr/Model.js')
assertDeepEqual(
wifiqr.parseQrOutput('meta\twlan0\tWPA\tCafe WiFi\n010\n111\n010\n'),
{ meta: { iface: 'wlan0', security: 'WPA', ssid: 'Cafe WiFi' }, matrix: { rows: ['010', '111', '010'], size: 3 } },
'wifiqr parses the meta header and a square matrix'
)
assertDeepEqual(
wifiqr.parseQrOutput('meta\twlan0\tnopass\tTab\tName\n010\n111\n010\n').meta.ssid,
'Tab\tName',
'wifiqr keeps tabs inside the SSID field'
)
assertDeepEqual(
wifiqr.parseQrOutput('010\n111\n010\n'),
{ meta: { iface: '', security: '', ssid: '' }, matrix: { rows: ['010', '111', '010'], size: 3 } },
'wifiqr tolerates output without a meta header'
)
assertDeepEqual(wifiqr.parseQrOutput('meta\twlan0\tWPA\tCafe\n01\n111\n').matrix, { rows: [], size: 0 }, 'wifiqr rejects ragged QR rows')
assertDeepEqual(wifiqr.parseQrOutput('010\n101\n').matrix, { rows: [], size: 0 }, 'wifiqr rejects a non-square QR matrix')
assertDeepEqual(wifiqr.parseQrOutput('010\n1x1\n010\n').matrix, { rows: [], size: 0 }, 'wifiqr rejects invalid QR modules')
JS