pragma ComponentBehavior: Bound // NoSignal Quick Settings popout (off the media / battery pill). Avatar + user + // uptime + power button; 2-col toggle grid; brightness + volume sliders; media // card. Wired to the real services (Network, Bluetooth, Notifs, Audio, // Brightness, Players). Night Light drives hyprsunset; Airplane drives the // NetworkManager + Bluetooth radios. (VPN tile removed pending a real backend.) import QtQuick import QtQuick.Layouts import Quickshell import Quickshell.Io import Quickshell.Bluetooth import qs.services import qs.utils import qs.components NsPanel { id: root implicitWidth: 380 anchorMode: "right" readonly property var brightMon: Brightness.monitors[0] ?? null // Night Light state tracks the real hyprsunset process rather than a local // flag, so the tile stays correct across shell reloads or changes made // elsewhere. Seeded on load (probe runs immediately), reconciled on a timer, // and re-checked right after a toggle. property bool nightLightOn: false Process { id: nightProbe command: ["pgrep", "-x", "hyprsunset"] running: true stdout: StdioCollector { onStreamFinished: root.nightLightOn = text.trim().length > 0 } } Timer { interval: 3000 running: true repeat: true onTriggered: nightProbe.running = true } Timer { id: nightRefresh interval: 500 repeat: false onTriggered: nightProbe.running = true } // ── Header ─────────────────────────────────────────────────────────── RowLayout { Layout.fillWidth: true spacing: 12 Rectangle { implicitWidth: 40 implicitHeight: 40 radius: 0 gradient: Gradient { orientation: Gradient.Vertical GradientStop { position: 0 color: Theme.accent } GradientStop { position: 1 color: Theme.blue } } StyledText { anchors.centerIn: parent text: (SysInfo.user || "?").charAt(0).toUpperCase() color: Theme.onAccent font.family: Theme.font.family font.pixelSize: Theme.font.body font.weight: Font.Bold } } ColumnLayout { spacing: 0 StyledText { text: SysInfo.user || "user" color: Theme.text font.family: Theme.font.family font.pixelSize: Theme.font.panelTitle font.weight: Font.DemiBold } StyledText { text: "uptime " + SysInfo.uptime color: Theme.textMuted font.family: Theme.font.family font.pixelSize: Theme.font.bodySmall } } Item { Layout.fillWidth: true } Rectangle { implicitWidth: 34 implicitHeight: 34 radius: 0 color: pwrMa.containsMouse ? Theme.accentSoft : Theme.fillSubtle NsIcon { anchors.centerIn: parent icon: "power_settings_new" color: Theme.danger } MouseArea { id: pwrMa anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: NsShell.show("power", 0) } } } // ── Toggle grid ────────────────────────────────────────────────────── GridLayout { Layout.fillWidth: true columns: 2 rowSpacing: 8 columnSpacing: 8 QSToggle { icon: "wifi" label: "Wi-Fi" sub: Network.wifiEnabled ? Network.active?.ssid ?? "On" : "Off" on: Network.wifiEnabled onToggled: Network.toggleWifi() } QSToggle { icon: "bluetooth" label: "Bluetooth" sub: Bluetooth.defaultAdapter?.enabled ? "On" : "Off" on: Bluetooth.defaultAdapter?.enabled ?? false onToggled: if (Bluetooth.defaultAdapter) Bluetooth.defaultAdapter.enabled = !Bluetooth.defaultAdapter.enabled } QSToggle { icon: "do_not_disturb_on" label: "Do Not Disturb" sub: Notifs.dnd ? "On" : "Off" on: Notifs.dnd onToggled: Notifs.dnd = !Notifs.dnd } QSToggle { id: nightTog icon: "nightlight" label: "Night Light" sub: on ? "Warm 3500K" : "Off" on: root.nightLightOn onToggled: { if (root.nightLightOn) Quickshell.execDetached(["pkill", "-x", "hyprsunset"]); else Quickshell.execDetached(["sh", "-c", "pkill -x hyprsunset; hyprsunset -t 3500"]); nightRefresh.restart(); } } QSToggle { id: airTog icon: "airplanemode_active" label: "Airplane" // Reflects the real radio state: airplane is "On" when both Wi-Fi and // Bluetooth are down. Network.wifiEnabled tracks nmcli; the adapter // tracks BlueZ, so the tile self-corrects if radios change elsewhere. readonly property bool radiosOff: !Network.wifiEnabled && !(Bluetooth.defaultAdapter?.enabled ?? false) sub: radiosOff ? "On" : "Off" on: radiosOff onToggled: { if (radiosOff) Quickshell.execDetached(["sh", "-c", "nmcli radio all on; bluetoothctl power on"]); else Quickshell.execDetached(["sh", "-c", "nmcli radio all off; bluetoothctl power off"]); } } } // ── Sliders ────────────────────────────────────────────────────────── QSSlider { icon: "brightness_6" value: root.brightMon?.brightness ?? 0 visible: root.brightMon !== null onMoved: v => root.brightMon?.setBrightness(v) } QSSlider { icon: Audio.muted ? "volume_off" : "volume_up" value: Audio.volume onMoved: v => Audio.setVolume(v) } // ── Media card ─────────────────────────────────────────────────────── Rectangle { Layout.fillWidth: true Layout.topMargin: 4 implicitHeight: 80 radius: Theme.radius.tile color: Theme.fillSubtle visible: Players.active !== null RowLayout { anchors.fill: parent anchors.margins: 12 spacing: 12 Rectangle { implicitWidth: 56 implicitHeight: 56 radius: 0 gradient: Gradient { orientation: Gradient.Vertical GradientStop { position: 0 color: Theme.accent } GradientStop { position: 1 color: Theme.blue } } NsIcon { anchors.centerIn: parent icon: "music_note" color: Theme.onAccent } } ColumnLayout { Layout.fillWidth: true spacing: 2 StyledText { Layout.fillWidth: true text: Players.active?.trackTitle || "Awake" color: Theme.text elide: Text.ElideRight font.family: Theme.font.family font.pixelSize: Theme.font.body font.weight: Font.DemiBold } StyledText { Layout.fillWidth: true text: Players.active?.trackArtist || "" color: Theme.textMuted elide: Text.ElideRight font.family: Theme.font.family font.pixelSize: Theme.font.bodySmall } RowLayout { spacing: 16 Layout.topMargin: 2 MediaBtn { icon: "skip_previous" onActivated: Players.previous() } MediaBtn { icon: Players.active?.isPlaying ? "pause" : "play_arrow" onActivated: Players.togglePlaying() } MediaBtn { icon: "skip_next" onActivated: Players.next() } } } } } // ── Reusable bits ──────────────────────────────────────────────────── component QSToggle: Rectangle { id: tile property string icon property string label property string sub property bool on: false signal toggled Layout.fillWidth: true implicitHeight: 56 radius: Theme.radius.button color: tile.on ? Theme.accentSoft : Theme.fillSubtle border.width: tile.on ? 1 : 0 border.color: Theme.accent RowLayout { anchors.fill: parent anchors.margins: 11 spacing: 10 Rectangle { implicitWidth: 30 implicitHeight: 30 radius: 0 color: tile.on ? Theme.accent : Qt.rgba(1, 1, 1, 0.06) NsIcon { anchors.centerIn: parent icon: tile.icon color: tile.on ? Theme.onAccent : Theme.text } } ColumnLayout { spacing: 0 StyledText { text: tile.label color: Theme.text font.family: Theme.font.family font.pixelSize: Theme.font.bodySmall font.weight: Font.Medium } StyledText { text: tile.sub color: Theme.textMuted font.family: Theme.font.family font.pixelSize: Theme.font.meta } } } MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: tile.toggled() } } component QSSlider: RowLayout { id: s property string icon property real value: 0 signal moved(real v) Layout.fillWidth: true spacing: 10 NsIcon { icon: s.icon color: Theme.textMuted } Rectangle { id: track Layout.fillWidth: true implicitHeight: 6 radius: 0 color: Theme.fillSubtle Rectangle { width: parent.width * Math.max(0, Math.min(1, s.value)) height: parent.height radius: 0 color: Theme.accent } Rectangle { x: parent.width * Math.max(0, Math.min(1, s.value)) - width / 2 anchors.verticalCenter: parent.verticalCenter implicitWidth: 14 implicitHeight: 14 radius: 0 color: Theme.accent } MouseArea { anchors.fill: parent onPressed: e => s.moved(Math.max(0, Math.min(1, e.x / width))) onPositionChanged: e => { if (pressed) s.moved(Math.max(0, Math.min(1, e.x / width))); } } } StyledText { text: Math.round(s.value * 100) + "%" color: Theme.textMuted font.family: Theme.font.family font.pixelSize: Theme.font.meta } } component MediaBtn: Rectangle { property string icon signal activated implicitWidth: 28 implicitHeight: 28 radius: 0 color: mbm.containsMouse ? Theme.hover : "transparent" NsIcon { anchors.centerIn: parent icon: parent.icon color: Theme.text } MouseArea { id: mbm anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: parent.activated() } } }