quickshell: clock, calendar, battery; remove waybar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4905389a3c
commit
8e914e3131
1 changed files with 205 additions and 137 deletions
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue