1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-26 22:42:50 -05:00

networking: improve wifi experience and bugs

This commit is contained in:
bbedward
2025-07-22 11:50:07 -04:00
parent a4da6921bd
commit 02bd9bbc72
7 changed files with 1166 additions and 395 deletions

View File

@@ -75,35 +75,7 @@ Singleton {
console.log("User prefers Ethernet, setting status to ethernet")
} else {
// Auto mode - check which interface has the default route
let priorityChecker = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["sh", "-c", "ip route show default | head -1 | cut -d\\\" \\\" -f5"]
running: true
stdout: SplitParser {
splitMarker: "\\n"
onRead: function(data) {
let defaultInterface = data.trim()
console.log("Default route interface:", defaultInterface)
// Check if the interface is wifi or ethernet
if (defaultInterface.startsWith("wl") || defaultInterface.includes("wifi")) {
root.networkStatus = "wifi"
console.log("WiFi interface has default route, setting status to wifi")
// Trigger WiFi SSID update
if (root.wifiEnabled) {
WifiService.updateCurrentWifiInfo()
}
} else if (defaultInterface.startsWith("en") || defaultInterface.includes("eth")) {
root.networkStatus = "ethernet"
console.log("Ethernet interface has default route, setting status to ethernet")
} else {
root.networkStatus = "disconnected"
console.log("Unknown interface type:", defaultInterface)
}
}
}
}
`, root)
defaultRouteChecker.running = true
}
} else if (hasWifi) {
root.networkStatus = "wifi"
@@ -157,6 +129,35 @@ Singleton {
}
}
Process {
id: defaultRouteChecker
command: ["sh", "-c", "ip route show default | head -1 | cut -d' ' -f5"]
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: function(data) {
let defaultInterface = data.trim()
console.log("Default route interface:", defaultInterface)
// Check if the interface is wifi or ethernet
if (defaultInterface.startsWith("wl") || defaultInterface.includes("wifi")) {
root.networkStatus = "wifi"
console.log("WiFi interface has default route, setting status to wifi")
// Trigger WiFi SSID update
if (root.wifiEnabled) {
WifiService.updateCurrentWifiInfo()
}
} else if (defaultInterface.startsWith("en") || defaultInterface.includes("eth")) {
root.networkStatus = "ethernet"
console.log("Ethernet interface has default route, setting status to ethernet")
} else {
root.networkStatus = "disconnected"
console.log("Unknown interface type:", defaultInterface)
}
}
}
}
Process {
id: wifiRadioChecker
command: ["nmcli", "radio", "wifi"]
@@ -186,25 +187,7 @@ Singleton {
console.log("Ethernet IP:", root.ethernetIP)
// Get the ethernet interface name
let ethInterfaceProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["sh", "-c", "nmcli -t -f DEVICE,TYPE device | grep ethernet | grep connected | cut -d: -f1 | head -1"]
running: true
stdout: SplitParser {
splitMarker: "\\n"
onRead: function(interfaceData) {
if (interfaceData.trim()) {
root.ethernetInterface = interfaceData.trim()
console.log("Ethernet Interface:", root.ethernetInterface)
// Ethernet interface detected - status will be determined by route checking
console.log("Ethernet interface detected:", root.ethernetInterface)
}
}
}
}
`, root)
ethernetInterfaceChecker.running = true
} else {
console.log("No ethernet IP found")
root.ethernetIP = ""
@@ -214,6 +197,25 @@ Singleton {
}
}
Process {
id: ethernetInterfaceChecker
command: ["sh", "-c", "nmcli -t -f DEVICE,TYPE device | grep ethernet | grep connected | cut -d: -f1 | head -1"]
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: function(interfaceData) {
if (interfaceData.trim()) {
root.ethernetInterface = interfaceData.trim()
console.log("Ethernet Interface:", root.ethernetInterface)
// Ethernet interface detected - status will be determined by route checking
console.log("Ethernet interface detected:", root.ethernetInterface)
}
}
}
}
Process {
id: wifiIPChecker
command: ["sh", "-c", "WIFI_DEV=$(nmcli -t -f DEVICE,TYPE device | grep wifi | grep connected | cut -d: -f1 | head -1); if [ -n \"$WIFI_DEV\" ]; then nmcli -t -f IP4.ADDRESS dev show \"$WIFI_DEV\" | cut -d: -f2 | cut -d/ -f1 | head -1; fi"]
@@ -236,76 +238,154 @@ Singleton {
}
}
// Static processes for network operations
Process {
id: ethernetDisconnector
command: ["sh", "-c", "nmcli device disconnect $(nmcli -t -f DEVICE,TYPE device | grep ethernet | cut -d: -f1 | head -1)"]
running: false
onExited: function(exitCode) {
console.log("Ethernet disconnect result:", exitCode)
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\n"
onRead: function(data) {
console.log("Ethernet disconnect stderr:", data)
}
}
}
Process {
id: ethernetConnector
command: ["sh", "-c", "ETH_DEV=$(nmcli -t -f DEVICE,TYPE device | grep ethernet | cut -d: -f1 | head -1); if [ -n \"$ETH_DEV\" ]; then nmcli device connect \"$ETH_DEV\"; ETH_CONN=$(nmcli -t -f NAME,DEVICE connection show --active | grep \"$ETH_DEV\" | cut -d: -f1); if [ -n \"$ETH_CONN\" ]; then nmcli connection modify \"$ETH_CONN\" connection.autoconnect-priority 100; nmcli connection down \"$ETH_CONN\"; nmcli connection up \"$ETH_CONN\"; fi; else echo \"No ethernet device found\"; exit 1; fi"]
running: false
onExited: function(exitCode) {
console.log("Ethernet connect result:", exitCode)
if (exitCode === 0) {
console.log("Ethernet connected successfully with higher priority")
} else {
console.log("Ethernet connection failed")
}
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\n"
onRead: function(data) {
console.log("Ethernet connect stderr:", data)
}
}
}
Process {
id: wifiDeviceConnector
command: ["sh", "-c", "WIFI_DEV=$(nmcli -t -f DEVICE,TYPE device | grep wifi | cut -d: -f1 | head -1); if [ -n \"$WIFI_DEV\" ]; then nmcli device connect \"$WIFI_DEV\"; else echo \"No WiFi device found\"; exit 1; fi"]
running: false
onExited: function(exitCode) {
console.log("WiFi device connect result:", exitCode)
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\n"
onRead: function(data) {
console.log("WiFi device connect stderr:", data)
}
}
}
Process {
id: wifiSwitcher
command: ["sh", "-c", "ETH_DEV=$(nmcli -t -f DEVICE,TYPE device | grep ethernet | cut -d: -f1 | head -1); WIFI_DEV=$(nmcli -t -f DEVICE,TYPE device | grep wifi | cut -d: -f1 | head -1); [ -n \"$ETH_DEV\" ] && nmcli device disconnect \"$ETH_DEV\" 2>/dev/null; [ -n \"$WIFI_DEV\" ] && nmcli device connect \"$WIFI_DEV\" 2>/dev/null || true"]
running: false
onExited: function(exitCode) {
console.log("Switch to wifi result:", exitCode)
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\n"
onRead: function(data) {
console.log("Switch to wifi stderr:", data)
}
}
}
Process {
id: ethernetSwitcher
command: ["sh", "-c", "WIFI_DEV=$(nmcli -t -f DEVICE,TYPE device | grep wifi | cut -d: -f1 | head -1); ETH_DEV=$(nmcli -t -f DEVICE,TYPE device | grep ethernet | cut -d: -f1 | head -1); [ -n \"$WIFI_DEV\" ] && nmcli device disconnect \"$WIFI_DEV\" 2>/dev/null; [ -n \"$ETH_DEV\" ] && nmcli device connect \"$ETH_DEV\" 2>/dev/null || true"]
running: false
onExited: function(exitCode) {
console.log("Switch to ethernet result:", exitCode)
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\n"
onRead: function(data) {
console.log("Switch to ethernet stderr:", data)
}
}
}
Process {
id: wifiRadioToggler
command: ["nmcli", "radio", "wifi", root.wifiEnabled ? "off" : "on"]
running: false
onExited: {
root.wifiToggling = false
networkStatusChecker.running = true
}
}
Process {
id: wifiPriorityChanger
command: ["sh", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | while read conn; do nmcli connection modify \"$conn\" ipv4.route-metric 50; done; nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | while read conn; do nmcli connection modify \"$conn\" ipv4.route-metric 200; done; nmcli -t -f NAME,TYPE connection show --active | grep -E \"(802-11-wireless|802-3-ethernet)\" | cut -d: -f1 | while read conn; do nmcli connection down \"$conn\" && nmcli connection up \"$conn\"; done"]
running: false
onExited: function(exitCode) {
console.log("WiFi route metric set to 50, ethernet to 200, connections restarted, exit code:", exitCode)
// Don't reset changingPreference here - let network status check handle it
delayedRefreshNetworkStatus()
}
}
Process {
id: ethernetPriorityChanger
command: ["sh", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | while read conn; do nmcli connection modify \"$conn\" ipv4.route-metric 50; done; nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | while read conn; do nmcli connection modify \"$conn\" ipv4.route-metric 200; done; nmcli -t -f NAME,TYPE connection show --active | grep -E \"(802-11-wireless|802-3-ethernet)\" | cut -d: -f1 | while read conn; do nmcli connection down \"$conn\" && nmcli connection up \"$conn\"; done"]
running: false
onExited: function(exitCode) {
console.log("Ethernet route metric set to 50, WiFi to 200, connections restarted, exit code:", exitCode)
// Don't reset changingPreference here - let network status check handle it
delayedRefreshNetworkStatus()
}
}
function toggleNetworkConnection(type) {
if (type === "ethernet") {
// Toggle ethernet connection
if (root.networkStatus === "ethernet") {
// Disconnect ethernet
console.log("Disconnecting ethernet...")
let disconnectProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["sh", "-c", "nmcli device disconnect $(nmcli -t -f DEVICE,TYPE device | grep ethernet | cut -d: -f1 | head -1)"]
running: true
onExited: function(exitCode) {
console.log("Ethernet disconnect result:", exitCode)
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: function(data) {
console.log("Ethernet disconnect stderr:", data)
}
}
}
`, root)
ethernetDisconnector.running = true
} else {
// Connect ethernet and set higher priority
console.log("Connecting ethernet...")
let connectProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["sh", "-c", "ETH_DEV=$(nmcli -t -f DEVICE,TYPE device | grep ethernet | cut -d: -f1 | head -1); if [ -n \\"$ETH_DEV\\" ]; then nmcli device connect \\"$ETH_DEV\\"; ETH_CONN=$(nmcli -t -f NAME,DEVICE connection show --active | grep \\"$ETH_DEV\\" | cut -d: -f1); if [ -n \\"$ETH_CONN\\" ]; then nmcli connection modify \\"$ETH_CONN\\" connection.autoconnect-priority 100; nmcli connection down \\"$ETH_CONN\\"; nmcli connection up \\"$ETH_CONN\\"; fi; else echo \\"No ethernet device found\\"; exit 1; fi"]
running: true
onExited: function(exitCode) {
console.log("Ethernet connect result:", exitCode)
if (exitCode === 0) {
console.log("Ethernet connected successfully with higher priority")
} else {
console.log("Ethernet connection failed")
}
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: function(data) {
console.log("Ethernet connect stderr:", data)
}
}
}
`, root)
ethernetConnector.running = true
}
} else if (type === "wifi") {
// Connect to WiFi if disconnected
if (root.networkStatus !== "wifi" && root.wifiEnabled) {
console.log("Connecting to WiFi device...")
let connectProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["sh", "-c", "WIFI_DEV=$(nmcli -t -f DEVICE,TYPE device | grep wifi | cut -d: -f1 | head -1); if [ -n \\"$WIFI_DEV\\" ]; then nmcli device connect \\"$WIFI_DEV\\"; else echo \\"No WiFi device found\\"; exit 1; fi"]
running: true
onExited: function(exitCode) {
console.log("WiFi device connect result:", exitCode)
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: function(data) {
console.log("WiFi device connect stderr:", data)
}
}
}
`, root)
wifiDeviceConnector.running = true
}
}
}
@@ -313,63 +393,21 @@ Singleton {
function switchToWifi() {
console.log("Switching to WiFi")
// Disconnect ethernet first, then try to connect to a known WiFi network
let switchProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["sh", "-c", "ETH_DEV=$(nmcli -t -f DEVICE,TYPE device | grep ethernet | cut -d: -f1 | head -1); WIFI_DEV=$(nmcli -t -f DEVICE,TYPE device | grep wifi | cut -d: -f1 | head -1); [ -n \\"$ETH_DEV\\" ] && nmcli device disconnect \\"$ETH_DEV\\" 2>/dev/null; [ -n \\"$WIFI_DEV\\" ] && nmcli device connect \\"$WIFI_DEV\\" 2>/dev/null || true"]
running: true
onExited: function(exitCode) {
console.log("Switch to wifi result:", exitCode)
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: function(data) {
console.log("Switch to wifi stderr:", data)
}
}
}
`, root)
wifiSwitcher.running = true
}
function switchToEthernet() {
console.log("Switching to Ethernet")
// Disconnect WiFi first, then connect ethernet
let switchProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["sh", "-c", "WIFI_DEV=$(nmcli -t -f DEVICE,TYPE device | grep wifi | cut -d: -f1 | head -1); ETH_DEV=$(nmcli -t -f DEVICE,TYPE device | grep ethernet | cut -d: -f1 | head -1); [ -n \\"$WIFI_DEV\\" ] && nmcli device disconnect \\"$WIFI_DEV\\" 2>/dev/null; [ -n \\"$ETH_DEV\\" ] && nmcli device connect \\"$ETH_DEV\\" 2>/dev/null || true"]
running: true
onExited: function(exitCode) {
console.log("Switch to ethernet result:", exitCode)
delayedRefreshNetworkStatus()
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: function(data) {
console.log("Switch to ethernet stderr:", data)
}
}
}
`, root)
ethernetSwitcher.running = true
}
function toggleWifiRadio() {
if (root.wifiToggling) return
root.wifiToggling = true
let action = root.wifiEnabled ? "off" : "on"
let toggleProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["nmcli", "radio", "wifi", "${action}"]
running: true
onExited: {
root.wifiToggling = false
networkStatusChecker.running = true
}
}
`, root)
wifiRadioToggler.command = ["nmcli", "radio", "wifi", root.wifiEnabled ? "off" : "on"]
wifiRadioToggler.running = true
}
function refreshNetworkStatus() {
@@ -391,32 +429,10 @@ Singleton {
if (preference === "wifi") {
// Set WiFi to low route metric (high priority), ethernet to high route metric (low priority)
let wifiPriorityProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["sh", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | while read conn; do nmcli connection modify \\\\\\"$conn\\\\\\" ipv4.route-metric 50; done; nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | while read conn; do nmcli connection modify \\\\\\"$conn\\\\\\" ipv4.route-metric 200; done; nmcli -t -f NAME,TYPE connection show --active | grep -E \\\\\\"(802-11-wireless|802-3-ethernet)\\\\\\" | cut -d: -f1 | while read conn; do nmcli connection down \\\\\\"$conn\\\\\\" && nmcli connection up \\\\\\"$conn\\\\\\"; done"]
running: true
onExited: function(exitCode) {
console.log("WiFi route metric set to 50, ethernet to 200, connections restarted, exit code:", exitCode)
// Don't reset changingPreference here - let network status check handle it
delayedRefreshNetworkStatus()
}
}
`, root)
wifiPriorityChanger.running = true
} else if (preference === "ethernet") {
// Set ethernet to low route metric (high priority), WiFi to high route metric (low priority)
let ethernetPriorityProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["sh", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | while read conn; do nmcli connection modify \\\\\\"$conn\\\\\\" ipv4.route-metric 50; done; nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | while read conn; do nmcli connection modify \\\\\\"$conn\\\\\\" ipv4.route-metric 200; done; nmcli -t -f NAME,TYPE connection show --active | grep -E \\\\\\"(802-11-wireless|802-3-ethernet)\\\\\\" | cut -d: -f1 | while read conn; do nmcli connection down \\\\\\"$conn\\\\\\" && nmcli connection up \\\\\\"$conn\\\\\\"; done"]
running: true
onExited: function(exitCode) {
console.log("Ethernet route metric set to 50, WiFi to 200, connections restarted, exit code:", exitCode)
// Don't reset changingPreference here - let network status check handle it
delayedRefreshNetworkStatus()
}
}
`, root)
ethernetPriorityChanger.running = true
}
}

View File

@@ -119,25 +119,13 @@ Singleton {
updateProcessList();
}
property int killPid: 0
function killProcess(pid) {
if (pid > 0) {
const killCmd = ["bash", "-c", "kill " + pid];
const killProcess = Qt.createQmlObject(`
import QtQuick
import Quickshell.Io
Process {
command: ${JSON.stringify(killCmd)}
running: true
onExited: (exitCode) => {
if (exitCode === 0) {
console.log("Process killed successfully:", ${pid})
} else {
console.warn("Failed to kill process:", ${pid}, "exit code:", exitCode)
}
destroy()
}
}
`, root);
root.killPid = pid
processKiller.command = ["bash", "-c", "kill " + pid]
processKiller.running = true
}
}
@@ -438,6 +426,21 @@ Singleton {
}
Process {
id: processKiller
command: ["bash", "-c", "kill " + root.killPid]
running: false
onExited: (exitCode) => {
if (exitCode === 0) {
console.log("Process killed successfully:", root.killPid)
} else {
console.warn("Failed to kill process:", root.killPid, "exit code:", exitCode)
}
root.killPid = 0
}
}
Timer {
id: processTimer

View File

@@ -13,10 +13,19 @@ Singleton {
property var wifiNetworks: []
property var savedWifiNetworks: []
property bool isScanning: false
property string connectionStatus: "" // "cosnnecting", "connected", "failed", ""
property string connectionStatus: "" // "connecting", "connected", "failed", "invalid_password", ""
property string connectingSSID: ""
property string lastConnectionError: ""
property bool passwordDialogShouldReopen: false
// Auto-refresh timer for when control center is open
property bool autoRefreshEnabled: false
signal networksUpdated()
// Network info properties
property string networkInfoSSID: ""
property string networkInfoDetails: ""
property bool networkInfoLoading: false
function scanWifi() {
if (root.isScanning)
@@ -33,107 +42,49 @@ Singleton {
console.log("Connecting to WiFi:", ssid);
root.connectionStatus = "connecting";
root.connectingSSID = ssid;
let connectProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["bash", "-c", "nmcli dev wifi connect \\"' + ssid + '\\" || nmcli connection up \\"' + ssid + '\\"; if [ $? -eq 0 ]; then nmcli connection modify \\"' + ssid + '\\" connection.autoconnect-priority 50; nmcli connection down \\"' + ssid + '\\"; nmcli connection up \\"' + ssid + '\\"; fi"]
running: true
onExited: (exitCode) => {
console.log("WiFi connection result:", exitCode)
if (exitCode === 0) {
root.connectionStatus = "connected"
console.log("Connected to WiFi successfully")
// Set user preference to WiFi when manually connecting
NetworkService.setNetworkPreference("wifi")
// Force network status refresh after successful connection
NetworkService.delayedRefreshNetworkStatus()
} else {
root.connectionStatus = "failed"
console.log("WiFi connection failed")
}
scanWifi()
statusResetTimer.start()
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: (data) => {
console.log("WiFi connection stderr:", data)
}
}
}
`, root);
ToastService.showInfo("Connecting to " + ssid + "...");
wifiConnector.running = true;
}
property string wifiPassword: ""
function connectToWifiWithPassword(ssid, password) {
console.log("Connecting to WiFi with password:", ssid);
root.connectionStatus = "connecting";
root.connectingSSID = ssid;
let connectProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["bash", "-c", "nmcli dev wifi connect \\"' + ssid + '\\" password \\"' + password + '\\"; if [ $? -eq 0 ]; then nmcli connection modify \\"' + ssid + '\\" connection.autoconnect-priority 50; nmcli connection down \\"' + ssid + '\\"; nmcli connection up \\"' + ssid + '\\"; fi"]
running: true
onExited: (exitCode) => {
console.log("WiFi connection with password result:", exitCode)
if (exitCode === 0) {
root.connectionStatus = "connected"
console.log("Connected to WiFi with password successfully")
// Set user preference to WiFi when manually connecting
NetworkService.setNetworkPreference("wifi")
// Force network status refresh after successful connection
NetworkService.delayedRefreshNetworkStatus()
} else {
root.connectionStatus = "failed"
console.log("WiFi connection with password failed")
}
scanWifi()
statusResetTimer.start()
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: (data) => {
console.log("WiFi connection with password stderr:", data)
}
}
}
`, root);
root.wifiPassword = password;
root.lastConnectionError = "";
root.passwordDialogShouldReopen = false;
ToastService.showInfo("Connecting to " + ssid + "...");
wifiPasswordConnector.running = true;
}
function disconnectWifi() {
console.log("Disconnecting from current WiFi network");
wifiDisconnector.running = true;
}
property string forgetSSID: ""
function forgetWifiNetwork(ssid) {
console.log("Forgetting WiFi network:", ssid);
let forgetProcess = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["bash", "-c", "nmcli connection delete \\"' + ssid + '\\" || nmcli connection delete id \\"' + ssid + '\\""]
running: true
onExited: (exitCode) => {
console.log("WiFi forget result:", exitCode)
if (exitCode === 0) {
console.log("Successfully forgot WiFi network:", "' + ssid + '")
} else {
console.log("Failed to forget WiFi network:", "' + ssid + '")
}
scanWifi()
}
root.forgetSSID = ssid;
wifiForget.running = true;
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: (data) => {
console.log("WiFi forget stderr:", data)
}
}
}
`, root);
function fetchNetworkInfo(ssid) {
console.log("Fetching network info for:", ssid);
root.networkInfoSSID = ssid;
root.networkInfoLoading = true;
root.networkInfoDetails = "Loading network information...";
wifiInfoFetcher.running = true;
}
function updateCurrentWifiInfo() {
currentWifiInfo.running = true;
}
Process {
id: currentWifiInfo
@@ -245,6 +196,7 @@ Singleton {
}
Timer {
id: fallbackTimer
@@ -273,4 +225,304 @@ Singleton {
onTriggered: root.scanWifi()
}
// WiFi Connection Process
Process {
id: wifiConnector
command: ["bash", "-c", "timeout 30 nmcli dev wifi connect \"" + root.connectingSSID + "\" || nmcli connection up \"" + root.connectingSSID + "\"; exit_code=$?; echo \"nmcli exit code: $exit_code\" >&2; if [ $exit_code -eq 0 ]; then nmcli connection modify \"" + root.connectingSSID + "\" connection.autoconnect-priority 50; sleep 2; if nmcli -t -f ACTIVE,SSID dev wifi | grep -q \"^yes:" + root.connectingSSID + "\"; then echo \"Connection verified\" >&2; exit 0; else echo \"Connection failed verification\" >&2; exit 4; fi; else exit $exit_code; fi"]
running: false
stderr: StdioCollector {
onStreamFinished: {
console.log("WiFi connection debug output:", text.trim())
}
}
onExited: (exitCode) => {
console.log("WiFi connection result:", exitCode)
if (exitCode === 0) {
root.connectionStatus = "connected"
root.passwordDialogShouldReopen = false
console.log("Connected to WiFi successfully")
ToastService.showInfo("Connected to " + root.connectingSSID)
NetworkService.setNetworkPreference("wifi")
NetworkService.delayedRefreshNetworkStatus()
// Immediately update savedWifiNetworks to include the new connection
if (!root.savedWifiNetworks.some((saved) => saved.ssid === root.connectingSSID)) {
let updatedSaved = [...root.savedWifiNetworks];
updatedSaved.push({"ssid": root.connectingSSID, "saved": true});
root.savedWifiNetworks = updatedSaved;
}
// Update wifiNetworks to reflect the change
let updatedNetworks = [...root.wifiNetworks];
for (let i = 0; i < updatedNetworks.length; i++) {
if (updatedNetworks[i].ssid === root.connectingSSID) {
updatedNetworks[i].saved = true;
updatedNetworks[i].connected = true;
break;
}
}
root.wifiNetworks = updatedNetworks;
} else if (exitCode === 4) {
// Connection failed - likely needs password for saved network
root.connectionStatus = "invalid_password"
root.passwordDialogShouldReopen = true
console.log("Saved network connection failed - password required")
ToastService.showError("Authentication failed for " + root.connectingSSID)
} else {
root.connectionStatus = "failed"
console.log("WiFi connection failed")
ToastService.showError("Failed to connect to " + root.connectingSSID)
}
scanWifi()
statusResetTimer.start()
}
}
// WiFi Connection with Password Process
Process {
id: wifiPasswordConnector
command: ["bash", "-c", "nmcli connection delete \"" + root.connectingSSID + "\" 2>/dev/null || true; timeout 30 nmcli dev wifi connect \"" + root.connectingSSID + "\" password \"" + root.wifiPassword + "\"; exit_code=$?; echo \"nmcli exit code: $exit_code\" >&2; if [ $exit_code -eq 0 ]; then nmcli connection modify \"" + root.connectingSSID + "\" connection.autoconnect-priority 50; sleep 2; if nmcli -t -f ACTIVE,SSID dev wifi | grep -q \"^yes:" + root.connectingSSID + "\"; then echo \"Connection verified\" >&2; exit 0; else echo \"Connection failed verification\" >&2; exit 4; fi; else exit $exit_code; fi"]
running: false
stdout: StdioCollector {
onStreamFinished: {
if (text.trim()) {
console.log("WiFi connection stdout:", text.trim())
}
}
}
stderr: StdioCollector {
onStreamFinished: {
root.lastConnectionError = text.trim()
console.log("WiFi connection debug output:", text.trim())
}
}
onExited: (exitCode) => {
console.log("WiFi connection with password result:", exitCode)
console.log("Error output:", root.lastConnectionError)
if (exitCode === 0) {
root.connectionStatus = "connected"
root.passwordDialogShouldReopen = false
console.log("Connected to WiFi with password successfully")
ToastService.showInfo("Connected to " + root.connectingSSID)
NetworkService.setNetworkPreference("wifi")
NetworkService.delayedRefreshNetworkStatus()
// Immediately update savedWifiNetworks to include the new connection
if (!root.savedWifiNetworks.some((saved) => saved.ssid === root.connectingSSID)) {
let updatedSaved = [...root.savedWifiNetworks];
updatedSaved.push({"ssid": root.connectingSSID, "saved": true});
root.savedWifiNetworks = updatedSaved;
}
// Update wifiNetworks to reflect the change
let updatedNetworks = [...root.wifiNetworks];
for (let i = 0; i < updatedNetworks.length; i++) {
if (updatedNetworks[i].ssid === root.connectingSSID) {
updatedNetworks[i].saved = true;
updatedNetworks[i].connected = true;
break;
}
}
root.wifiNetworks = updatedNetworks;
} else if (exitCode === 4) {
// Connection activation failed - likely invalid credentials
if (root.lastConnectionError.includes("Secrets were required") ||
root.lastConnectionError.includes("authentication") ||
root.lastConnectionError.includes("AUTH_TIMED_OUT")) {
root.connectionStatus = "invalid_password"
root.passwordDialogShouldReopen = true
console.log("Invalid password detected")
ToastService.showError("Invalid password for " + root.connectingSSID)
} else {
root.connectionStatus = "failed"
console.log("Connection failed - not password related")
ToastService.showError("Failed to connect to " + root.connectingSSID)
}
} else if (exitCode === 3 || exitCode === 124) {
root.connectionStatus = "failed"
console.log("Connection timed out")
ToastService.showError("Connection to " + root.connectingSSID + " timed out")
} else {
root.connectionStatus = "failed"
console.log("WiFi connection with password failed")
ToastService.showError("Failed to connect to " + root.connectingSSID)
}
root.wifiPassword = "" // Clear password
scanWifi()
statusResetTimer.start()
}
}
// WiFi Disconnect Process
Process {
id: wifiDisconnector
command: ["bash", "-c", "WIFI_DEV=$(nmcli -t -f DEVICE,TYPE device | grep wifi | cut -d: -f1 | head -1); [ -n \"$WIFI_DEV\" ] && nmcli device disconnect \"$WIFI_DEV\""]
running: false
onExited: (exitCode) => {
console.log("WiFi disconnect result:", exitCode)
if (exitCode === 0) {
console.log("Successfully disconnected from WiFi")
ToastService.showInfo("Disconnected from WiFi")
root.currentWifiSSID = ""
root.connectionStatus = ""
NetworkService.refreshNetworkStatus()
} else {
console.log("Failed to disconnect from WiFi")
ToastService.showError("Failed to disconnect from WiFi")
}
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: (data) => {
console.log("WiFi disconnect stderr:", data)
}
}
}
// WiFi Forget Network Process
Process {
id: wifiForget
command: ["bash", "-c", "nmcli connection delete \"" + root.forgetSSID + "\" || nmcli connection delete id \"" + root.forgetSSID + "\""]
running: false
onExited: (exitCode) => {
console.log("WiFi forget result:", exitCode)
if (exitCode === 0) {
console.log("Successfully forgot WiFi network:", root.forgetSSID)
ToastService.showInfo("Forgot network \"" + root.forgetSSID + "\"")
// If we forgot the currently connected network, clear connection status
if (root.forgetSSID === root.currentWifiSSID) {
root.currentWifiSSID = "";
root.connectionStatus = "";
NetworkService.refreshNetworkStatus();
}
// Update savedWifiNetworks to remove the forgotten network
root.savedWifiNetworks = root.savedWifiNetworks.filter((saved) => {
return saved.ssid !== root.forgetSSID;
});
// Update wifiNetworks - create new array with updated objects
let updatedNetworks = [];
for (let i = 0; i < root.wifiNetworks.length; i++) {
let network = root.wifiNetworks[i];
if (network.ssid === root.forgetSSID) {
let updatedNetwork = Object.assign({}, network);
updatedNetwork.saved = false;
updatedNetwork.connected = false;
updatedNetworks.push(updatedNetwork);
} else {
updatedNetworks.push(network);
}
}
root.wifiNetworks = updatedNetworks;
root.networksUpdated();
} else {
console.log("Failed to forget WiFi network:", root.forgetSSID)
ToastService.showError("Failed to forget network \"" + root.forgetSSID + "\"")
}
root.forgetSSID = "" // Clear SSID
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: (data) => {
console.log("WiFi forget stderr:", data)
}
}
}
// WiFi Network Info Fetcher Process - Using detailed nmcli output
Process {
id: wifiInfoFetcher
command: ["nmcli", "-t", "-f", "SSID,SIGNAL,SECURITY,FREQ,RATE,MODE,CHAN,WPA-FLAGS,RSN-FLAGS", "dev", "wifi", "list"]
running: false
stdout: StdioCollector {
onStreamFinished: {
let details = "";
if (text.trim()) {
let lines = text.trim().split('\n');
for (let line of lines) {
let parts = line.split(':');
if (parts.length >= 9 && parts[0] === root.networkInfoSSID) {
let ssid = parts[0] || "Unknown";
let signal = parts[1] || "0";
let security = parts[2] || "Open";
let freq = parts[3] || "Unknown";
let rate = parts[4] || "Unknown";
let mode = parts[5] || "Unknown";
let channel = parts[6] || "Unknown";
let wpaFlags = parts[7] || "";
let rsnFlags = parts[8] || "";
// Determine band from frequency
let band = "Unknown";
let freqNum = parseInt(freq);
if (freqNum >= 2400 && freqNum <= 2500) {
band = "2.4 GHz";
} else if (freqNum >= 5000 && freqNum <= 6000) {
band = "5 GHz";
} else if (freqNum >= 6000) {
band = "6 GHz";
}
details = "Network Name: " + ssid + "\\n";
details += "Signal Strength: " + signal + "%\\n";
details += "Security: " + (security === "" ? "Open" : security) + "\\n";
details += "Frequency: " + freq + " MHz\\n";
details += "Band: " + band + "\\n";
details += "Channel: " + channel + "\\n";
details += "Mode: " + mode + "\\n";
details += "Max Rate: " + rate + " Mbit/s\\n";
if (wpaFlags !== "") {
details += "WPA Flags: " + wpaFlags + "\\n";
}
if (rsnFlags !== "") {
details += "RSN Flags: " + rsnFlags + "\\n";
}
break;
}
}
}
if (details === "") {
details = "Network information not found or network not available.";
}
root.networkInfoDetails = details;
root.networkInfoLoading = false;
console.log("Network info fetched for:", root.networkInfoSSID);
}
}
onExited: (exitCode) => {
root.networkInfoLoading = false;
if (exitCode !== 0) {
console.log("Failed to fetch network info, exit code:", exitCode);
root.networkInfoDetails = "Failed to fetch network information";
}
}
stderr: SplitParser {
splitMarker: "\\n"
onRead: (data) => {
console.log("WiFi info stderr:", data);
}
}
}
}