Pins the active connection to 2.4/5/6GHz, or leaves the choice automatic.
The section only appears on Wi-Fi when the network answers on more than one
band, or while a pin is in force so it stays clearable.
bin/omarchy-network-band reports and sets the band. It sets NetworkManager's
802-11-wireless.band rather than pinning a BSSID: NM 1.44+ accepts a third
band value so 5 and 6GHz can be pinned apart, and a band survives an AP
rotating its BSSIDs while leaving roaming between APs intact. It refuses a
band the network does not answer on, and restores the previous setting if
reassociation fails rather than leaving the machine offline.
Under Automatic the pills collapse and the header reads the live band
("WI-FI BAND: 2.4GHZ"); pinning reveals them and the header goes plain. The
height is animated, and the section stays mounted through the reconnect a
band change causes -- otherwise `kind` briefly stops being "wifi" and the
whole segment would tear down and rebuild.
Two fixes to the same panel fall out of this:
- Every stat row stays mounted and reads "--" until it has data, instead of
appearing a beat after the panel opens and shoving the rows below down.
- The speed test's Run button is scaled to match the band header's controls
and joins the keyboard cursor chain.
ToggleSwitch gains a settable trackHeight so a compact placement can render a
genuinely small switch instead of scaling one down onto fractional pixels.
Defaults are unchanged.
Claude-Session: https://claude.ai/code/session_01XcKqYe1n5bnRBuAZwikwsr
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
125 lines
7.1 KiB
Bash
125 lines
7.1 KiB
Bash
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
|
|
|
run_node_test <<'JS'
|
|
const network = requireFromRoot('shell/plugins/panels/network/Model.js')
|
|
|
|
assertDeepEqual(
|
|
network.parseNetworkStatus('wifi\tCafe WiFi\t78\t5200\n'),
|
|
{ kind: 'wifi', label: 'Cafe WiFi', signalStrength: 78, frequency: '5200' },
|
|
'network parses bar status'
|
|
)
|
|
assertEqual(network.connectionIcon('wifi', 80), network.wifiIconFor(80), 'network maps wifi icon from signal')
|
|
assertEqual(network.formatHeaderSpeed('1000'), '1gbit', 'network formats gigabit speed')
|
|
assertEqual(network.formatHeaderSpeed('2500'), '2.5gbit', 'network formats fractional gigabit speed')
|
|
assertEqual(network.formatHeaderFreq('2462'), '2.4ghz', 'network formats 2.4GHz wifi band')
|
|
assertEqual(network.formatHeaderFreq('5200'), '5ghz', 'network formats 5GHz wifi band')
|
|
assertEqual(network.formatHeaderFreq('6455.0'), '6ghz', 'network formats 6GHz wifi band')
|
|
assertEqual(network.formatHeaderFreq('18300'), '18.3ghz', 'network falls back to exact GHz for unknown bands')
|
|
assertEqual(network.headerDetail({ type: 'ethernet', speed: '100' }), '100mbit', 'network header uses ethernet speed')
|
|
|
|
assertDeepEqual(
|
|
network.parseKeyValue('iface\twlan0\nrx_bytes\t100\ntx_bytes\t50\n'),
|
|
{ iface: 'wlan0', rx_bytes: '100', tx_bytes: '50' },
|
|
'network parses detail key values'
|
|
)
|
|
assertDeepEqual(
|
|
network.throughputState({ prevIface: '', prevSampleTime: 0 }, { iface: 'wlan0', rx_bytes: '100', tx_bytes: '50' }, 10),
|
|
{ prevIface: 'wlan0', prevRxBytes: 100, prevTxBytes: 50, prevSampleTime: 10, downloadRate: 0, uploadRate: 0 },
|
|
'network seeds throughput state on first sample'
|
|
)
|
|
assertDeepEqual(
|
|
network.throughputState({ prevIface: 'wlan0', prevRxBytes: 100, prevTxBytes: 50, prevSampleTime: 10 }, { iface: 'wlan0', rx_bytes: '300', tx_bytes: '90' }, 12),
|
|
{ prevIface: 'wlan0', prevRxBytes: 300, prevTxBytes: 90, prevSampleTime: 12, downloadRate: 100, uploadRate: 20 },
|
|
'network computes throughput deltas'
|
|
)
|
|
|
|
let ping = network.pingLatencyState(
|
|
{ pingIface: '', routerPingSamples: [], internetPingSamples: [] },
|
|
{ iface: 'wlan0', router_ping_ms: '2.0', internet_ping_ms: '20.0' },
|
|
4
|
|
)
|
|
assertDeepEqual(
|
|
ping,
|
|
{ pingIface: 'wlan0', routerPingSamples: [2], internetPingSamples: [20], routerPingLatency: 2, internetPingLatency: 20, internetPingPacketLoss: 0 },
|
|
'network seeds ping latency samples'
|
|
)
|
|
|
|
ping = network.pingLatencyState(ping, { iface: 'wlan0', router_ping_ms: '4.0', internet_ping_ms: '' }, 4)
|
|
assertDeepEqual(
|
|
ping,
|
|
{ pingIface: 'wlan0', routerPingSamples: [2, 4], internetPingSamples: [20, null], routerPingLatency: 3, internetPingLatency: 20, internetPingPacketLoss: 50 },
|
|
'network averages recent successful ping samples'
|
|
)
|
|
|
|
assertDeepEqual(
|
|
network.pingLatencyState(ping, { iface: 'eth0', router_ping_ms: '1.5', internet_ping_ms: '10.0' }, 4),
|
|
{ pingIface: 'eth0', routerPingSamples: [1.5], internetPingSamples: [10], routerPingLatency: 1.5, internetPingLatency: 10, internetPingPacketLoss: 0 },
|
|
'network resets ping samples when interface changes'
|
|
)
|
|
|
|
assertDeepEqual(
|
|
network.pingLatencyState(ping, { iface: 'wlan0', internet_ping_ms: '22.0' }, 4),
|
|
{ pingIface: 'wlan0', routerPingSamples: [], internetPingSamples: [20, null, 22], routerPingLatency: -1, internetPingLatency: 21, internetPingPacketLoss: 33 },
|
|
'network clears ping samples when a target is unavailable'
|
|
)
|
|
|
|
assertEqual(network.formatBytes(1536), '1.5 KB', 'network formats bytes')
|
|
assertEqual(network.formatRate(1536), '1.5 KB/s', 'network formats rates')
|
|
assertEqual(network.formatSpeedMbps('250.4'), '250 Mbps', 'network formats speed test results')
|
|
assertEqual(network.formatPingLatency('2.54'), '2.5 ms', 'network formats low ping with precision')
|
|
assertEqual(network.formatPingLatency('25.4'), '25 ms', 'network formats ping')
|
|
assertEqual(network.formatPingLatency(''), 'Timeout', 'network formats missing ping as timeout')
|
|
assertEqual(network.formatPingLatency(-1, false), '--', 'network holds the ping row before the first sample')
|
|
assertEqual(network.formatPingLatency('25.4', true), '25 ms', 'network formats ping once samples exist')
|
|
assertEqual(network.formatPingLatency('', true), 'Timeout', 'network still reports a timeout among real samples')
|
|
assertEqual(network.formatPacketLoss(2), '2%', 'network formats packet loss')
|
|
assertEqual(network.formatPacketLoss(0), '0%', 'network formats zero packet loss')
|
|
assertEqual(network.formatPacketLoss(0, false), '--', 'network holds the packet loss row before the first sample')
|
|
assertEqual(network.formatPacketLoss(0, true), '0%', 'network reports zero loss once samples exist')
|
|
|
|
const rows = network.sortWifiRows([
|
|
{ ssid: 'Open', connected: false, known: false, signal: 95 },
|
|
{ ssid: 'Known', connected: false, known: true, signal: 10 },
|
|
{ ssid: 'Connected', connected: true, known: true, signal: 20 }
|
|
])
|
|
assertDeepEqual(rows.map(row => row.ssid), ['Connected', 'Known', 'Open'], 'network sorts wifi rows by connection and known state')
|
|
assertEqual(network.wifiSectionTitle(rows, 0), 'KNOWN NETWORKS', 'network labels known wifi section')
|
|
assertEqual(network.wifiSectionTitle(rows, 2), 'OTHER NETWORKS', 'network labels other wifi section')
|
|
|
|
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')
|
|
assertEqual(network.networkFailureReason(99, reasons), 'Failed to connect', 'network maps unknown failures')
|
|
|
|
|
|
assertEqual(network.bandLabel('2.4'), '2.4ghz', 'network labels the 2.4GHz band')
|
|
assertEqual(network.bandLabel('6'), '6ghz', 'network labels the 6GHz band')
|
|
assertEqual(network.bandLabel('auto'), 'Auto', 'network labels the automatic band choice')
|
|
|
|
assertEqual(network.bandSectionTitle('auto', '2.4'), 'WI-FI BAND: 2.4GHZ', 'network names the live band in the header under automatic')
|
|
assertEqual(network.bandSectionTitle('auto', ''), 'WI-FI BAND', 'network omits an unknown band from the header')
|
|
assertEqual(network.bandSectionTitle('5', '5'), 'WI-FI BAND', 'network drops the header band once the pills are showing')
|
|
assertEqual(network.bandSectionTitle('5', '2.4'), 'WI-FI BAND', 'network keeps a plain header while a pin is settling')
|
|
|
|
assertDeepEqual(
|
|
network.parseBandStatus('band\t5\navailable\t2.4 5 6\nselected\tauto\n'),
|
|
{ band: '5', selected: 'auto', available: ['2.4', '5', '6'] },
|
|
'network parses band status'
|
|
)
|
|
assertDeepEqual(
|
|
network.parseBandStatus(''),
|
|
{ band: '', selected: 'auto', available: [] },
|
|
'network parses empty band status without a wifi connection'
|
|
)
|
|
|
|
|
|
|
|
assertEqual(network.headerDetail({ type: 'wifi', freq: '5745' }), '5ghz', 'network header shows the wifi band when the toggle is hidden')
|
|
assertEqual(network.headerDetail({ type: 'wifi', freq: '5745' }, true), '', 'network header drops the wifi band when the toggle shows it')
|
|
assertEqual(network.headerDetail({ type: 'ethernet', speed: '100' }, true), '100mbit', 'network header keeps ethernet speed regardless of the band toggle')
|
|
JS
|