Network/Wi-Fi: many fixes and robustness improvements
- proper detection when password is wrong - prevent a new connection while already connecting to a network - new mechanism to skip scan results if a new scan is incoming (avoid UI discrepancies)
This commit is contained in:
parent
4ba0f8d958
commit
ba33451957
2 changed files with 67 additions and 15 deletions
|
|
@ -397,6 +397,7 @@ NPanel {
|
||||||
}
|
}
|
||||||
outlined: !hovered
|
outlined: !hovered
|
||||||
fontSize: Style.fontSizeXS * scaling
|
fontSize: Style.fontSizeXS * scaling
|
||||||
|
enabled: !NetworkService.connecting
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (modelData.existing || modelData.cached || !NetworkService.isSecured(modelData.security)) {
|
if (modelData.existing || modelData.cached || !NetworkService.isSecured(modelData.security)) {
|
||||||
NetworkService.connect(modelData.ssid)
|
NetworkService.connect(modelData.ssid)
|
||||||
|
|
@ -461,7 +462,7 @@ NPanel {
|
||||||
onVisibleChanged: if (visible)
|
onVisibleChanged: if (visible)
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
if (text) {
|
if (text && !NetworkService.connecting) {
|
||||||
NetworkService.connect(passwordSsid, text)
|
NetworkService.connect(passwordSsid, text)
|
||||||
passwordSsid = ""
|
passwordSsid = ""
|
||||||
passwordInput = ""
|
passwordInput = ""
|
||||||
|
|
@ -481,7 +482,7 @@ NPanel {
|
||||||
NButton {
|
NButton {
|
||||||
text: "Connect"
|
text: "Connect"
|
||||||
fontSize: Style.fontSizeXXS * scaling
|
fontSize: Style.fontSizeXXS * scaling
|
||||||
enabled: passwordInput.length > 0
|
enabled: passwordInput.length > 0 && !NetworkService.connecting
|
||||||
outlined: true
|
outlined: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
NetworkService.connect(passwordSsid, passwordInput)
|
NetworkService.connect(passwordSsid, passwordInput)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ Singleton {
|
||||||
property string disconnectingFrom: ""
|
property string disconnectingFrom: ""
|
||||||
property string forgettingNetwork: ""
|
property string forgettingNetwork: ""
|
||||||
|
|
||||||
|
property bool ignoreScanResults: false
|
||||||
|
property bool scanPending: false
|
||||||
|
|
||||||
// Persistent cache
|
// Persistent cache
|
||||||
property string cacheFile: Settings.cacheDir + "network.json"
|
property string cacheFile: Settings.cacheDir + "network.json"
|
||||||
readonly property string cachedLastConnected: cacheAdapter.lastConnected
|
readonly property string cachedLastConnected: cacheAdapter.lastConnected
|
||||||
|
|
@ -95,11 +98,20 @@ Singleton {
|
||||||
}
|
}
|
||||||
|
|
||||||
function scan() {
|
function scan() {
|
||||||
if (scanning)
|
if (!Settings.data.network.wifiEnabled)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if (scanning) {
|
||||||
|
// Mark current scan results to be ignored and schedule a new scan
|
||||||
|
Logger.log("Network", "Scan already in progress, will ignore results and rescan")
|
||||||
|
ignoreScanResults = true
|
||||||
|
scanPending = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
scanning = true
|
scanning = true
|
||||||
lastError = ""
|
lastError = ""
|
||||||
|
ignoreScanResults = false
|
||||||
|
|
||||||
// Get existing profiles first, then scan
|
// Get existing profiles first, then scan
|
||||||
profileCheckProcess.running = true
|
profileCheckProcess.running = true
|
||||||
|
|
@ -247,13 +259,24 @@ Singleton {
|
||||||
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
|
if (root.ignoreScanResults) {
|
||||||
|
Logger.log("Network", "Ignoring profile check results (new scan requested)")
|
||||||
|
root.scanning = false
|
||||||
|
|
||||||
|
// Check if we need to start a new scan
|
||||||
|
if (root.scanPending) {
|
||||||
|
root.scanPending = false
|
||||||
|
delayedScanTimer.interval = 100
|
||||||
|
delayedScanTimer.restart()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const profiles = {}
|
const profiles = {}
|
||||||
const lines = text.split("\n").filter(l => l.trim())
|
const lines = text.split("\n").filter(l => l.trim())
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
profiles[line.trim()] = true
|
profiles[line.trim()] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.log("Network", "Got profiles", JSON.stringify(profiles))
|
|
||||||
scanProcess.existingProfiles = profiles
|
scanProcess.existingProfiles = profiles
|
||||||
scanProcess.running = true
|
scanProcess.running = true
|
||||||
}
|
}
|
||||||
|
|
@ -265,11 +288,24 @@ Singleton {
|
||||||
running: false
|
running: false
|
||||||
command: ["nmcli", "-t", "-f", "SSID,SECURITY,SIGNAL,IN-USE", "device", "wifi", "list", "--rescan", "yes"]
|
command: ["nmcli", "-t", "-f", "SSID,SECURITY,SIGNAL,IN-USE", "device", "wifi", "list", "--rescan", "yes"]
|
||||||
|
|
||||||
// Store existing profiles
|
|
||||||
property var existingProfiles: ({})
|
property var existingProfiles: ({})
|
||||||
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
|
if (root.ignoreScanResults) {
|
||||||
|
Logger.log("Network", "Ignoring scan results (new scan requested)")
|
||||||
|
root.scanning = false
|
||||||
|
|
||||||
|
// Check if we need to start a new scan
|
||||||
|
if (root.scanPending) {
|
||||||
|
root.scanPending = false
|
||||||
|
delayedScanTimer.interval = 100
|
||||||
|
delayedScanTimer.restart()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the scan results as before...
|
||||||
const lines = text.split("\n")
|
const lines = text.split("\n")
|
||||||
const networksMap = {}
|
const networksMap = {}
|
||||||
|
|
||||||
|
|
@ -358,9 +394,15 @@ Singleton {
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.log("Network", "Wi-Fi scan completed")
|
Logger.log("Network", "Wi-Fi scan completed")
|
||||||
Logger.log("Network", JSON.stringify(networksMap))
|
|
||||||
root.networks = networksMap
|
root.networks = networksMap
|
||||||
root.scanning = false
|
root.scanning = false
|
||||||
|
|
||||||
|
// Check if we need to start a new scan
|
||||||
|
if (root.scanPending) {
|
||||||
|
root.scanPending = false
|
||||||
|
delayedScanTimer.interval = 100
|
||||||
|
delayedScanTimer.restart()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,16 +411,14 @@ Singleton {
|
||||||
root.scanning = false
|
root.scanning = false
|
||||||
if (text.trim()) {
|
if (text.trim()) {
|
||||||
Logger.warn("Network", "Scan error: " + text)
|
Logger.warn("Network", "Scan error: " + text)
|
||||||
// If scan fails, set a short retry
|
|
||||||
if (Settings.data.network.wifiEnabled) {
|
// If scan fails, retry
|
||||||
delayedScanTimer.interval = 5000
|
delayedScanTimer.interval = 5000
|
||||||
delayedScanTimer.restart()
|
delayedScanTimer.restart()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: connectProcess
|
id: connectProcess
|
||||||
property string mode: "new"
|
property string mode: "new"
|
||||||
|
|
@ -400,6 +440,17 @@ Singleton {
|
||||||
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
|
// Check if the output actually indicates success
|
||||||
|
// nmcli outputs "Device '...' successfully activated" or "Connection successfully activated"
|
||||||
|
// on success. Empty output or other messages indicate failure.
|
||||||
|
const output = text.trim()
|
||||||
|
|
||||||
|
if (!output || (!output.includes("successfully activated") && !output.includes("Connection successfully"))) {
|
||||||
|
// No success message - likely an error occurred
|
||||||
|
// Don't update anything, let stderr handler deal with it
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Success - update cache
|
// Success - update cache
|
||||||
let known = cacheAdapter.knownNetworks
|
let known = cacheAdapter.knownNetworks
|
||||||
known[connectProcess.ssid] = {
|
known[connectProcess.ssid] = {
|
||||||
|
|
@ -474,7 +525,7 @@ Singleton {
|
||||||
Logger.warn("Network", "Disconnect error: " + text)
|
Logger.warn("Network", "Disconnect error: " + text)
|
||||||
}
|
}
|
||||||
// Still trigger a scan even on error
|
// Still trigger a scan even on error
|
||||||
delayedScanTimer.interval = 1000
|
delayedScanTimer.interval = 5000
|
||||||
delayedScanTimer.restart()
|
delayedScanTimer.restart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -545,7 +596,7 @@ Singleton {
|
||||||
Logger.warn("Network", "Forget error: " + text)
|
Logger.warn("Network", "Forget error: " + text)
|
||||||
}
|
}
|
||||||
// Still Trigger a scan even on error
|
// Still Trigger a scan even on error
|
||||||
delayedScanTimer.interval = 1000
|
delayedScanTimer.interval = 5000
|
||||||
delayedScanTimer.restart()
|
delayedScanTimer.restart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue