|
|
@@ -154,8 +154,8 @@ Panel {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Enter/Space on the highlighted row. Mirrors row-click semantics:
|
|
|
|
// Enter/Space on the highlighted row. Mirrors row-click semantics:
|
|
|
|
// connected → disconnect, protected-unknown → password prompt (via
|
|
|
|
// connected → disconnect, protected-unknown → password prompt,
|
|
|
|
// known-network probe), open/known → connect.
|
|
|
|
// open/known → connect.
|
|
|
|
function activateSelected() {
|
|
|
|
function activateSelected() {
|
|
|
|
if (busy || selectedIndex < 0 || selectedIndex >= wifiNetworks.length) return
|
|
|
|
if (busy || selectedIndex < 0 || selectedIndex >= wifiNetworks.length) return
|
|
|
|
var net = wifiNetworks[selectedIndex]
|
|
|
|
var net = wifiNetworks[selectedIndex]
|
|
|
@@ -297,6 +297,7 @@ Panel {
|
|
|
|
for (var i = 0; i < networks.length; i++) {
|
|
|
|
for (var i = 0; i < networks.length; i++) {
|
|
|
|
var network = networks[i]
|
|
|
|
var network = networks[i]
|
|
|
|
if (!network) continue
|
|
|
|
if (!network) continue
|
|
|
|
|
|
|
|
checkActionCompletion(network)
|
|
|
|
var isConnected = network.connected
|
|
|
|
var isConnected = network.connected
|
|
|
|
var ssid = network.name || ""
|
|
|
|
var ssid = network.name || ""
|
|
|
|
if (isConnected && ssid !== root.actionSsid) continue // Skip the connected network so it doesn't appear in the list, unless we are currently trying to connect to it
|
|
|
|
if (isConnected && ssid !== root.actionSsid) continue // Skip the connected network so it doesn't appear in the list, unless we are currently trying to connect to it
|
|
|
@@ -351,81 +352,81 @@ Panel {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function isProtected(security) {
|
|
|
|
function isProtected(security) {
|
|
|
|
var s = String(security || "").toLowerCase()
|
|
|
|
return security !== WifiSecurityType.Open
|
|
|
|
return s !== "" && s !== "open"
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function runAction(kind, ssid, command) {
|
|
|
|
function networkForSsid(ssid) {
|
|
|
|
if (actionProc.running) return
|
|
|
|
var networks = wifiNetworkObjects || []
|
|
|
|
|
|
|
|
for (var i = 0; i < networks.length; i++) {
|
|
|
|
|
|
|
|
if (networks[i] && networks[i].name === ssid) return networks[i]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return null
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function runNetworkAction(kind, network, callback) {
|
|
|
|
|
|
|
|
if (actionKind !== "" || !network) return
|
|
|
|
|
|
|
|
var ssid = network.name || ""
|
|
|
|
actionSsid = ssid
|
|
|
|
actionSsid = ssid
|
|
|
|
actionKind = kind
|
|
|
|
actionKind = kind
|
|
|
|
failureSsid = ""
|
|
|
|
failureSsid = ""
|
|
|
|
failureReason = ""
|
|
|
|
failureReason = ""
|
|
|
|
actionProc.command = ["bash", "-c", command]
|
|
|
|
callback(network)
|
|
|
|
actionProc.running = true
|
|
|
|
|
|
|
|
// Safety net: if onExited never fires (process death, signal handler
|
|
|
|
// Safety net: if onExited never fires (process death, signal handler
|
|
|
|
// throws, etc.), clear the busy state so the row doesn't get stuck on
|
|
|
|
// throws, etc.), clear the busy state so the row doesn't get stuck on
|
|
|
|
// "Connecting…" / "Disconnecting…" forever.
|
|
|
|
// "Connecting…" / "Disconnecting…" forever.
|
|
|
|
actionTimeout.restart()
|
|
|
|
actionTimeout.restart()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function clearNetworkAction() {
|
|
|
|
|
|
|
|
actionTimeout.stop()
|
|
|
|
|
|
|
|
if (actionKind === "connect") passwordSsid = ""
|
|
|
|
|
|
|
|
failureSsid = ""
|
|
|
|
|
|
|
|
failureReason = ""
|
|
|
|
|
|
|
|
actionSsid = ""
|
|
|
|
|
|
|
|
actionKind = ""
|
|
|
|
|
|
|
|
refresh()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function failNetworkAction(network, reason) {
|
|
|
|
|
|
|
|
if (!network || actionKind === "" || actionSsid !== (network.name || "")) return
|
|
|
|
|
|
|
|
actionTimeout.stop()
|
|
|
|
|
|
|
|
failureSsid = actionSsid
|
|
|
|
|
|
|
|
failureReason = networkFailureReason(reason)
|
|
|
|
|
|
|
|
actionSsid = ""
|
|
|
|
|
|
|
|
actionKind = ""
|
|
|
|
|
|
|
|
refresh()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function networkFailureReason(reason) {
|
|
|
|
|
|
|
|
if (reason === ConnectionFailReason.NoSecrets) return "Passphrase required"
|
|
|
|
|
|
|
|
if (reason === ConnectionFailReason.WifiAuthTimeout) return "Wrong password"
|
|
|
|
|
|
|
|
if (reason === ConnectionFailReason.WifiNetworkLost) return "Network lost"
|
|
|
|
|
|
|
|
if (reason === ConnectionFailReason.WifiClientDisconnected) return "Disconnected"
|
|
|
|
|
|
|
|
if (reason === ConnectionFailReason.WifiClientFailed) return "Connection failed"
|
|
|
|
|
|
|
|
return "Failed to connect"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function checkActionCompletion(network) {
|
|
|
|
|
|
|
|
if (!network || actionKind === "" || actionSsid !== (network.name || "")) return
|
|
|
|
|
|
|
|
if (actionKind === "connect" && network.connected) clearNetworkAction()
|
|
|
|
|
|
|
|
else if (actionKind === "disconnect" && !network.connected && !network.stateChanging) clearNetworkAction()
|
|
|
|
|
|
|
|
else if (actionKind === "forget" && !network.known && !network.stateChanging) clearNetworkAction()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function connectKnown(ssid) {
|
|
|
|
function connectKnown(ssid) {
|
|
|
|
var quotedSsid = Util.shellQuote(ssid)
|
|
|
|
runNetworkAction("connect", networkForSsid(ssid), function(network) { network.connect() })
|
|
|
|
runAction("connect", ssid, `
|
|
|
|
|
|
|
|
station=$(iwctl station list 2>/dev/null | sed -e 's/\\x1b\\[[0-9;]*m//g' | awk '/^[[:space:]]*wl/ { print $1; exit }')
|
|
|
|
|
|
|
|
[[ -z $station ]] && { echo "no Wi-Fi station available" >&2; exit 1; }
|
|
|
|
|
|
|
|
iwctl --dont-ask station "$station" connect ${quotedSsid}
|
|
|
|
|
|
|
|
`)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function connectWithPassphrase(ssid, passphrase) {
|
|
|
|
function connectWithPassphrase(ssid, passphrase) {
|
|
|
|
var quotedSsid = Util.shellQuote(ssid)
|
|
|
|
runNetworkAction("connect", networkForSsid(ssid), function(network) { network.connectWithPsk(passphrase) })
|
|
|
|
var quotedPass = Util.shellQuote(passphrase)
|
|
|
|
|
|
|
|
runAction("connect", ssid, `
|
|
|
|
|
|
|
|
station=$(iwctl station list 2>/dev/null | sed -e 's/\\x1b\\[[0-9;]*m//g' | awk '/^[[:space:]]*wl/ { print $1; exit }')
|
|
|
|
|
|
|
|
[[ -z $station ]] && { echo "No Wi-Fi station available" >&2; exit 1; }
|
|
|
|
|
|
|
|
output=$(iwctl --passphrase ${quotedPass} station "$station" connect ${quotedSsid} 2>&1)
|
|
|
|
|
|
|
|
exit_code=$?
|
|
|
|
|
|
|
|
if [[ $exit_code -ne 0 ]]; then
|
|
|
|
|
|
|
|
echo "$output" | sed -e 's/\\x1b\\[[0-9;]*m//g' >&2
|
|
|
|
|
|
|
|
exit $exit_code
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
`)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function disconnect(ssid) {
|
|
|
|
function disconnect(network) {
|
|
|
|
runAction("disconnect", ssid, `
|
|
|
|
runNetworkAction("disconnect", network || connectedWifiNetwork, function(net) { net.disconnect() })
|
|
|
|
station=$(iwctl station list 2>/dev/null | sed -e 's/\\x1b\\[[0-9;]*m//g' | awk '/^[[:space:]]*wl/ { print $1; exit }')
|
|
|
|
|
|
|
|
[[ -z $station ]] && { echo "no Wi-Fi station available" >&2; exit 1; }
|
|
|
|
|
|
|
|
iwctl station "$station" disconnect
|
|
|
|
|
|
|
|
`)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// iwd doesn't reliably tear down an active connection when you forget the
|
|
|
|
function forget(net) {
|
|
|
|
// network underneath it, so if the station is currently on this SSID we
|
|
|
|
runNetworkAction("forget", net ? net.network : null, function(network) { network.forget() })
|
|
|
|
// disconnect first and bail on failure rather than reporting a misleading
|
|
|
|
|
|
|
|
// success. If the station isn't on this SSID (or there is no station),
|
|
|
|
|
|
|
|
// skip straight to forget.
|
|
|
|
|
|
|
|
function forget(ssid) {
|
|
|
|
|
|
|
|
var quotedSsid = Util.shellQuote(ssid)
|
|
|
|
|
|
|
|
runAction("forget", ssid, `
|
|
|
|
|
|
|
|
station=$(iwctl station list 2>/dev/null | sed -e 's/\\x1b\\[[0-9;]*m//g' | awk '/^[[:space:]]*wl/ { print $1; exit }')
|
|
|
|
|
|
|
|
if [[ -n $station ]]; then
|
|
|
|
|
|
|
|
current=$(iwctl station "$station" show 2>/dev/null \
|
|
|
|
|
|
|
|
| sed -e 's/\\x1b\\[[0-9;]*m//g' \
|
|
|
|
|
|
|
|
| awk '/Connected network/ {
|
|
|
|
|
|
|
|
s = $0
|
|
|
|
|
|
|
|
sub(/.*Connected network[[:space:]]+/, "", s)
|
|
|
|
|
|
|
|
sub(/[[:space:]]+$/, "", s)
|
|
|
|
|
|
|
|
print s
|
|
|
|
|
|
|
|
exit
|
|
|
|
|
|
|
|
}')
|
|
|
|
|
|
|
|
if [[ $current == ${quotedSsid} ]]; then
|
|
|
|
|
|
|
|
iwctl station "$station" disconnect || { echo "failed to disconnect before forget" >&2; exit 1; }
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
iwctl known-networks ${quotedSsid} forget
|
|
|
|
|
|
|
|
`)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
implicitWidth: button.implicitWidth
|
|
|
|
implicitWidth: button.implicitWidth
|
|
|
@@ -471,17 +472,23 @@ fi
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Wi-Fi scan via iwctl. Emits a STATION_AVAILABLE marker followed by TSV
|
|
|
|
Timer {
|
|
|
|
// rows (connected, ssid, signal_pct, security). Strip ANSI escapes early —
|
|
|
|
id: scanRestart
|
|
|
|
// iwctl's table layout starts each row with one, which breaks naive parsing.
|
|
|
|
interval: 100
|
|
|
|
Process {
|
|
|
|
repeat: false
|
|
|
|
id: wifiProc
|
|
|
|
onTriggered: {
|
|
|
|
stdout: StdioCollector {
|
|
|
|
if (root.wifiDevice) root.wifiDevice.scannerEnabled = true
|
|
|
|
waitForEnd: true
|
|
|
|
scanDone.start()
|
|
|
|
onStreamFinished: root.updateWifi(text)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Timer {
|
|
|
|
|
|
|
|
id: scanDone
|
|
|
|
|
|
|
|
interval: 1500
|
|
|
|
|
|
|
|
repeat: false
|
|
|
|
|
|
|
|
onTriggered: root.syncWifiNetworks()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Process {
|
|
|
|
Process {
|
|
|
|
id: dnsProc
|
|
|
|
id: dnsProc
|
|
|
|
stdout: StdioCollector {
|
|
|
|
stdout: StdioCollector {
|
|
|
@@ -490,64 +497,22 @@ fi
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Action runner for connect/disconnect/forget and DNS provider changes.
|
|
|
|
// Action runner for DNS provider changes. Wi-Fi actions use the
|
|
|
|
// Streams stderr for wifi actions so we can surface "Operation failed" or
|
|
|
|
// Quickshell.Networking NetworkManager backend directly.
|
|
|
|
// "Invalid passphrase" inline rather than dropping the user back to a
|
|
|
|
|
|
|
|
// silent UI. setDns() and runAction() both gate on `actionProc.running`,
|
|
|
|
|
|
|
|
// so the two flows can't overlap on this shared process.
|
|
|
|
|
|
|
|
Process {
|
|
|
|
Process {
|
|
|
|
id: actionProc
|
|
|
|
id: actionProc
|
|
|
|
stdout: StdioCollector { id: actionStdout; waitForEnd: true }
|
|
|
|
stdout: StdioCollector { id: actionStdout; waitForEnd: true }
|
|
|
|
stderr: StdioCollector { id: actionStderr; waitForEnd: true }
|
|
|
|
stderr: StdioCollector { id: actionStderr; waitForEnd: true }
|
|
|
|
onExited: function(exitCode) {
|
|
|
|
onExited: function(exitCode) {
|
|
|
|
// DNS change finished — pendingDnsProvider is the in-flight marker
|
|
|
|
|
|
|
|
// for that flow (setDns doesn't touch actionKind), so handle it and
|
|
|
|
|
|
|
|
// return before the wifi-action path.
|
|
|
|
|
|
|
|
if (root.pendingDnsProvider !== "") {
|
|
|
|
if (root.pendingDnsProvider !== "") {
|
|
|
|
if (exitCode === 0) root.dnsProvider = root.pendingDnsProvider
|
|
|
|
if (exitCode === 0) root.dnsProvider = root.pendingDnsProvider
|
|
|
|
root.pendingDnsProvider = ""
|
|
|
|
root.pendingDnsProvider = ""
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Timeout already cleared our state and killed us — the exit signal
|
|
|
|
|
|
|
|
// is stale, don't clobber whatever the user has done since.
|
|
|
|
|
|
|
|
if (root.actionKind === "") return
|
|
|
|
|
|
|
|
actionTimeout.stop()
|
|
|
|
|
|
|
|
var ssid = root.actionSsid
|
|
|
|
|
|
|
|
var kind = root.actionKind
|
|
|
|
|
|
|
|
if (exitCode === 0) {
|
|
|
|
|
|
|
|
if (kind === "connect") root.passwordSsid = ""
|
|
|
|
|
|
|
|
root.failureSsid = ""
|
|
|
|
|
|
|
|
root.failureReason = ""
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
root.failureSsid = ssid
|
|
|
|
|
|
|
|
var reason = (actionStderr.text || actionStdout.text || "").trim()
|
|
|
|
|
|
|
|
if (!reason) {
|
|
|
|
|
|
|
|
if (kind === "connect") reason = "Failed to connect"
|
|
|
|
|
|
|
|
else if (kind === "disconnect") reason = "Failed to disconnect"
|
|
|
|
|
|
|
|
else reason = "Failed to forget"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Squash multi-line iwctl errors into a single readable line.
|
|
|
|
|
|
|
|
// Also strip bash script error prefixes like "bash: line 4: " and "Operation failed"
|
|
|
|
|
|
|
|
var finalReason = reason.split("\n").pop().replace(/^bash: line \d+: /, "").replace(/^Operation failed/, "").trim()
|
|
|
|
|
|
|
|
if (!finalReason) {
|
|
|
|
|
|
|
|
if (kind === "connect") finalReason = "Failed to connect"
|
|
|
|
|
|
|
|
else if (kind === "disconnect") finalReason = "Failed to disconnect"
|
|
|
|
|
|
|
|
else finalReason = "Failed to forget"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
root.failureReason = finalReason
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
root.actionSsid = ""
|
|
|
|
|
|
|
|
root.actionKind = ""
|
|
|
|
|
|
|
|
root.refresh()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Poll detailsProc while the panel is open. `iwctl connect` returns
|
|
|
|
// Poll details while the panel is open so the IP/route header catches up
|
|
|
|
// success the moment iwd accepts credentials — the IP/route isn't
|
|
|
|
// as soon as NetworkManager finishes activating a connection.
|
|
|
|
// actually assigned until a beat later, so a single post-action refresh
|
|
|
|
|
|
|
|
// races against routing and the header stays blank. Polling fills the
|
|
|
|
|
|
|
|
// details in as soon as the route comes up; cheap since the script is
|
|
|
|
|
|
|
|
// small and only runs while the panel is visible.
|
|
|
|
|
|
|
|
Timer {
|
|
|
|
Timer {
|
|
|
|
id: detailsPoll
|
|
|
|
id: detailsPoll
|
|
|
|
interval: 1500
|
|
|
|
interval: 1500
|
|
|
@@ -566,13 +531,10 @@ fi
|
|
|
|
if (root.actionKind === "connect") reason = "Timed out connecting"
|
|
|
|
if (root.actionKind === "connect") reason = "Timed out connecting"
|
|
|
|
else if (root.actionKind === "disconnect") reason = "Timed out disconnecting"
|
|
|
|
else if (root.actionKind === "disconnect") reason = "Timed out disconnecting"
|
|
|
|
else reason = "Timed out forgetting"
|
|
|
|
else reason = "Timed out forgetting"
|
|
|
|
// Clear state *before* killing the process so the eventual onExited
|
|
|
|
|
|
|
|
// sees actionKind === "" and bails out as stale.
|
|
|
|
|
|
|
|
root.failureSsid = root.actionSsid
|
|
|
|
root.failureSsid = root.actionSsid
|
|
|
|
root.failureReason = reason
|
|
|
|
root.failureReason = reason
|
|
|
|
root.actionSsid = ""
|
|
|
|
root.actionSsid = ""
|
|
|
|
root.actionKind = ""
|
|
|
|
root.actionKind = ""
|
|
|
|
if (actionProc.running) actionProc.running = false // SIGTERM
|
|
|
|
|
|
|
|
root.refresh()
|
|
|
|
root.refresh()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -693,9 +655,9 @@ fi
|
|
|
|
foreground: root.bar.foreground
|
|
|
|
foreground: root.bar.foreground
|
|
|
|
hoverColor: root.bar.foreground // Override the dimming behavior
|
|
|
|
hoverColor: root.bar.foreground // Override the dimming behavior
|
|
|
|
fontFamily: root.bar.fontFamily
|
|
|
|
fontFamily: root.bar.fontFamily
|
|
|
|
enabled: true
|
|
|
|
enabled: root.networkManagerAvailable
|
|
|
|
onClicked: {
|
|
|
|
onClicked: {
|
|
|
|
root.bar.run("rfkill toggle wlan")
|
|
|
|
Networking.wifiEnabled = !Networking.wifiEnabled
|
|
|
|
Qt.callLater(function() { root.refresh(true) })
|
|
|
|
Qt.callLater(function() { root.refresh(true) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -756,7 +718,7 @@ fi
|
|
|
|
root.focusSection = "header"
|
|
|
|
root.focusSection = "header"
|
|
|
|
root.headerIndex = 0
|
|
|
|
root.headerIndex = 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
onClicked: root.disconnect(root.info.ssid)
|
|
|
|
onClicked: root.disconnect(root.connectedWifiNetwork)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Button {
|
|
|
|
Button {
|
|
|
@@ -974,7 +936,7 @@ fi
|
|
|
|
|
|
|
|
|
|
|
|
readonly property bool isConnected: net && net.connected
|
|
|
|
readonly property bool isConnected: net && net.connected
|
|
|
|
readonly property bool isKnown: !!(net && net.known)
|
|
|
|
readonly property bool isKnown: !!(net && net.known)
|
|
|
|
readonly property bool isProtected: root.isProtected(net ? net.security : "")
|
|
|
|
readonly property bool isProtected: net ? root.isProtected(net.security) : false
|
|
|
|
readonly property bool canForget: isConnected || isKnown
|
|
|
|
readonly property bool canForget: isConnected || isKnown
|
|
|
|
readonly property bool isSelected: root.focusSection === "wifi" && root.selectedIndex === index
|
|
|
|
readonly property bool isSelected: root.focusSection === "wifi" && root.selectedIndex === index
|
|
|
|
|
|
|
|
|
|
|
@@ -989,6 +951,23 @@ fi
|
|
|
|
readonly property bool isFailed: root.failureReason !== "" && root.failureSsid === (net ? net.ssid : "")
|
|
|
|
readonly property bool isFailed: root.failureReason !== "" && root.failureSsid === (net ? net.ssid : "")
|
|
|
|
readonly property bool isPasswordOpen: root.passwordSsid !== "" && root.passwordSsid === (net ? net.ssid : "")
|
|
|
|
readonly property bool isPasswordOpen: root.passwordSsid !== "" && root.passwordSsid === (net ? net.ssid : "")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Connections {
|
|
|
|
|
|
|
|
target: row.net ? row.net.network : null
|
|
|
|
|
|
|
|
function onConnectionFailed(reason) {
|
|
|
|
|
|
|
|
root.failNetworkAction(row.net.network, reason)
|
|
|
|
|
|
|
|
if (reason === ConnectionFailReason.NoSecrets) root.passwordSsid = row.net.ssid
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function onConnectedChanged() {
|
|
|
|
|
|
|
|
if (row.net) root.checkActionCompletion(row.net.network)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function onKnownChanged() {
|
|
|
|
|
|
|
|
if (row.net) root.checkActionCompletion(row.net.network)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function onStateChangingChanged() {
|
|
|
|
|
|
|
|
if (row.net) root.checkActionCompletion(row.net.network)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
readonly property string statusText: {
|
|
|
|
readonly property string statusText: {
|
|
|
|
if (!net) return ""
|
|
|
|
if (!net) return ""
|
|
|
|
if (isPasswordOpen) return ""
|
|
|
|
if (isPasswordOpen) return ""
|
|
|
@@ -1033,28 +1012,11 @@ fi
|
|
|
|
root.focusSection = "wifi"
|
|
|
|
root.focusSection = "wifi"
|
|
|
|
root.selectedIndex = row.index
|
|
|
|
root.selectedIndex = row.index
|
|
|
|
if (row.isConnected) {
|
|
|
|
if (row.isConnected) {
|
|
|
|
root.disconnect(row.net.ssid)
|
|
|
|
root.disconnect(row.net.network)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (row.isProtected && !row.isKnown) {
|
|
|
|
if (row.isProtected && !row.isKnown) {
|
|
|
|
// Unknown protected network: probe iwd before expanding the inline
|
|
|
|
root.passwordSsid = row.net.ssid
|
|
|
|
// password prompt for this row. Stash the SSID as a string — if we
|
|
|
|
|
|
|
|
// held a reference to the row delegate it could be destroyed by a
|
|
|
|
|
|
|
|
// model refresh, and a rapid second click would overwrite it and
|
|
|
|
|
|
|
|
// misroute the first result.
|
|
|
|
|
|
|
|
var quotedSsid = Util.shellQuote(row.net.ssid)
|
|
|
|
|
|
|
|
knownCheck.targetSsid = row.net.ssid
|
|
|
|
|
|
|
|
knownCheck.command = ["bash", "-c", `
|
|
|
|
|
|
|
|
iwctl known-networks list 2>/dev/null \\
|
|
|
|
|
|
|
|
| sed -e 's/\\x1b\\[[0-9;]*m//g' \\
|
|
|
|
|
|
|
|
| awk -v s=${quotedSsid} 'NR > 3 {
|
|
|
|
|
|
|
|
line = $0
|
|
|
|
|
|
|
|
sub(/^[[:space:]]+/, "", line)
|
|
|
|
|
|
|
|
sub(/[[:space:]]+$/, "", line)
|
|
|
|
|
|
|
|
n = split(line, p, /[[:space:]]{2,}/)
|
|
|
|
|
|
|
|
if (n >= 1 && p[1] == s) { print "yes"; exit }
|
|
|
|
|
|
|
|
}'`]
|
|
|
|
|
|
|
|
knownCheck.running = true
|
|
|
|
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
root.connectKnown(row.net.ssid)
|
|
|
|
root.connectKnown(row.net.ssid)
|
|
|
@@ -1092,7 +1054,7 @@ iwctl known-networks list 2>/dev/null \\
|
|
|
|
foreground: root.bar.foreground
|
|
|
|
foreground: root.bar.foreground
|
|
|
|
hoverColor: root.bar.urgent
|
|
|
|
hoverColor: root.bar.urgent
|
|
|
|
fontFamily: root.bar.fontFamily
|
|
|
|
fontFamily: root.bar.fontFamily
|
|
|
|
onClicked: if (row.net) root.forget(row.net.ssid)
|
|
|
|
onClicked: if (row.net) root.forget(row.net)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Shows a lock glyph for protected disconnected networks at the far
|
|
|
|
// Shows a lock glyph for protected disconnected networks at the far
|
|
|
@@ -1239,27 +1201,6 @@ iwctl known-networks list 2>/dev/null \\
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// One-shot probe: is the just-clicked SSID in iwd's known-networks?
|
|
|
|
|
|
|
|
// If so, skip the passphrase prompt and connect directly. We hold an SSID
|
|
|
|
|
|
|
|
// string (not a row delegate) so a model refresh during the probe can't
|
|
|
|
|
|
|
|
// leave us pointing at a destroyed object. Rows are globally disabled
|
|
|
|
|
|
|
|
// while `knownCheck.running`, so the SSID can't be overwritten mid-flight.
|
|
|
|
|
|
|
|
Process {
|
|
|
|
|
|
|
|
id: knownCheck
|
|
|
|
|
|
|
|
property string targetSsid: ""
|
|
|
|
|
|
|
|
stdout: StdioCollector {
|
|
|
|
|
|
|
|
id: knownStdout
|
|
|
|
|
|
|
|
waitForEnd: true
|
|
|
|
|
|
|
|
onStreamFinished: {
|
|
|
|
|
|
|
|
var ssid = knownCheck.targetSsid
|
|
|
|
|
|
|
|
knownCheck.targetSsid = ""
|
|
|
|
|
|
|
|
if (!ssid) return
|
|
|
|
|
|
|
|
if (text.indexOf("yes") !== -1) root.connectKnown(ssid)
|
|
|
|
|
|
|
|
else root.passwordSsid = ssid
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Poll the wifi/ethernet pill state every 3s. Local to this panel so
|
|
|
|
// Poll the wifi/ethernet pill state every 3s. Local to this panel so
|
|
|
|
// Bar.qml does not need to mirror network state.
|
|
|
|
// Bar.qml does not need to mirror network state.
|
|
|
|
Process {
|
|
|
|
Process {
|
|
|
|