quickshell: clock, calendar, battery; remove waybar

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
rope 2026-05-26 11:15:01 +01:00
parent 4905389a3c
commit 8e914e3131

View file

@ -60,7 +60,6 @@ in
networkmanagerapplet
pavucontrol
polkit_gnome
] ++ lib.optionals isGaming [
quickshell
qt6.qt5compat
];
@ -423,145 +422,11 @@ in
};
};
# Scope all HM Wayland services (hyprpaper, waybar, …) to the
# Scope all HM Wayland services (hyprpaper, etc.) to the
# Hyprland session so they don't crash-loop in a GNOME session.
wayland.systemd.target = "hyprland-session.target";
programs.waybar = {
enable = true;
systemd.enable = true;
settings.mainBar = {
layer = "top";
position = "top";
height = 30;
spacing = 6;
modules-left = [ "hyprland/workspaces" ];
modules-center = [ "clock" ];
modules-right = lib.optionals isMacbook [ "battery" ] ++ [ "group/tray-drawer" ];
"hyprland/workspaces" = {
format = "{name}";
on-click = "activate";
sort-by-number = true;
};
clock = {
format = "{:%H:%M}";
tooltip-format = "<big>{:%A, %d %B %Y}</big>\n<tt><small>{calendar}</small></tt>";
};
"group/tray-drawer" = {
orientation = "horizontal";
drawer = {
transition-duration = 500;
transition-left-to-right = false;
};
modules = [ "custom/tray-handle" "pulseaudio" "tray" ];
};
"custom/tray-handle" = {
format = builtins.fromJSON ''"\ue0b2"''; # U+E0B2 Nerd Font powerline filled left-arrow
tooltip = false;
};
# Pulseaudio module, now conditionally visible
pulseaudio = {
format = "{icon} {volume}%";
format-muted = " muted";
format-icons = {
default = [ "" "" "" ];
headphone = "";
headset = "";
};
on-click = "pavucontrol";
scroll-step = 5;
};
# Tray module, now conditionally visible
tray = {
icon-size = 16;
spacing = 8;
};
} // lib.optionalAttrs isMacbook {
battery = {
format = "{capacity}% {icon}";
format-charging = "{capacity}% ";
format-icons = [ "" "" "" "" "" ];
states = { warning = 30; critical = 15; };
};
};
style = ''
* {
font-family: "FiraMono Nerd Font", monospace;
font-size: 13px;
min-height: 0;
border: none;
border-radius: 0;
}
window#waybar {
background: alpha(@base00, 0.82);
color: @base05;
}
#workspaces {
margin-left: 6px;
}
#workspaces button {
padding: 0 8px;
color: @base03;
background: transparent;
}
#workspaces button.active {
color: @base05;
}
#workspaces button:hover {
background: alpha(@base05, 0.08);
color: @base05;
box-shadow: none;
text-shadow: none;
}
#clock {
color: @base05;
font-weight: 500;
}
#pulseaudio,
#tray {
padding: 0 10px;
color: @base05;
}
#pulseaudio.muted {
color: @base03;
}
#tray {
margin-right: 6px;
}
#custom-tray-handle {
padding: 0 0px;
color: @base05;
}
#battery {
padding: 0 10px;
color: @base05;
}
#battery.warning { color: @base0A; }
#battery.critical { color: @base08; }
'';
};
xdg.configFile."quickshell/shell.qml" = lib.mkIf isGaming {
xdg.configFile."quickshell/shell.qml" = {
text = ''
//@ pragma UseQApplication
import Quickshell
@ -637,6 +502,32 @@ in
// Spacer
Item { Layout.fillWidth: true }
// Clock
Text {
id: clockText
property date now: new Date()
text: now.toLocaleTimeString(Qt.locale(), "HH:mm")
color: "#${c.base05}"
font.family: "FiraMono Nerd Font"
font.pixelSize: 13
font.weight: Font.Medium
Timer {
interval: 1000
running: true
repeat: true
onTriggered: clockText.now = new Date()
}
MouseArea {
anchors.fill: parent
onClicked: calPopup.visible = !calPopup.visible
}
}
// Spacer
Item { Layout.fillWidth: true }
// Network status
Item {
id: netWidget
@ -703,6 +594,78 @@ in
}
}
${lib.optionalString isMacbook ''
// Battery
Item {
id: batteryWidget
Layout.preferredHeight: 30
Layout.preferredWidth: batteryRow.width
Layout.rightMargin: 10
property int batteryLevel: 0
property bool charging: false
property string batteryIcon: "\u{f008e}"
function updateIcon() {
if (charging) { batteryIcon = "\u{f0084}"; return; }
if (batteryLevel >= 90) batteryIcon = "\u{f0079}";
else if (batteryLevel >= 70) batteryIcon = "\u{f0082}";
else if (batteryLevel >= 50) batteryIcon = "\u{f007f}";
else if (batteryLevel >= 30) batteryIcon = "\u{f007c}";
else if (batteryLevel >= 15) batteryIcon = "\u{f007a}";
else batteryIcon = "\u{f008e}";
}
Timer {
interval: 10000
running: true
repeat: true
triggeredOnStart: true
onTriggered: batteryProc.running = true
}
Process {
id: batteryProc
command: ["sh", "-c", "cat /sys/class/power_supply/BAT0/capacity; cat /sys/class/power_supply/BAT0/status"]
stdout: SplitParser {
onRead: data => {
let trimmed = data.trim();
if (/^\\d+$/.test(trimmed)) {
batteryWidget.batteryLevel = parseInt(trimmed);
} else {
batteryWidget.charging = (trimmed === "Charging");
}
batteryWidget.updateIcon();
}
}
}
RowLayout {
id: batteryRow
anchors.verticalCenter: parent.verticalCenter
spacing: 4
Text {
text: batteryWidget.batteryLevel + "%"
color: batteryWidget.batteryLevel <= 15 ? "#${c.base08}"
: batteryWidget.batteryLevel <= 30 ? "#${c.base0A}"
: "#${c.base05}"
font.family: "FiraMono Nerd Font"
font.pixelSize: 13
}
Text {
text: batteryWidget.batteryIcon
color: batteryWidget.batteryLevel <= 15 ? "#${c.base08}"
: batteryWidget.batteryLevel <= 30 ? "#${c.base0A}"
: "#${c.base05}"
font.family: "FiraMono Nerd Font"
font.pixelSize: 14
}
}
}
''}
// Tray icons inline
RowLayout {
id: trayArea
@ -851,6 +814,111 @@ in
}
}
}
// Calendar popup
PopupWindow {
id: calPopup
anchor.item: clockText
anchor.edges: Edges.Bottom
anchor.gravity: Edges.Bottom
anchor.adjustment: PopupAdjustment.Slide
grabFocus: true
visible: false
color: "transparent"
implicitWidth: calContent.width + 2
implicitHeight: calContent.height + 2
Rectangle {
id: calContent
width: calCol.width + 32
height: calCol.height + 24
color: "#${c.base00}"
border.color: "#${c.base03}"
border.width: 1
radius: 8
Column {
id: calCol
anchors.centerIn: parent
spacing: 8
// Date header
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: clockText.now.toLocaleDateString(Qt.locale(), "dddd, d MMMM yyyy")
color: "#${c.base05}"
font.family: "FiraMono Nerd Font"
font.pixelSize: 14
font.weight: Font.Medium
}
// Day headers
Row {
spacing: 0
Repeater {
model: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"]
Text {
required property var modelData
width: 28
horizontalAlignment: Text.AlignHCenter
text: modelData
color: "#${c.base03}"
font.family: "FiraMono Nerd Font"
font.pixelSize: 11
}
}
}
// Calendar grid
Grid {
columns: 7
spacing: 0
Repeater {
id: calRepeater
model: 42
Rectangle {
required property int index
width: 28
height: 24
radius: 4
color: {
let d = clockText.now;
let first = new Date(d.getFullYear(), d.getMonth(), 1);
let startDay = (first.getDay() + 6) % 7;
let dayNum = index - startDay + 1;
let daysInMonth = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
return (dayNum === d.getDate() && dayNum >= 1 && dayNum <= daysInMonth)
? "#${c.base02}" : "transparent";
}
Text {
anchors.centerIn: parent
text: {
let d = clockText.now;
let first = new Date(d.getFullYear(), d.getMonth(), 1);
let startDay = (first.getDay() + 6) % 7;
let dayNum = parent.index - startDay + 1;
let daysInMonth = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
return (dayNum >= 1 && dayNum <= daysInMonth) ? dayNum.toString() : "";
}
color: {
let d = clockText.now;
let first = new Date(d.getFullYear(), d.getMonth(), 1);
let startDay = (first.getDay() + 6) % 7;
let dayNum = parent.index - startDay + 1;
return (dayNum === d.getDate()) ? "#${c.base05}" : "#${c.base04}";
}
font.family: "FiraMono Nerd Font"
font.pixelSize: 11
}
}
}
}
}
}
}
}
}
}