diff --git a/modules/Backlight.qml b/modules/Backlight.qml index 4b36226..7ac38a1 100644 --- a/modules/Backlight.qml +++ b/modules/Backlight.qml @@ -16,7 +16,8 @@ M.BarSection { property bool _osdActive: false readonly property bool _showPanel: root._hovered || _panelHovered || _osdActive - onPercentChanged: if (percent > 0) _flashPanel() + onPercentChanged: if (percent > 0) + _flashPanel() function _flashPanel() { _osdActive = true; @@ -56,7 +57,8 @@ M.BarSection { stdout: StdioCollector { onStreamFinished: { const dev = text.trim(); - if (dev) root._blDev = "/sys/class/backlight/" + dev; + if (dev) + root._blDev = "/sys/class/backlight/" + dev; } } } @@ -114,10 +116,7 @@ M.BarSection { anchors.left: true margins.top: 0 - margins.left: Math.max(0, Math.min( - Math.round(root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0) - implicitWidth / 2), - (panel.screen?.width ?? 1920) - implicitWidth - )) + margins.left: Math.max(0, Math.min(Math.round(root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0) - implicitWidth / 2), (panel.screen?.width ?? 1920) - implicitWidth)) implicitWidth: panelContent.width implicitHeight: panelContent.height @@ -138,14 +137,38 @@ M.BarSection { ParallelAnimation { id: showAnim - NumberAnimation { target: panelContent; property: "opacity"; to: 1; duration: 120; easing.type: Easing.OutCubic } - NumberAnimation { target: panelContent; property: "y"; to: 0; duration: 150; easing.type: Easing.OutCubic } + NumberAnimation { + target: panelContent + property: "opacity" + to: 1 + duration: 120 + easing.type: Easing.OutCubic + } + NumberAnimation { + target: panelContent + property: "y" + to: 0 + duration: 150 + easing.type: Easing.OutCubic + } } ParallelAnimation { id: hideAnim - NumberAnimation { target: panelContent; property: "opacity"; to: 0; duration: 150; easing.type: Easing.InCubic } - NumberAnimation { target: panelContent; property: "y"; to: -panelContent.height; duration: 150; easing.type: Easing.InCubic } + NumberAnimation { + target: panelContent + property: "opacity" + to: 0 + duration: 150 + easing.type: Easing.InCubic + } + NumberAnimation { + target: panelContent + property: "y" + to: -panelContent.height + duration: 150 + easing.type: Easing.InCubic + } onFinished: panel._winVisible = false } @@ -210,7 +233,11 @@ M.BarSection { color: M.Theme.base0A radius: 3 - Behavior on width { NumberAnimation { duration: 80 } } + Behavior on width { + NumberAnimation { + duration: 80 + } + } } MouseArea { @@ -218,7 +245,10 @@ M.BarSection { anchors.margins: -6 cursorShape: Qt.PointingHandCursor onPressed: mouse => _set(mouse) - onPositionChanged: mouse => { if (pressed) _set(mouse); } + onPositionChanged: mouse => { + if (pressed) + _set(mouse); + } function _set(mouse) { root.setPercent(mouse.x / slider.width * 100); } diff --git a/modules/Bar.qml b/modules/Bar.qml index 44f0fce..701c70b 100644 --- a/modules/Bar.qml +++ b/modules/Bar.qml @@ -34,8 +34,14 @@ PanelWindow { height: 3 gradient: Gradient { orientation: Gradient.Horizontal - GradientStop { position: 0; color: M.Theme.base0C } - GradientStop { position: 1; color: M.Theme.base09 } + GradientStop { + position: 0 + color: M.Theme.base0C + } + GradientStop { + position: 1 + color: M.Theme.base09 + } } } @@ -53,8 +59,12 @@ PanelWindow { M.BarGroup { borderColor: M.Theme.base0D - M.Clock { visible: M.Modules.clock.enable } - M.Notifications { visible: M.Modules.notifications.enable } + M.Clock { + visible: M.Modules.clock.enable + } + M.Notifications { + visible: M.Modules.notifications.enable + } } } @@ -67,11 +77,17 @@ PanelWindow { M.BarGroup { borderColor: M.Theme.base0D - M.Workspaces { bar: bar; visible: M.Modules.workspaces.enable } + M.Workspaces { + bar: bar + visible: M.Modules.workspaces.enable + } } M.BarGroup { borderColor: M.Theme.base0D - M.Tray { bar: bar; visible: M.Modules.tray.enable } + M.Tray { + bar: bar + visible: M.Modules.tray.enable + } } M.BarGroup { borderColor: M.Theme.base0D @@ -80,7 +96,9 @@ PanelWindow { visible: M.Modules.windowTitle.enable } } - Item { Layout.fillWidth: true } + Item { + Layout.fillWidth: true + } } // ---- right ---- @@ -90,45 +108,73 @@ PanelWindow { anchors.verticalCenter: parent.verticalCenter spacing: M.Theme.barSpacing - Item { Layout.fillWidth: true } + Item { + Layout.fillWidth: true + } // Media M.BarGroup { borderColor: M.Theme.base0E - M.Mpris { bar: bar } - M.Volume { visible: M.Modules.volume.enable } + M.Mpris { + bar: bar + } + M.Volume { + visible: M.Modules.volume.enable + } } // Connectivity M.BarGroup { borderColor: M.Theme.base0D - M.Network { bar: bar; visible: M.Modules.network.enable } - M.Bluetooth { bar: bar } + M.Network { + bar: bar + visible: M.Modules.network.enable + } + M.Bluetooth { + bar: bar + } } // Controls M.BarGroup { borderColor: M.Theme.base0A M.Backlight {} - M.PowerProfile { visible: M.Modules.powerProfile.enable } - M.IdleInhibitor { visible: M.Modules.idleInhibitor.enable } + M.PowerProfile { + visible: M.Modules.powerProfile.enable + } + M.IdleInhibitor { + visible: M.Modules.idleInhibitor.enable + } } // Stats M.BarGroup { borderColor: M.Theme.base08 - M.Cpu { visible: M.Modules.cpu.enable } - M.Memory { visible: M.Modules.memory.enable } - M.Temperature { visible: M.Modules.temperature.enable } - M.Weather { visible: M.Modules.weather.enable } - M.Disk { visible: M.Modules.disk.enable } + M.Cpu { + visible: M.Modules.cpu.enable + } + M.Memory { + visible: M.Modules.memory.enable + } + M.Temperature { + visible: M.Modules.temperature.enable + } + M.Weather { + visible: M.Modules.weather.enable + } + M.Disk { + visible: M.Modules.disk.enable + } } // Power M.BarGroup { borderColor: M.Theme.base08 M.Battery {} - M.Power { bar: bar; visible: M.Modules.power.enable } + M.Power { + bar: bar + visible: M.Modules.power.enable + } } } } diff --git a/modules/BarGroup.qml b/modules/BarGroup.qml index 718b2e7..460b366 100644 --- a/modules/BarGroup.qml +++ b/modules/BarGroup.qml @@ -41,8 +41,14 @@ Item { anchors.fill: parent radius: M.Theme.radius gradient: Gradient { - GradientStop { position: 0; color: Qt.rgba(root.borderColor.r, root.borderColor.g, root.borderColor.b, 0.15) } - GradientStop { position: 1; color: "transparent" } + GradientStop { + position: 0 + color: Qt.rgba(root.borderColor.r, root.borderColor.g, root.borderColor.b, 0.15) + } + GradientStop { + position: 1 + color: "transparent" + } } } diff --git a/modules/BarIcon.qml b/modules/BarIcon.qml index a034e04..dcc768c 100644 --- a/modules/BarIcon.qml +++ b/modules/BarIcon.qml @@ -21,9 +21,23 @@ Text { SequentialAnimation { id: _crossfade - NumberAnimation { target: root; property: "opacity"; to: 0; duration: 60; easing.type: Easing.InQuad } - ScriptAction { script: root._displayIcon = root._pendingIcon } - NumberAnimation { target: root; property: "opacity"; to: 1; duration: 100; easing.type: Easing.OutQuad } + NumberAnimation { + target: root + property: "opacity" + to: 0 + duration: 60 + easing.type: Easing.InQuad + } + ScriptAction { + script: root._displayIcon = root._pendingIcon + } + NumberAnimation { + target: root + property: "opacity" + to: 1 + duration: 100 + easing.type: Easing.OutQuad + } } color: M.Theme.base05 font.pixelSize: M.Theme.fontSize + 1 diff --git a/modules/BarSection.qml b/modules/BarSection.qml index 292ba69..59c118e 100644 --- a/modules/BarSection.qml +++ b/modules/BarSection.qml @@ -8,7 +8,11 @@ Row { property string tooltip: "" property bool _hovered: false - Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on opacity { + NumberAnimation { + duration: 150 + } + } layer.enabled: _hovered layer.effect: MultiEffect { diff --git a/modules/Battery.qml b/modules/Battery.qml index 4282dd7..2f8884a 100644 --- a/modules/Battery.qml +++ b/modules/Battery.qml @@ -28,19 +28,37 @@ M.BarSection { SequentialAnimation { running: root._critical loops: Animation.Infinite - NumberAnimation { target: root; property: "_blinkOpacity"; to: 0.2; duration: 400; easing.type: Easing.InOutQuad } - NumberAnimation { target: root; property: "_blinkOpacity"; to: 1; duration: 400; easing.type: Easing.InOutQuad } - onRunningChanged: if (!running) root._blinkOpacity = 1 + NumberAnimation { + target: root + property: "_blinkOpacity" + to: 0.2 + duration: 400 + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: root + property: "_blinkOpacity" + to: 1 + duration: 400 + easing.type: Easing.InOutQuad + } + onRunningChanged: if (!running) + root._blinkOpacity = 1 } property bool _warnSent: false property bool _critSent: false - onChargingChanged: { _warnSent = false; _critSent = false; } + onChargingChanged: { + _warnSent = false; + _critSent = false; + } onPctChanged: { - if (charging) return; + if (charging) + return; if (pct < _critThresh && !_critSent) { - _critSent = true; _warnSent = true; + _critSent = true; + _warnSent = true; _notif.command = ["notify-send", "--urgency=critical", "--icon=battery-low", "--category=device", "Very Low Battery", "Connect to power now!"]; _notif.running = true; } else if (pct < _warnThresh && !_warnSent) { @@ -50,7 +68,9 @@ M.BarSection { } } - Process { id: _notif } + Process { + id: _notif + } M.BarIcon { icon: { diff --git a/modules/Bluetooth.qml b/modules/Bluetooth.qml index 558084a..ee55f22 100644 --- a/modules/Bluetooth.qml +++ b/modules/Bluetooth.qml @@ -72,7 +72,10 @@ M.BarSection { TapHandler { acceptedButtons: Qt.LeftButton cursorShape: Qt.PointingHandCursor - onTapped: { menuLoader.active = !menuLoader.active; M.FlyoutState.visible = false; } + onTapped: { + menuLoader.active = !menuLoader.active; + M.FlyoutState.visible = false; + } } TapHandler { diff --git a/modules/BluetoothMenu.qml b/modules/BluetoothMenu.qml index 3704070..f4d58f2 100644 --- a/modules/BluetoothMenu.qml +++ b/modules/BluetoothMenu.qml @@ -13,23 +13,18 @@ M.PopupPanel { property Process _scanner: Process { id: scanner running: true - command: ["sh", "-c", - "bluetoothctl devices Paired 2>/dev/null | while read -r _ mac name; do " + - "info=$(bluetoothctl info \"$mac\" 2>/dev/null); " + - "conn=$(echo \"$info\" | grep -c 'Connected: yes'); " + - "bat=$(echo \"$info\" | awk -F'[(): ]' '/Battery Percentage/{for(i=1;i<=NF;i++) if($i+0==$i && $i!=\"\") print $i}'); " + - "echo \"$mac:$conn:${bat:-}:$name\"; " + - "done" - ] + command: ["sh", "-c", "bluetoothctl devices Paired 2>/dev/null | while read -r _ mac name; do " + "info=$(bluetoothctl info \"$mac\" 2>/dev/null); " + "conn=$(echo \"$info\" | grep -c 'Connected: yes'); " + "bat=$(echo \"$info\" | awk -F'[(): ]' '/Battery Percentage/{for(i=1;i<=NF;i++) if($i+0==$i && $i!=\"\") print $i}'); " + "echo \"$mac:$conn:${bat:-}:$name\"; " + "done"] stdout: StdioCollector { onStreamFinished: { const devs = []; for (const line of text.trim().split("\n")) { - if (!line) continue; + if (!line) + continue; const i1 = line.indexOf(":"); const i2 = line.indexOf(":", i1 + 1); const i3 = line.indexOf(":", i2 + 1); - if (i3 < 0) continue; + if (i3 < 0) + continue; devs.push({ mac: line.slice(0, i1), connected: line.slice(i1 + 1, i2) === "1", @@ -38,7 +33,8 @@ M.PopupPanel { }); } devs.sort((a, b) => { - if (a.connected !== b.connected) return a.connected ? -1 : 1; + if (a.connected !== b.connected) + return a.connected ? -1 : 1; return a.name.localeCompare(b.name); }); menuWindow._devices = devs; @@ -51,7 +47,8 @@ M.PopupPanel { property string action: "" property string mac: "" command: ["bluetoothctl", action, mac] - onRunningChanged: if (!running) scanner.running = true + onRunningChanged: if (!running) + scanner.running = true } Repeater { diff --git a/modules/Flyout.qml b/modules/Flyout.qml index fe0f9ac..5570635 100644 --- a/modules/Flyout.qml +++ b/modules/Flyout.qml @@ -33,24 +33,45 @@ PanelWindow { anchors.left: true margins.top: 0 - margins.left: Math.max(0, Math.min( - Math.round(M.FlyoutState.itemX - implicitWidth / 2), - screen.width - implicitWidth - )) + margins.left: Math.max(0, Math.min(Math.round(M.FlyoutState.itemX - implicitWidth / 2), screen.width - implicitWidth)) implicitWidth: label.implicitWidth + M.Theme.barPadding * 2 implicitHeight: label.implicitHeight + M.Theme.barPadding * 2 ParallelAnimation { id: showAnim - NumberAnimation { target: content; property: "opacity"; to: 1; duration: 120; easing.type: Easing.OutCubic } - NumberAnimation { target: content; property: "y"; to: 0; duration: 150; easing.type: Easing.OutCubic } + NumberAnimation { + target: content + property: "opacity" + to: 1 + duration: 120 + easing.type: Easing.OutCubic + } + NumberAnimation { + target: content + property: "y" + to: 0 + duration: 150 + easing.type: Easing.OutCubic + } } ParallelAnimation { id: hideAnim - NumberAnimation { target: content; property: "opacity"; to: 0; duration: 150; easing.type: Easing.InCubic } - NumberAnimation { target: content; property: "y"; to: -content.height; duration: 150; easing.type: Easing.InCubic } + NumberAnimation { + target: content + property: "opacity" + to: 0 + duration: 150 + easing.type: Easing.InCubic + } + NumberAnimation { + target: content + property: "y" + to: -content.height + duration: 150 + easing.type: Easing.InCubic + } onFinished: root._winVisible = false } diff --git a/modules/Modules.qml b/modules/Modules.qml index 7a978e0..1e0702b 100644 --- a/modules/Modules.qml +++ b/modules/Modules.qml @@ -7,25 +7,77 @@ import Quickshell.Io QtObject { id: root - property var workspaces: ({ enable: true }) - property var tray: ({ enable: true }) - property var windowTitle: ({ enable: true }) - property var clock: ({ enable: true }) - property var notifications: ({ enable: true }) - property var mpris: ({ enable: true }) - property var volume: ({ enable: true }) - property var bluetooth: ({ enable: true, interval: 5000 }) - property var backlight: ({ enable: true, step: 5 }) - property var network: ({ enable: true, interval: 5000 }) - property var powerProfile: ({ enable: true, interval: 5000 }) - property var idleInhibitor: ({ enable: true }) - property var weather: ({ enable: true, args: ["--nerd"], interval: 3600000 }) - property var temperature: ({ enable: true, interval: 2000, warm: 60, hot: 80 }) - property var cpu: ({ enable: true, interval: 1000 }) - property var memory: ({ enable: true, interval: 2000 }) - property var disk: ({ enable: true, interval: 30000 }) - property var battery: ({ enable: true, warning: 25, critical: 15 }) - property var power: ({ enable: true }) + property var workspaces: ({ + enable: true + }) + property var tray: ({ + enable: true + }) + property var windowTitle: ({ + enable: true + }) + property var clock: ({ + enable: true + }) + property var notifications: ({ + enable: true + }) + property var mpris: ({ + enable: true + }) + property var volume: ({ + enable: true + }) + property var bluetooth: ({ + enable: true, + interval: 5000 + }) + property var backlight: ({ + enable: true, + step: 5 + }) + property var network: ({ + enable: true, + interval: 5000 + }) + property var powerProfile: ({ + enable: true, + interval: 5000 + }) + property var idleInhibitor: ({ + enable: true + }) + property var weather: ({ + enable: true, + args: ["--nerd"], + interval: 3600000 + }) + property var temperature: ({ + enable: true, + interval: 2000, + warm: 60, + hot: 80 + }) + property var cpu: ({ + enable: true, + interval: 1000 + }) + property var memory: ({ + enable: true, + interval: 2000 + }) + property var disk: ({ + enable: true, + interval: 30000 + }) + property var battery: ({ + enable: true, + warning: 25, + critical: 15 + }) + property var power: ({ + enable: true + }) property FileView _file: FileView { path: (Quickshell.env("XDG_CONFIG_HOME") || (Quickshell.env("HOME") + "/.config")) + "/nova-shell/modules.json" @@ -42,12 +94,15 @@ QtObject { return; } for (const k of Object.keys(data)) { - if (!(k in root)) continue; + if (!(k in root)) + continue; const v = data[k]; if (typeof v === "object" && v !== null) root[k] = Object.assign({}, root[k], v); else if (typeof v === "boolean") - root[k] = Object.assign({}, root[k], { enable: v }); + root[k] = Object.assign({}, root[k], { + enable: v + }); } } } diff --git a/modules/Mpris.qml b/modules/Mpris.qml index 17f7c7f..d596571 100644 --- a/modules/Mpris.qml +++ b/modules/Mpris.qml @@ -19,8 +19,12 @@ M.BarSection { // Cache art URL at root level so it's captured even when panel is hidden readonly property string _artUrl: player?.trackArtUrl ?? "" readonly property string _currentTrack: player?.trackTitle ?? "" - on_ArtUrlChanged: if (_artUrl) _cachedArt = _artUrl - on_CurrentTrackChanged: if (_currentTrack !== _artTrack) { _artTrack = _currentTrack; _cachedArt = _artUrl || "" } + on_ArtUrlChanged: if (_artUrl) + _cachedArt = _artUrl + on_CurrentTrackChanged: if (_currentTrack !== _artTrack) { + _artTrack = _currentTrack; + _cachedArt = _artUrl || ""; + } // Preload art while panel is hidden — ensures QML image cache has the pixels Image { @@ -89,10 +93,7 @@ M.BarSection { anchors.left: true margins.top: 0 - margins.left: Math.max(0, Math.min( - Math.round(root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0) - implicitWidth / 2), - (panel.screen?.width ?? 1920) - implicitWidth - )) + margins.left: Math.max(0, Math.min(Math.round(root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0) - implicitWidth / 2), (panel.screen?.width ?? 1920) - implicitWidth)) implicitWidth: panelContent.width implicitHeight: panelContent.height @@ -113,14 +114,38 @@ M.BarSection { ParallelAnimation { id: showAnim - NumberAnimation { target: panelContent; property: "opacity"; to: 1; duration: 120; easing.type: Easing.OutCubic } - NumberAnimation { target: panelContent; property: "y"; to: 0; duration: 150; easing.type: Easing.OutCubic } + NumberAnimation { + target: panelContent + property: "opacity" + to: 1 + duration: 120 + easing.type: Easing.OutCubic + } + NumberAnimation { + target: panelContent + property: "y" + to: 0 + duration: 150 + easing.type: Easing.OutCubic + } } ParallelAnimation { id: hideAnim - NumberAnimation { target: panelContent; property: "opacity"; to: 0; duration: 150; easing.type: Easing.InCubic } - NumberAnimation { target: panelContent; property: "y"; to: -panelContent.height; duration: 150; easing.type: Easing.InCubic } + NumberAnimation { + target: panelContent + property: "opacity" + to: 0 + duration: 150 + easing.type: Easing.InCubic + } + NumberAnimation { + target: panelContent + property: "y" + to: -panelContent.height + duration: 150 + easing.type: Easing.InCubic + } onFinished: panel._winVisible = false } @@ -172,10 +197,14 @@ M.BarSection { source: root._cachedArt property bool _hasArt: false - onStatusChanged: if (status === Image.Ready) _hasArt = true + onStatusChanged: if (status === Image.Ready) + _hasArt = true Connections { target: root - function on_CachedArtChanged() { if (!root._cachedArt) _artImg._hasArt = false } + function on_CachedArtChanged() { + if (!root._cachedArt) + _artImg._hasArt = false; + } } } @@ -186,8 +215,14 @@ M.BarSection { height: 40 visible: _artImg.visible gradient: Gradient { - GradientStop { position: 0; color: "transparent" } - GradientStop { position: 1; color: M.Theme.base01 } + GradientStop { + position: 0 + color: "transparent" + } + GradientStop { + position: 1 + color: M.Theme.base01 + } } } @@ -229,7 +264,8 @@ M.BarSection { width: parent.width text: { const p = root.player; - if (!p) return ""; + if (!p) + return ""; const artist = Array.isArray(p.trackArtists) ? p.trackArtists.join(", ") : (p.trackArtists || ""); return [artist, p.trackAlbum].filter(s => s).join(" \u2014 "); } diff --git a/modules/Network.qml b/modules/Network.qml index c6f854d..47c9efc 100644 --- a/modules/Network.qml +++ b/modules/Network.qml @@ -10,7 +10,8 @@ M.BarSection { const parts = []; if (root.state === "wifi") { parts.push("WiFi: " + root.essid); - if (root.signal) parts.push("Signal: " + root.signal + "%"); + if (root.signal) + parts.push("Signal: " + root.signal + "%"); } else if (root.state === "eth") { parts.push("Ethernet"); } else if (root.state === "linked") { @@ -18,8 +19,10 @@ M.BarSection { } else { return "Disconnected"; } - if (root.ipAddr) parts.push("IP: " + root.ipAddr); - if (root.ifname) parts.push("Interface: " + root.ifname); + if (root.ipAddr) + parts.push("IP: " + root.ipAddr); + if (root.ifname) + parts.push("Interface: " + root.ifname); return parts.join("\n"); } @@ -96,7 +99,10 @@ M.BarSection { TapHandler { cursorShape: Qt.PointingHandCursor - onTapped: { menuLoader.active = !menuLoader.active; M.FlyoutState.visible = false; } + onTapped: { + menuLoader.active = !menuLoader.active; + M.FlyoutState.visible = false; + } } Loader { diff --git a/modules/NetworkMenu.qml b/modules/NetworkMenu.qml index 2c26119..7b3ca65 100644 --- a/modules/NetworkMenu.qml +++ b/modules/NetworkMenu.qml @@ -13,12 +13,7 @@ M.PopupPanel { property Process _scanner: Process { id: scanner running: true - command: ["sh", "-c", - "echo '---CONNS---';" + - "nmcli -t -f NAME,UUID,TYPE,ACTIVE connection show 2>/dev/null;" + - "echo '---WIFI---';" + - "nmcli -t -f SSID,SIGNAL device wifi list --rescan no 2>/dev/null" - ] + command: ["sh", "-c", "echo '---CONNS---';" + "nmcli -t -f NAME,UUID,TYPE,ACTIVE connection show 2>/dev/null;" + "echo '---WIFI---';" + "nmcli -t -f SSID,SIGNAL device wifi list --rescan no 2>/dev/null"] stdout: StdioCollector { onStreamFinished: { const sections = text.split("---WIFI---"); @@ -28,16 +23,19 @@ M.PopupPanel { // Visible SSIDs with signal const visible = {}; for (const l of wifiLines.trim().split("\n")) { - if (!l) continue; + if (!l) + continue; const parts = l.split(":"); const ssid = parts[0]; - if (ssid) visible[ssid] = parseInt(parts[1]) || 0; + if (ssid) + visible[ssid] = parseInt(parts[1]) || 0; } // Saved connections — filter: show wired always, wifi only if visible const nets = []; for (const l of connLines.trim().split("\n")) { - if (!l) continue; + if (!l) + continue; const parts = l.split(":"); const name = parts[0]; const uuid = parts[1]; @@ -45,7 +43,8 @@ M.PopupPanel { const active = parts[3] === "yes"; const isWifi = type.includes("wireless"); - if (isWifi && !(name in visible)) continue; + if (isWifi && !(name in visible)) + continue; nets.push({ name: name, @@ -58,8 +57,10 @@ M.PopupPanel { // Active first, then by signal (wifi) or name nets.sort((a, b) => { - if (a.active !== b.active) return a.active ? -1 : 1; - if (a.signal >= 0 && b.signal >= 0) return b.signal - a.signal; + if (a.active !== b.active) + return a.active ? -1 : 1; + if (a.signal >= 0 && b.signal >= 0) + return b.signal - a.signal; return a.name.localeCompare(b.name); }); @@ -72,14 +73,16 @@ M.PopupPanel { id: connectProc property string uuid: "" command: ["nmcli", "connection", "up", uuid] - onRunningChanged: if (!running) scanner.running = true + onRunningChanged: if (!running) + scanner.running = true } property Process _disconnectProc: Process { id: disconnectProc property string uuid: "" command: ["nmcli", "connection", "down", uuid] - onRunningChanged: if (!running) scanner.running = true + onRunningChanged: if (!running) + scanner.running = true } Repeater { diff --git a/modules/Notifications.qml b/modules/Notifications.qml index 6812277..81919ed 100644 --- a/modules/Notifications.qml +++ b/modules/Notifications.qml @@ -57,17 +57,31 @@ M.BarSection { id: countScale origin.x: countLabel.width / 2 origin.y: countLabel.height / 2 - xScale: 1; yScale: 1 + xScale: 1 + yScale: 1 } SequentialAnimation { id: popAnim - NumberAnimation { target: countScale; properties: "xScale,yScale"; to: 1.4; duration: 100; easing.type: Easing.OutQuad } - NumberAnimation { target: countScale; properties: "xScale,yScale"; to: 1.0; duration: 200; easing.type: Easing.OutElastic } + NumberAnimation { + target: countScale + properties: "xScale,yScale" + to: 1.4 + duration: 100 + easing.type: Easing.OutQuad + } + NumberAnimation { + target: countScale + properties: "xScale,yScale" + to: 1.0 + duration: 200 + easing.type: Easing.OutElastic + } } } - onCountChanged: if (count > 0) popAnim.start() + onCountChanged: if (count > 0) + popAnim.start() TapHandler { acceptedButtons: Qt.LeftButton diff --git a/modules/Osd.qml b/modules/Osd.qml index d3485fb..1aab452 100644 --- a/modules/Osd.qml +++ b/modules/Osd.qml @@ -35,24 +35,45 @@ PanelWindow { anchors.left: true margins.top: 0 - margins.left: Math.max(0, Math.min( - Math.round(M.OsdState.itemX - implicitWidth / 2), - screen.width - implicitWidth - )) + margins.left: Math.max(0, Math.min(Math.round(M.OsdState.itemX - implicitWidth / 2), screen.width - implicitWidth)) implicitWidth: 200 implicitHeight: 48 ParallelAnimation { id: showAnim - NumberAnimation { target: content; property: "opacity"; to: 1; duration: 150; easing.type: Easing.OutCubic } - NumberAnimation { target: content; property: "y"; to: 0; duration: 200; easing.type: Easing.OutCubic } + NumberAnimation { + target: content + property: "opacity" + to: 1 + duration: 150 + easing.type: Easing.OutCubic + } + NumberAnimation { + target: content + property: "y" + to: 0 + duration: 200 + easing.type: Easing.OutCubic + } } ParallelAnimation { id: hideAnim - NumberAnimation { target: content; property: "opacity"; to: 0; duration: 250; easing.type: Easing.InCubic } - NumberAnimation { target: content; property: "y"; to: -content.height; duration: 250; easing.type: Easing.InCubic } + NumberAnimation { + target: content + property: "opacity" + to: 0 + duration: 250 + easing.type: Easing.InCubic + } + NumberAnimation { + target: content + property: "y" + to: -content.height + duration: 250 + easing.type: Easing.InCubic + } onFinished: root._winVisible = false } @@ -104,7 +125,10 @@ PanelWindow { radius: 3 Behavior on width { - NumberAnimation { duration: 120; easing.type: Easing.OutCubic } + NumberAnimation { + duration: 120 + easing.type: Easing.OutCubic + } } } } diff --git a/modules/PopupPanel.qml b/modules/PopupPanel.qml index 8702254..8412c47 100644 --- a/modules/PopupPanel.qml +++ b/modules/PopupPanel.qml @@ -14,7 +14,7 @@ PanelWindow { required property real anchorX property real panelWidth: 220 - signal dismissed() + signal dismissed visible: true color: "transparent" @@ -44,10 +44,7 @@ PanelWindow { Item { id: panel - x: Math.max(0, Math.min( - Math.round(root.anchorX - contentCol.width / 2), - root.width - contentCol.width - )) + x: Math.max(0, Math.min(Math.round(root.anchorX - contentCol.width / 2), root.width - contentCol.width)) y: 0 width: contentCol.width height: contentCol.height @@ -79,14 +76,40 @@ PanelWindow { ParallelAnimation { id: showAnim - NumberAnimation { target: panel; property: "opacity"; from: 0; to: 1; duration: 150; easing.type: Easing.OutCubic } - NumberAnimation { target: panel; property: "y"; from: -panel.height; to: 0; duration: 200; easing.type: Easing.OutCubic } + NumberAnimation { + target: panel + property: "opacity" + from: 0 + to: 1 + duration: 150 + easing.type: Easing.OutCubic + } + NumberAnimation { + target: panel + property: "y" + from: -panel.height + to: 0 + duration: 200 + easing.type: Easing.OutCubic + } } ParallelAnimation { id: hideAnim - NumberAnimation { target: panel; property: "opacity"; to: 0; duration: 150; easing.type: Easing.InCubic } - NumberAnimation { target: panel; property: "y"; to: -panel.height; duration: 150; easing.type: Easing.InCubic } + NumberAnimation { + target: panel + property: "opacity" + to: 0 + duration: 150 + easing.type: Easing.InCubic + } + NumberAnimation { + target: panel + property: "y" + to: -panel.height + duration: 150 + easing.type: Easing.InCubic + } onFinished: root.dismissed() } } diff --git a/modules/Power.qml b/modules/Power.qml index cf5add9..f50597d 100644 --- a/modules/Power.qml +++ b/modules/Power.qml @@ -18,7 +18,10 @@ M.BarIcon { MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor - onClicked: { menuLoader.active = !menuLoader.active; M.FlyoutState.visible = false; } + onClicked: { + menuLoader.active = !menuLoader.active; + M.FlyoutState.visible = false; + } } Loader { diff --git a/modules/PowerMenu.qml b/modules/PowerMenu.qml index a2a042e..53197ac 100644 --- a/modules/PowerMenu.qml +++ b/modules/PowerMenu.qml @@ -18,11 +18,36 @@ M.PopupPanel { Repeater { model: [ - { label: "Lock", icon: "\uF023", cmd: ["loginctl", "lock-session"], color: M.Theme.base0D }, - { label: "Suspend", icon: "\uF186", cmd: ["systemctl", "suspend"], color: M.Theme.base0E }, - { label: "Logout", icon: "\uF2F5", cmd: menuWindow._isNiri ? ["niri", "msg", "action", "quit"] : ["loginctl", "terminate-user", ""], color: M.Theme.base0A }, - { label: "Reboot", icon: "\uF021", cmd: ["systemctl", "reboot"], color: M.Theme.base09 }, - { label: "Shutdown", icon: "\uF011", cmd: ["systemctl", "poweroff"], color: M.Theme.base08 } + { + label: "Lock", + icon: "\uF023", + cmd: ["loginctl", "lock-session"], + color: M.Theme.base0D + }, + { + label: "Suspend", + icon: "\uF186", + cmd: ["systemctl", "suspend"], + color: M.Theme.base0E + }, + { + label: "Logout", + icon: "\uF2F5", + cmd: menuWindow._isNiri ? ["niri", "msg", "action", "quit"] : ["loginctl", "terminate-user", ""], + color: M.Theme.base0A + }, + { + label: "Reboot", + icon: "\uF021", + cmd: ["systemctl", "reboot"], + color: M.Theme.base09 + }, + { + label: "Shutdown", + icon: "\uF011", + cmd: ["systemctl", "poweroff"], + color: M.Theme.base08 + } ] delegate: Item { diff --git a/modules/Temperature.qml b/modules/Temperature.qml index ba9982c..64ec432 100644 --- a/modules/Temperature.qml +++ b/modules/Temperature.qml @@ -8,9 +8,12 @@ M.BarSection { tooltip: "Temperature: " + root.celsius + "\u00B0C" property int celsius: 0 - property color _stateColor: celsius > (M.Modules.temperature.hot || 80) ? M.Theme.base09 - : celsius > (M.Modules.temperature.warm || 60) ? M.Theme.base0A : M.Theme.base08 - Behavior on _stateColor { ColorAnimation { duration: 300 } } + property color _stateColor: celsius > (M.Modules.temperature.hot || 80) ? M.Theme.base09 : celsius > (M.Modules.temperature.warm || 60) ? M.Theme.base0A : M.Theme.base08 + Behavior on _stateColor { + ColorAnimation { + duration: 300 + } + } FileView { id: thermal diff --git a/modules/Tray.qml b/modules/Tray.qml index 05a20ea..55f9894 100644 --- a/modules/Tray.qml +++ b/modules/Tray.qml @@ -30,9 +30,22 @@ RowLayout { SequentialAnimation { running: iconItem._needsAttention loops: Animation.Infinite - NumberAnimation { target: iconItem; property: "_pulseOpacity"; to: 0.3; duration: 400; easing.type: Easing.InOutQuad } - NumberAnimation { target: iconItem; property: "_pulseOpacity"; to: 1; duration: 400; easing.type: Easing.InOutQuad } - onRunningChanged: if (!running) iconItem._pulseOpacity = 1 + NumberAnimation { + target: iconItem + property: "_pulseOpacity" + to: 0.3 + duration: 400 + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: iconItem + property: "_pulseOpacity" + to: 1 + duration: 400 + easing.type: Easing.InOutQuad + } + onRunningChanged: if (!running) + iconItem._pulseOpacity = 1 } Item { diff --git a/modules/Volume.qml b/modules/Volume.qml index 194a870..79fc010 100644 --- a/modules/Volume.qml +++ b/modules/Volume.qml @@ -120,10 +120,7 @@ M.BarSection { anchors.left: true margins.top: 0 - margins.left: Math.max(0, Math.min( - Math.round(root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0) - implicitWidth / 2), - (panel.screen?.width ?? 1920) - implicitWidth - )) + margins.left: Math.max(0, Math.min(Math.round(root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0) - implicitWidth / 2), (panel.screen?.width ?? 1920) - implicitWidth)) implicitWidth: panelContent.width implicitHeight: panelContent.height @@ -146,14 +143,38 @@ M.BarSection { ParallelAnimation { id: showAnim - NumberAnimation { target: panelContent; property: "opacity"; to: 1; duration: 120; easing.type: Easing.OutCubic } - NumberAnimation { target: panelContent; property: "y"; to: 0; duration: 150; easing.type: Easing.OutCubic } + NumberAnimation { + target: panelContent + property: "opacity" + to: 1 + duration: 120 + easing.type: Easing.OutCubic + } + NumberAnimation { + target: panelContent + property: "y" + to: 0 + duration: 150 + easing.type: Easing.OutCubic + } } ParallelAnimation { id: hideAnim - NumberAnimation { target: panelContent; property: "opacity"; to: 0; duration: 150; easing.type: Easing.InCubic } - NumberAnimation { target: panelContent; property: "y"; to: -panelContent.height; duration: 150; easing.type: Easing.InCubic } + NumberAnimation { + target: panelContent + property: "opacity" + to: 0 + duration: 150 + easing.type: Easing.InCubic + } + NumberAnimation { + target: panelContent + property: "y" + to: -panelContent.height + duration: 150 + easing.type: Easing.InCubic + } onFinished: panel._winVisible = false } @@ -203,7 +224,8 @@ M.BarSection { MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor - onClicked: if (root.sink?.audio) root.sink.audio.muted = !root.sink.audio.muted + onClicked: if (root.sink?.audio) + root.sink.audio.muted = !root.sink.audio.muted } } @@ -229,7 +251,11 @@ M.BarSection { color: root._volumeColor radius: 3 - Behavior on width { NumberAnimation { duration: 80 } } + Behavior on width { + NumberAnimation { + duration: 80 + } + } } MouseArea { @@ -237,9 +263,13 @@ M.BarSection { anchors.margins: -6 cursorShape: Qt.PointingHandCursor onPressed: mouse => _setVol(mouse) - onPositionChanged: mouse => { if (pressed) _setVol(mouse); } + onPositionChanged: mouse => { + if (pressed) + _setVol(mouse); + } function _setVol(mouse) { - if (!root.sink?.audio) return; + if (!root.sink?.audio) + return; root.sink.audio.volume = Math.max(0, Math.min(1, mouse.x / slider.width)); } } @@ -281,7 +311,12 @@ M.BarSection { property real _targetHeight: root._expanded ? implicitHeight : 0 height: _targetHeight - Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } + Behavior on height { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } // Separator Rectangle { @@ -445,9 +480,13 @@ M.BarSection { anchors.margins: -6 cursorShape: Qt.PointingHandCursor onPressed: mouse => _set(mouse) - onPositionChanged: mouse => { if (pressed) _set(mouse); } + onPositionChanged: mouse => { + if (pressed) + _set(mouse); + } function _set(mouse) { - if (!streamEntry.modelData.audio) return; + if (!streamEntry.modelData.audio) + return; streamEntry.modelData.audio.volume = Math.max(0, Math.min(1, mouse.x / streamSlider.width)); } } @@ -468,7 +507,10 @@ M.BarSection { } // Bottom padding - Item { width: 1; height: 4 } + Item { + width: 1 + height: 4 + } } } } diff --git a/modules/Workspaces.qml b/modules/Workspaces.qml index 3b20d2b..e16b54c 100644 --- a/modules/Workspaces.qml +++ b/modules/Workspaces.qml @@ -90,7 +90,11 @@ Row { height: 20 radius: M.Theme.radius color: pill.active ? M.Theme.base0D : (pill._hovered ? M.Theme.base03 : M.Theme.base02) - Behavior on color { ColorAnimation { duration: 150 } } + Behavior on color { + ColorAnimation { + duration: 150 + } + } Text { anchors.centerIn: parent diff --git a/nix/hm-module.nix b/nix/hm-module.nix index eb2375d..c9b297a 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -66,7 +66,8 @@ in default = true; description = "Enable the ${name} module."; }; - } // extra; + } + // extra; }; }; intervalOpt = default: { @@ -103,18 +104,21 @@ in description = "Brightness adjustment step (%)."; }; }; - temperature = moduleOpt "temperature" ((intervalOpt 2000) // { - warm = lib.mkOption { - type = lib.types.int; - default = 60; - description = "Temperature threshold for warm state (°C)."; - }; - hot = lib.mkOption { - type = lib.types.int; - default = 80; - description = "Temperature threshold for hot state (°C)."; - }; - }); + temperature = moduleOpt "temperature" ( + (intervalOpt 2000) + // { + warm = lib.mkOption { + type = lib.types.int; + default = 60; + description = "Temperature threshold for warm state (°C)."; + }; + hot = lib.mkOption { + type = lib.types.int; + default = 80; + description = "Temperature threshold for hot state (°C)."; + }; + } + ); battery = moduleOpt "battery" { warning = lib.mkOption { type = lib.types.int; @@ -127,18 +131,21 @@ in description = "Battery percentage for critical notification and blink."; }; }; - weather = moduleOpt "weather" ((intervalOpt 3600000) // { - args = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ "--nerd" ]; - description = "Arguments passed to wttrbar."; - example = [ - "--nerd" - "--location" - "Berlin" - ]; - }; - }); + weather = moduleOpt "weather" ( + (intervalOpt 3600000) + // { + args = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ "--nerd" ]; + description = "Arguments passed to wttrbar."; + example = [ + "--nerd" + "--location" + "Berlin" + ]; + }; + } + ); }; theme = lib.mkOption { @@ -174,7 +181,8 @@ in ++ lib.optional cfg.modules.weather.enable pkgs.wttrbar; xdg.configFile."nova-shell/modules.json".source = - (pkgs.formats.json { }).generate "nova-shell-modules.json" cfg.modules; + (pkgs.formats.json { }).generate "nova-shell-modules.json" + cfg.modules; xdg.configFile."nova-shell/theme.json".source = let