diff --git a/settings/quickshell.nix b/settings/quickshell.nix index 69251ce..3474484 100644 --- a/settings/quickshell.nix +++ b/settings/quickshell.nix @@ -722,6 +722,8 @@ in import Quickshell.Io import Quickshell.Wayland import Quickshell.Services.Pam + import Quickshell.Services.UPower + import Quickshell.Services.Mpris import QtQuick import Qt5Compat.GraphicalEffects @@ -869,7 +871,79 @@ in font.pixelSize: 18 } - Item { width: 1; height: 28 } + Item { width: 1; height: 14 } + + ${lib.optionalString isMacbook '' + // Power. UPower.displayDevice is the same DBus source + // the bar reads — no polling, no /sys parsing. + Row { + id: lockBatt + spacing: 8 + property var dev: UPower.displayDevice + property int level: dev && dev.ready ? Math.round(dev.percentage * 100) : 0 + property bool charging: dev ? dev.state === UPowerDeviceState.Charging : false + property string remaining: { + if (!dev) return ""; + let secs = charging ? dev.timeToFull : dev.timeToEmpty; + if (!secs || secs <= 0) return ""; + return Math.floor(secs / 3600) + "h " + Math.round((secs % 3600) / 60) + "m"; + } + visible: dev && dev.ready + + Text { + anchors.verticalCenter: parent.verticalCenter + text: lockBatt.charging ? "battery-charging" + : lockBatt.level >= 75 ? "battery-full" + : lockBatt.level >= 50 ? "battery-medium" + : lockBatt.level >= 20 ? "battery-low" + : "battery" + font.family: Theme.iconFont + font.pixelSize: 17 + color: lockBatt.level <= 15 ? Theme.err + : lockBatt.level <= 30 ? Theme.warn : Theme.base04 + } + Text { + anchors.verticalCenter: parent.verticalCenter + text: lockBatt.level + "%" + (lockBatt.remaining === "" ? "" + : " · " + lockBatt.remaining + (lockBatt.charging ? " to full" : " left")) + color: Theme.base04 + font.family: Theme.fontFamily + font.pixelSize: 15 + } + } + ''} + + // Now playing. Mpris is a global service, so this shows + // whatever kept playing into the lock — nothing is woken. + Row { + id: lockMedia + spacing: 8 + property var player: Mpris.players.values.filter(p => p.trackTitle)[0] + visible: !!player + + Text { + anchors.verticalCenter: parent.verticalCenter + text: "music" + font.family: Theme.iconFont + font.pixelSize: 17 + color: Theme.base04 + } + Text { + anchors.verticalCenter: parent.verticalCenter + width: 380 + elide: Text.ElideRight + text: lockMedia.player + ? lockMedia.player.trackTitle + (lockMedia.player.trackArtist + ? " · " + lockMedia.player.trackArtist : "") + : "" + color: Theme.base04 + font.family: Theme.fontFamily + font.pixelSize: 15 + } + } + + Item { width: 1; height: 14 } + // Password pill: dots for typed chars; border tracks // state (accent while checking, red on failure).