import QtQuick import Quickshell import Quickshell.Io import "." as M M.BarSection { id: root spacing: M.Theme.moduleSpacing tooltip: "" property string ifname: "" property string essid: "" property string state: "disconnected" property string ipAddr: "" property string signal: "" Process { id: proc running: true command: ["sh", "-c", "line=$(nmcli -t -f NAME,TYPE,DEVICE connection show --active 2>/dev/null | head -1); if [ -z \"$line\" ]; then dev=$(nmcli -t -f DEVICE,STATE device 2>/dev/null | grep ':connected' | grep -v ':unmanaged\\|:unavailable\\|:disconnected\\|:connecting' | head -1 | cut -d: -f1); [ -n \"$dev\" ] && line=\"linked:linked:$dev\"; fi; [ -z \"$line\" ] && exit 0; echo \"$line\"; dev=$(echo \"$line\" | cut -d: -f3); ip=$(nmcli -t -f IP4.ADDRESS device show \"$dev\" 2>/dev/null | head -1 | cut -d: -f2); echo \"ip:${ip:-}\"; sig=$(nmcli -t -f GENERAL.SIGNAL device show \"$dev\" 2>/dev/null | head -1 | cut -d: -f2); echo \"sig:${sig:-}\""] stdout: StdioCollector { onStreamFinished: { const lines = text.trim().split("\n"); if (!lines[0]) { root.state = "disconnected"; root.essid = ""; root.ifname = ""; root.ipAddr = ""; root.signal = ""; return; } const parts = lines[0].split(":"); root.essid = parts[0] || ""; root.ifname = parts[2] || ""; if ((parts[1] || "").includes("wireless")) root.state = "wifi"; else if (parts[0] === "linked") root.state = "linked"; else root.state = "eth"; // Parse extra info lines root.ipAddr = ""; root.signal = ""; for (let i = 1; i < lines.length; i++) { if (lines[i].startsWith("ip:")) root.ipAddr = lines[i].slice(3); else if (lines[i].startsWith("sig:")) root.signal = lines[i].slice(4); } } } } // Event-driven: re-poll on any network change Process { id: monitor running: true command: ["nmcli", "monitor"] stdout: SplitParser { splitMarker: "\n" onRead: _debounce.restart() } } Timer { id: _debounce interval: 300 onTriggered: { proc.running = true; networkMenu.triggerRefresh(); } } // Fallback poll Timer { interval: 60000 running: true repeat: true onTriggered: proc.running = true } M.BarIcon { icon: { if (root.state === "wifi") return "\uF1EB"; if (root.state === "eth") return "\uDB80\uDE00"; if (root.state === "linked") return "\uDB85\uDE16"; return "\uDB82\uDCFD"; } color: root.state === "disconnected" ? M.Theme.base08 : root.accentColor anchors.verticalCenter: parent.verticalCenter } M.BarLabel { visible: root.state === "wifi" label: root.essid color: root.state === "disconnected" ? M.Theme.base08 : root.accentColor anchors.verticalCenter: parent.verticalCenter } required property var bar readonly property bool _anyHover: root._hovered || networkMenu.panelHovered || networkMenu._busy M.NetworkMenu { id: networkMenu showPanel: root._anyHover screen: root.bar.screen anchorItem: root accentColor: root.accentColor } }