Network/WiFi: improve UI with more immediate feedback on operations.
+ proper deletion of profiles when forgetting a network
This commit is contained in:
parent
5bc8f410e7
commit
fc1ee9fb2f
2 changed files with 210 additions and 23 deletions
|
|
@ -15,6 +15,8 @@ Singleton {
|
|||
property string connectingTo: ""
|
||||
property string lastError: ""
|
||||
property bool ethernetConnected: false
|
||||
property string disconnectingFrom: ""
|
||||
property string forgettingNetwork: ""
|
||||
|
||||
// Persistent cache
|
||||
property string cacheFile: Settings.cacheDir + "network.json"
|
||||
|
|
@ -123,11 +125,14 @@ Singleton {
|
|||
}
|
||||
|
||||
function disconnect(ssid) {
|
||||
disconnectingFrom = ssid
|
||||
disconnectProcess.ssid = ssid
|
||||
disconnectProcess.running = true
|
||||
}
|
||||
|
||||
function forget(ssid) {
|
||||
forgettingNetwork = ssid
|
||||
|
||||
// Remove from cache
|
||||
let known = cacheAdapter.knownNetworks
|
||||
delete known[ssid]
|
||||
|
|
@ -144,6 +149,40 @@ Singleton {
|
|||
forgetProcess.running = true
|
||||
}
|
||||
|
||||
// Helper function to immediately update network status
|
||||
function updateNetworkStatus(ssid, connected) {
|
||||
let nets = networks
|
||||
|
||||
// Update all networks connected status
|
||||
for (let key in nets) {
|
||||
if (nets[key].connected && key !== ssid) {
|
||||
nets[key].connected = false
|
||||
}
|
||||
}
|
||||
|
||||
// Update the target network if it exists
|
||||
if (nets[ssid]) {
|
||||
nets[ssid].connected = connected
|
||||
nets[ssid].existing = true
|
||||
nets[ssid].cached = true
|
||||
} else if (connected) {
|
||||
// Create a temporary entry if network doesn't exist yet
|
||||
nets[ssid] = {
|
||||
"ssid": ssid,
|
||||
"security": "--",
|
||||
"signal": 100,
|
||||
"connected"// Default to good signal until real scan
|
||||
: true,
|
||||
"existing": true,
|
||||
"cached": true
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger property change notification
|
||||
networks = ({})
|
||||
networks = nets
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
function signalIcon(signal) {
|
||||
if (signal >= 80)
|
||||
|
|
@ -170,9 +209,9 @@ Singleton {
|
|||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const connected = text.split("\n").some(line => {
|
||||
const parts = line.split(":")
|
||||
return parts[1] === "ethernet" && parts[2] === "connected"
|
||||
})
|
||||
const parts = line.split(":")
|
||||
return parts[1] === "ethernet" && parts[2] === "connected"
|
||||
})
|
||||
if (root.ethernetConnected !== connected) {
|
||||
root.ethernetConnected = connected
|
||||
Logger.log("Network", "Ethernet connected:", root.ethernetConnected)
|
||||
|
|
@ -189,7 +228,7 @@ Singleton {
|
|||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const enabled = text.trim() === "enabled"
|
||||
Logger.log("Network", "Wifi enabled:", enabled)
|
||||
Logger.log("Network", "Wi-Fi enabled:", enabled)
|
||||
if (Settings.data.network.wifiEnabled !== enabled) {
|
||||
Settings.data.network.wifiEnabled = enabled
|
||||
}
|
||||
|
|
@ -229,11 +268,11 @@ Singleton {
|
|||
id: scanProcess
|
||||
running: false
|
||||
command: ["sh", "-c", `
|
||||
# Get existing profiles
|
||||
profiles=$(nmcli -t -f NAME,TYPE connection show | grep ':802-11-wireless' | cut -d: -f1)
|
||||
# Get list of saved connection profiles (just the names)
|
||||
profiles=$(nmcli -t -f NAME connection show | tr '\n' '|')
|
||||
|
||||
# Get WiFi networks
|
||||
nmcli -t -f SSID,SECURITY,SIGNAL,IN-USE device wifi list | while read line; do
|
||||
nmcli -t -f SSID,SECURITY,SIGNAL,IN-USE device wifi list --rescan yes | while read line; do
|
||||
ssid=$(echo "$line" | cut -d: -f1)
|
||||
security=$(echo "$line" | cut -d: -f2)
|
||||
signal=$(echo "$line" | cut -d: -f3)
|
||||
|
|
@ -244,8 +283,10 @@ Singleton {
|
|||
continue
|
||||
fi
|
||||
|
||||
# Check if SSID matches any profile name (simple check)
|
||||
# This covers most cases where profile name equals or contains the SSID
|
||||
existing=false
|
||||
if echo "$profiles" | grep -q "^$ssid$"; then
|
||||
if echo "$profiles" | grep -qF "$ssid|"; then
|
||||
existing=true
|
||||
fi
|
||||
|
||||
|
|
@ -288,12 +329,24 @@ Singleton {
|
|||
}
|
||||
}
|
||||
|
||||
if (JSON.stringify(root.networks) !== JSON.stringify(nets)) {
|
||||
Logger.log("Network", "Discovered", Object.keys(nets).length, "Wi-Fi networks")
|
||||
// For logging purpose only
|
||||
const oldSSIDs = Object.keys(root.networks)
|
||||
const newSSIDs = Object.keys(nets)
|
||||
const newNetworks = newSSIDs.filter(ssid => !oldSSIDs.includes(ssid))
|
||||
const lostNetworks = oldSSIDs.filter(ssid => !newSSIDs.includes(ssid))
|
||||
if (newNetworks.length > 0 || lostNetworks.length > 0) {
|
||||
if (newNetworks.length > 0) {
|
||||
Logger.log("Network", "New Wi-Fi SSID discovered:", newNetworks.join(", "))
|
||||
}
|
||||
if (lostNetworks.length > 0) {
|
||||
Logger.log("Network", "Wi-Fi SSID disappeared:", lostNetworks.join(", "))
|
||||
}
|
||||
Logger.log("Network", "Total Wi-Fi SSIDs:", Object.keys(nets).length)
|
||||
}
|
||||
|
||||
// Assign the results
|
||||
root.networks = nets
|
||||
root.scanning = false
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -343,11 +396,14 @@ Singleton {
|
|||
cacheAdapter.lastConnected = connectProcess.ssid
|
||||
saveCache()
|
||||
|
||||
// Immediately update the UI before scanning
|
||||
root.updateNetworkStatus(connectProcess.ssid, true)
|
||||
|
||||
root.connecting = false
|
||||
root.connectingTo = ""
|
||||
Logger.log("Network", "Connected to " + connectProcess.ssid)
|
||||
Logger.log("Network", `Connected to network: "${connectProcess.ssid}"`)
|
||||
|
||||
// Rescan to update status
|
||||
// Still do a scan to get accurate signal and security info
|
||||
delayedScanTimer.interval = 1000
|
||||
delayedScanTimer.restart()
|
||||
}
|
||||
|
|
@ -383,8 +439,27 @@ Singleton {
|
|||
running: false
|
||||
command: ["nmcli", "connection", "down", "id", ssid]
|
||||
|
||||
onRunningChanged: {
|
||||
if (!running) {
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
Logger.log("Network", `Disconnected from network: "${disconnectProcess.ssid}"`)
|
||||
|
||||
// Immediately update UI on successful disconnect
|
||||
root.updateNetworkStatus(disconnectProcess.ssid, false)
|
||||
root.disconnectingFrom = ""
|
||||
|
||||
// Do a scan to refresh the list
|
||||
delayedScanTimer.interval = 1000
|
||||
delayedScanTimer.restart()
|
||||
}
|
||||
}
|
||||
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: {
|
||||
root.disconnectingFrom = ""
|
||||
if (text.trim()) {
|
||||
Logger.warn("Network", "Disconnect error: " + text)
|
||||
}
|
||||
// Still trigger a scan even on error
|
||||
delayedScanTimer.interval = 1000
|
||||
delayedScanTimer.restart()
|
||||
}
|
||||
|
|
@ -395,11 +470,68 @@ Singleton {
|
|||
id: forgetProcess
|
||||
property string ssid: ""
|
||||
running: false
|
||||
command: ["nmcli", "connection", "delete", "id", ssid]
|
||||
|
||||
onRunningChanged: {
|
||||
if (!running) {
|
||||
delayedScanTimer.interval = 1000
|
||||
// Try multiple common profile name patterns
|
||||
command: ["sh", "-c", `
|
||||
ssid="$1"
|
||||
deleted=false
|
||||
|
||||
# Try exact SSID match first
|
||||
if nmcli connection delete id "$ssid" 2>/dev/null; then
|
||||
echo "Deleted profile: $ssid"
|
||||
deleted=true
|
||||
fi
|
||||
|
||||
# Try "Auto <SSID>" pattern
|
||||
if nmcli connection delete id "Auto $ssid" 2>/dev/null; then
|
||||
echo "Deleted profile: Auto $ssid"
|
||||
deleted=true
|
||||
fi
|
||||
|
||||
# Try "<SSID> 1", "<SSID> 2", etc. patterns
|
||||
for i in 1 2 3; do
|
||||
if nmcli connection delete id "$ssid $i" 2>/dev/null; then
|
||||
echo "Deleted profile: $ssid $i"
|
||||
deleted=true
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$deleted" = "false" ]; then
|
||||
echo "No profiles found for SSID: $ssid"
|
||||
fi
|
||||
`, "--", ssid]
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
Logger.log("Network", `Forget network: "${forgetProcess.ssid}"`)
|
||||
Logger.log("Network", text.trim().replace(/[\r\n]/g, " "))
|
||||
|
||||
// Update both cached and existing status immediately
|
||||
let nets = root.networks
|
||||
if (nets[forgetProcess.ssid]) {
|
||||
nets[forgetProcess.ssid].cached = false
|
||||
nets[forgetProcess.ssid].existing = false
|
||||
// Trigger property change
|
||||
root.networks = ({})
|
||||
root.networks = nets
|
||||
}
|
||||
|
||||
root.forgettingNetwork = ""
|
||||
|
||||
// Quick scan to verify the profile is gone
|
||||
delayedScanTimer.interval = 500
|
||||
delayedScanTimer.restart()
|
||||
}
|
||||
}
|
||||
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: {
|
||||
root.forgettingNetwork = ""
|
||||
if (text.trim() && !text.includes("No profiles found")) {
|
||||
Logger.warn("Network", "Forget error: " + text)
|
||||
}
|
||||
// Still Trigger a scan even on error
|
||||
delayedScanTimer.interval = 500
|
||||
delayedScanTimer.restart()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue