1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-30 09:32:05 -04:00
Files
DankMaterialShell/quickshell/Services/LegacyNetworkService.qml
bbedward f76724f7cd logger: add a dedicated QML logging Singleton
- adds log.info/error/debug/warn/fatal
- adds ability to write logs to any file
- add CLI options in addition to env to set log levels
2026-04-29 15:42:30 -04:00

985 lines
35 KiB
QML

pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
import qs.Common
import qs.Services
Singleton {
id: root
readonly property var log: Log.scoped("LegacyNetworkService")
property bool isActive: false
property string networkStatus: "disconnected"
property string primaryConnection: ""
property string ethernetIP: ""
property string ethernetInterface: ""
property bool ethernetConnected: false
property string ethernetConnectionUuid: ""
property var wiredConnections: []
property string wifiIP: ""
property string wifiInterface: ""
property bool wifiConnected: false
property bool wifiEnabled: true
property string wifiConnectionUuid: ""
property string wifiDevicePath: ""
property string activeAccessPointPath: ""
property string currentWifiSSID: ""
property int wifiSignalStrength: 0
property var wifiNetworks: []
property var savedConnections: []
property var ssidToConnectionName: {}
property var wifiSignalIcon: {
if (!wifiConnected || networkStatus !== "wifi") {
return "wifi_off";
}
if (wifiSignalStrength >= 50) {
return "wifi";
}
if (wifiSignalStrength >= 25) {
return "wifi_2_bar";
}
return "wifi_1_bar";
}
property string userPreference: "auto" // "auto", "wifi", "ethernet"
property bool isConnecting: false
property string connectingSSID: ""
property string connectionError: ""
property bool isScanning: false
property bool wifiAvailable: true
property bool wifiToggling: false
property bool changingPreference: false
property string targetPreference: ""
property var savedWifiNetworks: []
property string connectionStatus: ""
property string lastConnectionError: ""
property bool passwordDialogShouldReopen: false
property string wifiPassword: ""
property string forgetSSID: ""
readonly property var lowPriorityCmd: ["nice", "-n", "19", "ionice", "-c3"]
property string networkInfoSSID: ""
property string networkInfoDetails: ""
property bool networkInfoLoading: false
property string networkWiredInfoUUID: ""
property string networkWiredInfoDetails: ""
property bool networkWiredInfoLoading: false
signal networksUpdated
signal connectionChanged
function splitNmcliFields(line) {
const parts = [];
let cur = "";
let escape = false;
for (var i = 0; i < line.length; i++) {
const ch = line[i];
if (escape) {
cur += ch;
escape = false;
} else if (ch === '\\') {
escape = true;
} else if (ch === ':') {
parts.push(cur);
cur = "";
} else {
cur += ch;
}
}
parts.push(cur);
return parts;
}
Component.onCompleted: {
root.userPreference = SettingsData.networkPreference;
}
function activate() {
if (!isActive) {
isActive = true;
log.info("Activating...");
doRefreshNetworkState();
}
}
function doRefreshNetworkState() {
updatePrimaryConnection();
updateDeviceStates();
updateActiveConnections();
updateWifiState();
}
function updatePrimaryConnection() {
primaryConnectionQuery.running = true;
}
Process {
id: primaryConnectionQuery
command: lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", "/org/freedesktop/NetworkManager", "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager", "PrimaryConnection"])
running: false
stdout: StdioCollector {
onStreamFinished: {
const match = text.match(/objectpath '([^']+)'/);
if (match && match[1] !== '/') {
root.primaryConnection = match[1];
getPrimaryConnectionType.running = true;
} else {
root.primaryConnection = "";
root.networkStatus = "disconnected";
}
}
}
}
Process {
id: getPrimaryConnectionType
command: root.primaryConnection ? lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", root.primaryConnection, "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager.Connection.Active", "Type"]) : []
running: false
stdout: StdioCollector {
onStreamFinished: {
if (text.includes("802-3-ethernet")) {
root.networkStatus = "ethernet";
} else if (text.includes("802-11-wireless")) {
root.networkStatus = "wifi";
}
root.connectionChanged();
}
}
}
function updateDeviceStates() {
getEthernetDevice.running = true;
getWifiDevice.running = true;
}
Process {
id: getEthernetDevice
command: lowPriorityCmd.concat(["nmcli", "-t", "-f", "DEVICE,TYPE", "device"])
running: false
stdout: StdioCollector {
onStreamFinished: {
const lines = text.trim().split('\n');
let ethernetInterface = "";
for (const line of lines) {
const splitParts = line.split(':');
const device = splitParts[0];
const type = splitParts.length > 1 ? splitParts[1] : "";
if (type === "ethernet") {
ethernetInterface = device;
break;
}
}
if (ethernetInterface) {
root.ethernetInterface = ethernetInterface;
getEthernetDevicePath.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", "/org/freedesktop/NetworkManager", "--method", "org.freedesktop.NetworkManager.GetDeviceByIpIface", ethernetInterface]);
getEthernetDevicePath.running = true;
} else {
root.ethernetInterface = "";
root.ethernetConnected = false;
}
}
}
}
Process {
id: getEthernetDevicePath
running: false
stdout: StdioCollector {
onStreamFinished: {
const match = text.match(/objectpath '([^']+)'/);
if (match && match[1] !== '/') {
checkEthernetState.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", match[1], "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager.Device", "State"]);
checkEthernetState.running = true;
} else {
root.ethernetInterface = "";
root.ethernetConnected = false;
}
}
}
onExited: exitCode => {
if (exitCode !== 0) {
root.ethernetInterface = "";
root.ethernetConnected = false;
}
}
}
Process {
id: checkEthernetState
running: false
stdout: StdioCollector {
onStreamFinished: {
const isConnected = text.includes("uint32 100");
root.ethernetConnected = isConnected;
if (isConnected) {
getEthernetIP.running = true;
} else {
root.ethernetIP = "";
}
}
}
}
Process {
id: getEthernetIP
command: root.ethernetInterface ? lowPriorityCmd.concat(["ip", "-4", "addr", "show", root.ethernetInterface]) : []
running: false
stdout: StdioCollector {
onStreamFinished: {
const match = text.match(/inet (\d+\.\d+\.\d+\.\d+)/);
if (match) {
root.ethernetIP = match[1];
}
}
}
}
Process {
id: getWifiDevice
command: lowPriorityCmd.concat(["nmcli", "-t", "-f", "DEVICE,TYPE", "device"])
running: false
stdout: StdioCollector {
onStreamFinished: {
const lines = text.trim().split('\n');
let wifiInterface = "";
for (const line of lines) {
const splitParts = line.split(':');
const device = splitParts[0];
const type = splitParts.length > 1 ? splitParts[1] : "";
if (type === "wifi") {
wifiInterface = device;
break;
}
}
if (wifiInterface) {
root.wifiInterface = wifiInterface;
getWifiDevicePath.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", "/org/freedesktop/NetworkManager", "--method", "org.freedesktop.NetworkManager.GetDeviceByIpIface", wifiInterface]);
getWifiDevicePath.running = true;
} else {
root.wifiInterface = "";
root.wifiConnected = false;
}
}
}
}
Process {
id: getWifiDevicePath
running: false
stdout: StdioCollector {
onStreamFinished: {
const match = text.match(/objectpath '([^']+)'/);
if (match && match[1] !== '/') {
root.wifiDevicePath = match[1];
checkWifiState.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", match[1], "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager.Device", "State"]);
checkWifiState.running = true;
} else {
root.wifiInterface = "";
root.wifiConnected = false;
root.wifiDevicePath = "";
root.activeAccessPointPath = "";
}
}
}
onExited: exitCode => {
if (exitCode !== 0) {
root.wifiInterface = "";
root.wifiConnected = false;
}
}
}
Process {
id: checkWifiState
running: false
stdout: StdioCollector {
onStreamFinished: {
root.wifiConnected = text.includes("uint32 100");
if (root.wifiConnected) {
getWifiIP.running = true;
getCurrentWifiInfo.running = true;
getActiveAccessPoint.running = true;
if (root.currentWifiSSID === "") {
if (root.wifiConnectionUuid) {
resolveWifiSSID.running = true;
}
if (root.wifiInterface) {
resolveWifiSSIDFromDevice.running = true;
}
}
} else {
root.wifiIP = "";
root.currentWifiSSID = "";
root.wifiSignalStrength = 0;
root.activeAccessPointPath = "";
}
}
}
}
Process {
id: getWifiIP
command: root.wifiInterface ? lowPriorityCmd.concat(["ip", "-4", "addr", "show", root.wifiInterface]) : []
running: false
stdout: StdioCollector {
onStreamFinished: {
const match = text.match(/inet (\d+\.\d+\.\d+\.\d+)/);
if (match) {
root.wifiIP = match[1];
}
}
}
}
Process {
id: getActiveAccessPoint
command: root.wifiDevicePath ? lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", root.wifiDevicePath, "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager.Device.Wireless", "ActiveAccessPoint"]) : []
running: false
stdout: StdioCollector {
onStreamFinished: {
const match = text.match(/objectpath '([^']+)'/);
if (match && match[1] !== '/') {
root.activeAccessPointPath = match[1];
} else {
root.activeAccessPointPath = "";
}
}
}
}
Process {
id: getCurrentWifiInfo
command: root.wifiInterface ? lowPriorityCmd.concat(["nmcli", "-t", "-f", "ACTIVE,SIGNAL,SSID", "device", "wifi", "list", "ifname", root.wifiInterface, "--rescan", "no"]) : []
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: line => {
if (line.startsWith("yes:")) {
const rest = line.substring(4);
const parts = root.splitNmcliFields(rest);
if (parts.length >= 2) {
const signal = parseInt(parts[0]);
log.debug("Current WiFi signal strength:", signal);
root.wifiSignalStrength = isNaN(signal) ? 0 : signal;
root.currentWifiSSID = parts[1];
log.debug("Current WiFi SSID:", root.currentWifiSSID);
}
return;
}
}
}
}
function updateActiveConnections() {
getActiveConnections.running = true;
}
Process {
id: getActiveConnections
command: lowPriorityCmd.concat(["nmcli", "-t", "-f", "UUID,TYPE,DEVICE,STATE", "connection", "show", "--active"])
running: false
stdout: StdioCollector {
onStreamFinished: {
const lines = text.trim().split('\n');
for (const line of lines) {
const parts = line.split(':');
if (parts.length >= 4) {
const uuid = parts[0];
const type = parts[1];
const device = parts[2];
const state = parts[3];
if (type === "802-3-ethernet" && state === "activated") {
root.ethernetConnectionUuid = uuid;
} else if (type === "802-11-wireless" && state === "activated") {
root.wifiConnectionUuid = uuid;
}
}
}
}
}
}
// Resolve SSID from active WiFi connection UUID when scans don't mark any row as ACTIVE.
Process {
id: resolveWifiSSID
command: root.wifiConnectionUuid ? lowPriorityCmd.concat(["nmcli", "-g", "802-11-wireless.ssid", "connection", "show", "uuid", root.wifiConnectionUuid]) : []
running: false
stdout: StdioCollector {
onStreamFinished: {
const ssid = text.trim();
if (ssid) {
root.currentWifiSSID = ssid;
}
}
}
}
// Fallback 2: Resolve SSID from device info (GENERAL.CONNECTION usually matches SSID for WiFi)
Process {
id: resolveWifiSSIDFromDevice
command: root.wifiInterface ? lowPriorityCmd.concat(["nmcli", "-t", "-f", "GENERAL.CONNECTION", "device", "show", root.wifiInterface]) : []
running: false
stdout: StdioCollector {
onStreamFinished: {
if (!root.currentWifiSSID) {
const name = text.trim();
if (name) {
root.currentWifiSSID = name;
}
}
}
}
}
function updateWifiState() {
checkWifiEnabled.running = true;
}
Process {
id: checkWifiEnabled
command: lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", "/org/freedesktop/NetworkManager", "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager", "WirelessEnabled"])
running: false
stdout: StdioCollector {
onStreamFinished: {
root.wifiEnabled = text.includes("true");
root.wifiAvailable = true; // Always available if we can check it
}
}
}
function scanWifi() {
if (root.isScanning || !root.wifiEnabled) {
return;
}
root.isScanning = true;
requestWifiScan.running = true;
}
Process {
id: requestWifiScan
command: root.wifiInterface ? lowPriorityCmd.concat(["nmcli", "dev", "wifi", "rescan", "ifname", root.wifiInterface]) : []
running: false
onExited: exitCode => {
if (exitCode === 0) {
scanWifiNetworks();
} else {
log.warn("WiFi scan request failed");
root.isScanning = false;
}
}
}
function scanWifiNetworks() {
if (!root.wifiInterface) {
root.isScanning = false;
return;
}
getWifiNetworks.running = true;
getSavedConnections.running = true;
}
Process {
id: getWifiNetworks
command: lowPriorityCmd.concat(["nmcli", "-t", "-f", "SSID,SIGNAL,SECURITY,BSSID", "dev", "wifi", "list", "ifname", root.wifiInterface])
running: false
stdout: StdioCollector {
onStreamFinished: {
const networks = [];
const lines = text.trim().split('\n');
const seen = new Set();
for (const line of lines) {
const parts = root.splitNmcliFields(line);
if (parts.length >= 4 && parts[0]) {
const ssid = parts[0];
if (!seen.has(ssid)) {
seen.add(ssid);
const signal = parseInt(parts[1]) || 0;
networks.push({
"ssid": ssid,
"signal": signal,
"secured": parts[2] !== "",
"bssid": parts[3],
"connected": ssid === root.currentWifiSSID,
"saved": false
});
}
}
}
networks.sort((a, b) => b.signal - a.signal);
root.wifiNetworks = networks;
root.isScanning = false;
root.networksUpdated();
}
}
}
Process {
id: getSavedConnections
command: lowPriorityCmd.concat(["bash", "-c", "nmcli -t -f NAME,TYPE connection show | grep ':802-11-wireless$' | cut -d: -f1 | while read name; do ssid=$(nmcli -g 802-11-wireless.ssid connection show \"$name\"); echo \"$ssid:$name\"; done"])
running: false
stdout: StdioCollector {
onStreamFinished: {
const saved = [];
const mapping = {};
const lines = text.trim().split('\n');
for (const line of lines) {
const parts = line.trim().split(':');
if (parts.length >= 2) {
const ssid = parts[0];
const connectionName = parts[1];
if (ssid && ssid.length > 0 && connectionName && connectionName.length > 0) {
saved.push({
"ssid": ssid,
"saved": true
});
mapping[ssid] = connectionName;
}
}
}
root.savedConnections = saved;
root.savedWifiNetworks = saved;
root.ssidToConnectionName = mapping;
const updated = [...root.wifiNetworks];
for (const network of updated) {
network.saved = saved.some(s => s.ssid === network.ssid);
}
root.wifiNetworks = updated;
}
}
}
function connectToWifi(ssid, password = "", username = "") {
if (root.isConnecting) {
return;
}
root.isConnecting = true;
root.connectingSSID = ssid;
root.connectionError = "";
root.connectionStatus = "connecting";
if (!password && root.ssidToConnectionName[ssid]) {
const connectionName = root.ssidToConnectionName[ssid];
wifiConnector.command = lowPriorityCmd.concat(["nmcli", "connection", "up", connectionName]);
} else if (password) {
wifiConnector.command = lowPriorityCmd.concat(["nmcli", "dev", "wifi", "connect", ssid, "password", password]);
} else {
wifiConnector.command = lowPriorityCmd.concat(["nmcli", "dev", "wifi", "connect", ssid]);
}
wifiConnector.running = true;
}
Process {
id: wifiConnector
running: false
property bool connectionSucceeded: false
stdout: StdioCollector {
onStreamFinished: {
if (text.includes("successfully")) {
wifiConnector.connectionSucceeded = true;
ToastService.showInfo(`Connected to ${root.connectingSSID}`);
root.connectionError = "";
root.connectionStatus = "connected";
if (root.userPreference === "wifi" || root.userPreference === "auto") {
setConnectionPriority("wifi");
}
}
}
}
stderr: StdioCollector {
onStreamFinished: {
root.connectionError = text;
root.lastConnectionError = text;
if (!wifiConnector.connectionSucceeded && text.trim() !== "") {
if (text.includes("password") || text.includes("authentication")) {
root.connectionStatus = "invalid_password";
root.passwordDialogShouldReopen = true;
} else {
root.connectionStatus = "failed";
}
}
}
}
onExited: exitCode => {
if (exitCode === 0 || wifiConnector.connectionSucceeded) {
if (!wifiConnector.connectionSucceeded) {
ToastService.showInfo(`Connected to ${root.connectingSSID}`);
root.connectionStatus = "connected";
}
} else {
if (root.connectionStatus === "") {
root.connectionStatus = "failed";
}
if (root.connectionStatus === "invalid_password") {
ToastService.showError(`Invalid password for ${root.connectingSSID}`);
} else {
ToastService.showError(`Failed to connect to ${root.connectingSSID}`);
}
}
wifiConnector.connectionSucceeded = false;
root.isConnecting = false;
root.connectingSSID = "";
doRefreshNetworkState();
}
}
function disconnectWifi() {
if (!root.wifiInterface) {
return;
}
wifiDisconnector.command = lowPriorityCmd.concat(["nmcli", "dev", "disconnect", root.wifiInterface]);
wifiDisconnector.running = true;
}
Process {
id: wifiDisconnector
running: false
onExited: exitCode => {
if (exitCode === 0) {
ToastService.showInfo("Disconnected from WiFi");
root.currentWifiSSID = "";
root.connectionStatus = "";
}
doRefreshNetworkState();
}
}
function forgetWifiNetwork(ssid) {
root.forgetSSID = ssid;
const connectionName = root.ssidToConnectionName[ssid] || ssid;
networkForgetter.command = lowPriorityCmd.concat(["nmcli", "connection", "delete", connectionName]);
networkForgetter.running = true;
}
Process {
id: networkForgetter
running: false
onExited: exitCode => {
if (exitCode === 0) {
ToastService.showInfo(`Forgot network ${root.forgetSSID}`);
root.savedConnections = root.savedConnections.filter(s => s.ssid !== root.forgetSSID);
root.savedWifiNetworks = root.savedWifiNetworks.filter(s => s.ssid !== root.forgetSSID);
const updated = [...root.wifiNetworks];
for (const network of updated) {
if (network.ssid === root.forgetSSID) {
network.saved = false;
if (network.connected) {
network.connected = false;
root.currentWifiSSID = "";
}
}
}
root.wifiNetworks = updated;
root.networksUpdated();
doRefreshNetworkState();
}
root.forgetSSID = "";
}
}
function toggleWifiRadio() {
if (root.wifiToggling) {
return;
}
root.wifiToggling = true;
const targetState = root.wifiEnabled ? "off" : "on";
wifiRadioToggler.targetState = targetState;
wifiRadioToggler.command = lowPriorityCmd.concat(["nmcli", "radio", "wifi", targetState]);
wifiRadioToggler.running = true;
}
Process {
id: wifiRadioToggler
running: false
property string targetState: ""
onExited: exitCode => {
root.wifiToggling = false;
if (exitCode === 0) {
ToastService.showInfo(targetState === "on" ? "WiFi enabled" : "WiFi disabled");
}
doRefreshNetworkState();
}
}
function setNetworkPreference(preference) {
root.userPreference = preference;
root.changingPreference = true;
root.targetPreference = preference;
SettingsData.set("networkPreference", preference);
if (preference === "wifi") {
setConnectionPriority("wifi");
} else if (preference === "ethernet") {
setConnectionPriority("ethernet");
}
}
function setConnectionPriority(type) {
if (type === "wifi") {
setRouteMetrics.command = lowPriorityCmd.concat(["bash", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 50 ipv6.route-metric 50'; " + "nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 100 ipv6.route-metric 100'"]);
} else if (type === "ethernet") {
setRouteMetrics.command = lowPriorityCmd.concat(["bash", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 50 ipv6.route-metric 50'; " + "nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 100 ipv6.route-metric 100'"]);
}
setRouteMetrics.running = true;
}
Process {
id: setRouteMetrics
running: false
onExited: exitCode => {
log.debug("Set route metrics process exited with code:", exitCode);
if (exitCode === 0) {
restartConnections.running = true;
}
}
}
Process {
id: restartConnections
command: lowPriorityCmd.concat(["bash", "-c", "nmcli -t -f UUID,TYPE connection show --active | " + "grep -E '802-11-wireless|802-3-ethernet' | cut -d: -f1 | " + "xargs -I {} sh -c 'nmcli connection down {} && nmcli connection up {}'"])
running: false
onExited: {
root.changingPreference = false;
root.targetPreference = "";
doRefreshNetworkState();
}
}
function fetchNetworkInfo(ssid) {
root.networkInfoSSID = ssid;
root.networkInfoLoading = true;
root.networkInfoDetails = "Loading network information...";
wifiInfoFetcher.running = true;
}
Process {
id: wifiInfoFetcher
command: lowPriorityCmd.concat(["nmcli", "-t", "-f", "SSID,SIGNAL,SECURITY,FREQ,RATE,MODE,CHAN,WPA-FLAGS,RSN-FLAGS,ACTIVE,BSSID", "dev", "wifi", "list"])
running: false
stdout: StdioCollector {
onStreamFinished: {
let details = "";
if (text.trim()) {
const lines = text.trim().split('\n');
const bands = [];
for (const line of lines) {
const parts = line.split(':');
if (parts.length >= 11 && parts[0] === root.networkInfoSSID) {
const signal = parts[1] || "0";
const security = parts[2] || "Open";
const freq = parts[3] || "Unknown";
const rate = parts[4] || "Unknown";
const channel = parts[6] || "Unknown";
const isActive = parts[9] === "yes";
let colonCount = 0;
let bssidStart = -1;
for (var i = 0; i < line.length; i++) {
if (line[i] === ':') {
colonCount++;
if (colonCount === 10) {
bssidStart = i + 1;
break;
}
}
}
const bssid = bssidStart >= 0 ? line.substring(bssidStart).replace(/\\:/g, ":") : "";
let band = "Unknown";
const 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";
}
bands.push({
"band": band,
"freq": freq,
"channel": channel,
"signal": signal,
"rate": rate,
"security": security,
"isActive": isActive,
"bssid": bssid
});
}
}
if (bands.length > 0) {
bands.sort((a, b) => {
if (a.isActive && !b.isActive) {
return -1;
}
if (!a.isActive && b.isActive) {
return 1;
}
return parseInt(b.signal) - parseInt(a.signal);
});
for (var i = 0; i < bands.length; i++) {
const b = bands[i];
if (b.isActive) {
details += "● " + b.band + " (Connected) - " + b.signal + "%\\n";
} else {
details += " " + b.band + " - " + b.signal + "%\\n";
}
details += " Channel " + b.channel + " (" + b.freq + " MHz) • " + b.rate + " Mbit/s\\n";
details += " " + b.bssid;
if (i < bands.length - 1) {
details += "\\n\\n";
}
}
}
}
if (details === "") {
details = "Network information not found or network not available.";
}
root.networkInfoDetails = details;
root.networkInfoLoading = false;
}
}
onExited: exitCode => {
root.networkInfoLoading = false;
if (exitCode !== 0) {
root.networkInfoDetails = "Failed to fetch network information";
}
}
}
function enableWifiDevice() {
wifiDeviceEnabler.running = true;
}
Process {
id: wifiDeviceEnabler
command: lowPriorityCmd.concat(["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: exitCode => {
if (exitCode === 0) {
ToastService.showInfo("WiFi enabled");
} else {
ToastService.showError("Failed to enable WiFi");
}
doRefreshNetworkState();
}
}
function connectToWifiAndSetPreference(ssid, password) {
connectToWifi(ssid, password);
setNetworkPreference("wifi");
}
function toggleNetworkConnection(type) {
if (type === "ethernet") {
if (root.networkStatus === "ethernet") {
ethernetDisconnector.running = true;
} else {
ethernetConnector.running = true;
}
}
}
Process {
id: ethernetDisconnector
command: lowPriorityCmd.concat(["sh", "-c", "nmcli device disconnect $(nmcli -t -f DEVICE,TYPE device | grep ethernet | cut -d: -f1 | head -1)"])
running: false
onExited: function (exitCode) {
doRefreshNetworkState();
}
}
Process {
id: ethernetConnector
command: lowPriorityCmd.concat(["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\"; else echo \"No ethernet device found\"; exit 1; fi"])
running: false
onExited: function (exitCode) {
doRefreshNetworkState();
}
}
function getNetworkInfo(ssid) {
const network = root.wifiNetworks.find(n => n.ssid === ssid);
if (!network) {
return null;
}
return {
"ssid": network.ssid,
"signal": network.signal,
"secured": network.secured,
"saved": network.saved,
"connected": network.connected,
"bssid": network.bssid
};
}
}