Waybar here i come (#58)

This commit is contained in:
Hadi
2026-08-13 13:55:30 +02:00
committed by GitHub
parent f1f22de7b7
commit 0cef4320fd
137 changed files with 3488 additions and 2941 deletions
+103
View File
@@ -0,0 +1,103 @@
# battery-monitor: low-battery alerts for waybar/swaync.
# Runs main once (triggered by the battery-monitor systemd timer).
POWER_SUPPLY_DIR="${POWER_SUPPLY_DIR:-/sys/class/power_supply}"
STATE_FILE="${BATTERY_STATE_FILE:-/tmp/battery-alert-state}"
CRIT_ID_FILE="${BATTERY_CRIT_ID_FILE:-/tmp/battery-crit-id}"
WARN_THRESHOLD=10
CRIT_THRESHOLD=5
# Pure decision. Prints "<action>:<newstate>".
# action ∈ noop | osd_warn | crit_show | crit_clear ; state ∈ none | warn10 | crit5
battery_decide() {
status=$1
cap=$2
prev=$3
if [ "$status" = "Discharging" ]; then
if [ "$cap" -le "$CRIT_THRESHOLD" ]; then
echo "crit_show:crit5"
elif [ "$cap" -le "$WARN_THRESHOLD" ]; then
if [ "$prev" = "crit5" ]; then
echo "crit_clear:warn10"
elif [ "$prev" = "warn10" ]; then
echo "noop:warn10"
else
echo "osd_warn:warn10"
fi
else
if [ "$prev" = "crit5" ]; then
echo "crit_clear:none"
else
echo "noop:none"
fi
fi
else
if [ "$prev" = "crit5" ]; then
echo "crit_clear:none"
else
echo "noop:none"
fi
fi
}
# First real battery (type == Battery, with status + capacity).
resolve_battery() {
for d in "$POWER_SUPPLY_DIR"/*; do
[ -r "$d/type" ] || continue
[ "$(cat "$d/type")" = "Battery" ] || continue
[ -r "$d/status" ] && [ -r "$d/capacity" ] || continue
printf '%s' "$d"
return 0
done
return 1
}
show_warn_osd() {
waybar-osd "󰂃 Low battery · $1%"
}
show_crit_notification() {
cap=$1
id=$(cat "$CRIT_ID_FILE" 2>/dev/null || echo 0)
newid=$(notify-send --print-id --replace-id="$id" \
--urgency=critical --expire-time=0 \
"󰂃 Critical battery" "Battery at $cap%: plug in the charger")
printf '%s' "$newid" >"$CRIT_ID_FILE"
}
clear_crit_notification() {
id=$(cat "$CRIT_ID_FILE" 2>/dev/null || echo 0)
if [ "$id" != "0" ]; then
gdbus call --session \
--dest org.freedesktop.Notifications \
--object-path /org/freedesktop/Notifications \
--method org.freedesktop.Notifications.CloseNotification "$id" \
>/dev/null 2>&1 || true
fi
rm -f "$CRIT_ID_FILE"
}
main() {
dir=$(resolve_battery) || exit 0
status=$(cat "$dir/status")
cap=$(cat "$dir/capacity")
prev=$(cat "$STATE_FILE" 2>/dev/null || echo none)
result=$(battery_decide "$status" "$cap" "$prev")
action=${result%%:*}
newstate=${result##*:}
case "$action" in
osd_warn) show_warn_osd "$cap" ;;
crit_show) show_crit_notification "$cap" ;;
crit_clear) clear_crit_notification ;;
noop) : ;;
esac
printf '%s' "$newstate" >"$STATE_FILE"
}
main "$@"
+59
View File
@@ -0,0 +1,59 @@
{
pkgs,
config,
...
}: let
scripts = import ./scripts.nix {inherit pkgs config;};
in {
imports = [
./settings.nix
./style.nix
];
_module.args.networkScript = scripts.networkScript;
_module.args.bluetoothScript = scripts.bluetoothScript;
_module.args.volMuteScript = scripts.vol-mute;
_module.args.caffeineToggleScript = scripts.caffeine-toggle;
_module.args.osdStatusScript = scripts.waybar-osd-status;
_module.args.nightshiftToggleScript = scripts.nightshift-toggle;
programs.waybar.enable = true;
stylix.targets.waybar.enable = false;
home.packages = with pkgs;
[
playerctl
pavucontrol
blueman
hyprsunset
]
++ (with scripts; [waybar-osd waybar-osd-status battery-monitor vol-up vol-down vol-mute mic-mute bright-up bright-down nightshift-toggle focus-toggle waybar-toggle wifi-toggle bluetooth-toggle dnd-toggle output-cycle input-cycle color-pick screenshot-edit record-toggle power-cycle airplane-toggle clipboard-menu emoji-picker caffeine-toggle mic-status]);
# Poll battery level every 30s; battery-monitor no-ops when no battery exists.
systemd.user.services.battery-monitor = {
Unit.Description = "Low-battery OSD and critical notification monitor";
Service = {
Type = "oneshot";
ExecStart = "${scripts.battery-monitor}/bin/battery-monitor";
};
};
systemd.user.timers.battery-monitor = {
Unit.Description = "Poll battery level for low-battery alerts";
Timer = {
OnBootSec = "1min";
OnUnitActiveSec = "30s";
};
Install.WantedBy = ["timers.target"];
};
# Prevent blueman-applet from auto-starting via XDG autostart (we use custom/bluetooth module instead)
xdg.configFile."autostart/blueman.desktop".text = ''
[Desktop Entry]
Hidden=true
'';
wayland.windowManager.hyprland.settings.exec-once = [
"waybar"
];
}
+455
View File
@@ -0,0 +1,455 @@
{
pkgs,
config,
}: let
waybar-osd = pkgs.writeShellApplication {
name = "waybar-osd";
runtimeInputs = with pkgs; [procps coreutils];
text = ''
printf '%s' "$1" > /tmp/waybar-osd
pkill -x -RTMIN+8 waybar 2>/dev/null || true
'';
};
waybar-osd-status = pkgs.writeShellApplication {
name = "waybar-osd-status";
runtimeInputs = with pkgs; [coreutils];
text = ''
file=/tmp/waybar-osd
[ -f "$file" ] || exit 1
mtime=$(stat -c %Y "$file" 2>/dev/null) || exit 1
age=$(( $(date +%s) - mtime ))
if [ "$age" -ge 3 ]; then
rm -f "$file"
exit 1
fi
'';
};
# battery-monitor: low-battery alerts, run by the systemd user timer.
battery-monitor = pkgs.writeShellApplication {
name = "battery-monitor";
runtimeInputs = with pkgs; [waybar-osd libnotify glib coreutils];
text = builtins.readFile ./battery-monitor.sh;
};
updateOsd = ''
${waybar-osd}/bin/waybar-osd "$OSD_TEXT"
'';
volGetText = ''
VOL_RAW=$(${pkgs.wireplumber}/bin/wpctl get-volume @DEFAULT_SINK@)
VOL=$(printf '%s' "$VOL_RAW" | awk '{printf "%d", $2*100}')
if printf '%s' "$VOL_RAW" | grep -q MUTED; then
OSD_TEXT="󰝟 $VOL%"
elif [ "$VOL" -lt 33 ]; then
OSD_TEXT="󰕿 $VOL%"
elif [ "$VOL" -lt 66 ]; then
OSD_TEXT="󰖀 $VOL%"
else
OSD_TEXT="󰕾 $VOL%"
fi
'';
brightGetText = ''
BRIGHT=$(${pkgs.brightnessctl}/bin/brightnessctl -m | awk -F, '{print int($5)}')
if [ "$BRIGHT" -lt 33 ]; then
OSD_TEXT="󰃞 $BRIGHT%"
elif [ "$BRIGHT" -lt 66 ]; then
OSD_TEXT="󰃟 $BRIGHT%"
else
OSD_TEXT="󰃠 $BRIGHT%"
fi
'';
# Resolve $src: the default source, otherwise the first available source.
# Some machines have no default audio source (@DEFAULT_AUDIO_SOURCE@ unresolved).
micSource = ''
src=$(${pkgs.wireplumber}/bin/wpctl inspect @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | sed -n 's/^id \([0-9]*\),.*/\1/p')
if [ -z "$src" ]; then
src=$(${pkgs.pipewire}/bin/pw-dump | ${pkgs.jq}/bin/jq -r \
'[.[] | select(.info.props."media.class"=="Audio/Source") | .id] | .[0] // empty')
fi
'';
# tofi in vertical dmenu mode: the global config is a 36px-tall horizontal
# launcher, unusable for a list, so override the geometry here.
tofiMenu = "${pkgs.tofi}/bin/tofi --horizontal false --anchor center --width 700 --height 500 --margin-top 0 --margin-left 0 --margin-right 0 --num-results 10";
# Name -> glyph table maintained by the nerd-fonts project itself, pinned to
# the same release as the nerd-fonts packages in nixos/fonts.nix.
nerdFontGlyphnames = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/ryanoasis/nerd-fonts/v3.4.0/glyphnames.json";
sha256 = "sha256-4tENI/W/8L1vBnbpsB2XifzcZW3ntJiilVwncW6kQ5w=";
};
nerdFontIconList = pkgs.runCommand "nerd-font-icons.txt" {nativeBuildInputs = [pkgs.jq];} ''
jq -r 'to_entries[] | select(.key != "METADATA") | "\(.value.char) \(.key)"' \
${nerdFontGlyphnames} > "$out"
'';
in {
inherit waybar-osd waybar-osd-status battery-monitor;
bluetoothScript = pkgs.writeShellScript "waybar-bluetooth" ''
jq=${pkgs.jq}/bin/jq
nl=$'\n'
# bluetoothctl hangs without a controller by default always bounded by timeout.
bt() { timeout 3 ${pkgs.bluez}/bin/bluetoothctl "$@" 2>/dev/null; }
powered=$(bt show | awk '/Powered:/ { print $2; exit }')
if [ "$powered" != "yes" ]; then
"$jq" -cn '{ text: "󰂲", class: "off", tooltip: "Bluetooth off" }'
exit 0
fi
tip=""
add_tip() { tip="''${tip:+$tip$nl}$1"; }
count=0
for mac in $(bt devices Connected | awk '{ print $2 }'); do
count=$((count + 1))
info=$(bt info "$mac")
name=$(printf '%s' "$info" | sed -n 's/^[[:space:]]*Name: //p' | head -1)
[ -z "$name" ] && name="$mac"
batt=$(printf '%s' "$info" | sed -n 's/.*Battery Percentage:.*(\([0-9][0-9]*\)).*/\1/p' | head -1)
add_tip "󰂱 $name''${batt:+ · $batt%}"
done
if [ "$count" -gt 0 ]; then
"$jq" -cn --arg tooltip "$tip" '{ text: "󰂰", class: "connected", tooltip: $tooltip }'
else
"$jq" -cn '{ text: "󰂰", class: "on", tooltip: "Bluetooth on" }'
fi
'';
networkScript = pkgs.writeShellScript "waybar-network" ''
nmcli=${pkgs.networkmanager}/bin/nmcli
ip=${pkgs.iproute2}/bin/ip
jq=${pkgs.jq}/bin/jq
nl=$'\n'
text=""
tip=""
class="disconnected"
add_seg() { text="''${text:+$text }$1"; }
add_tip() { tip="''${tip:+$tip$nl}$1"; }
# Ethernet
eth=$("$nmcli" -t -f DEVICE,TYPE,STATE device status 2>/dev/null \
| awk -F: '$2 == "ethernet" && $3 == "connected" { print $1; exit }')
if [ -n "$eth" ]; then
eth_ip=$("$ip" -4 -br addr show "$eth" 2>/dev/null | awk '{ print $3 }' | cut -d/ -f1)
add_seg "󰛳"
class="ethernet"
add_tip "󰛳 Ethernet''${eth_ip:+ · $eth_ip}"
fi
# Wi-Fi
wifi=$("$nmcli" -t -f ACTIVE,SSID,SIGNAL device wifi 2>/dev/null | grep -m1 '^yes:')
if [ -n "$wifi" ]; then
ssid=$(printf '%s' "$wifi" | cut -d: -f2)
signal=$(printf '%s' "$wifi" | cut -d: -f3)
if [ "''${signal:-0}" -ge 80 ]; then icon="󰤨"
elif [ "''${signal:-0}" -ge 60 ]; then icon="󰤥"
elif [ "''${signal:-0}" -ge 40 ]; then icon="󰤢"
elif [ "''${signal:-0}" -ge 20 ]; then icon="󰤟"
else icon="󰤯"
fi
add_seg "$icon"
[ "$class" = "disconnected" ] && class="wifi"
add_tip "$icon ''${ssid:-Wi-Fi}''${signal:+ · $signal%}"
fi
# VPN (nmcli, fallback interfaces)
vpn=$("$nmcli" -t -f TYPE,NAME connection show --active 2>/dev/null \
| awk -F: '$1 == "vpn" || $1 == "wireguard" { print $2; exit }')
if [ -z "$vpn" ]; then
vpn=$("$ip" -br link show 2>/dev/null \
| awk '($2 == "UP" || $2 == "UNKNOWN") && $1 ~ /^(tun|wg|proton|ppp)/ { sub(/@.*/, "", $1); print $1; exit }')
fi
if [ -n "$vpn" ]; then
add_seg "󰦝"
add_tip "󰦝 VPN · $vpn"
fi
if [ -z "$text" ]; then
text="󰤭"
tip="Disconnected"
fi
"$jq" -cn --arg text "$text" --arg class "$class" --arg tooltip "$tip" \
'{ text: $text, class: $class, tooltip: $tooltip }'
'';
vol-up = pkgs.writeShellScriptBin "vol-up" ''
${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 5%+ --limit 1.0
${volGetText}
${updateOsd}
'';
vol-down = pkgs.writeShellScriptBin "vol-down" ''
${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 5%-
${volGetText}
${updateOsd}
'';
vol-mute = pkgs.writeShellScriptBin "vol-mute" ''
${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_SINK@ toggle
${volGetText}
${updateOsd}
'';
mic-mute = pkgs.writeShellScriptBin "mic-mute" ''
wpctl=${pkgs.wireplumber}/bin/wpctl
${micSource}
[ -z "$src" ] && exit 0
"$wpctl" set-mute "$src" toggle
if "$wpctl" get-volume "$src" | grep -q MUTED; then
OSD_TEXT="󰍭 Muted"
else
OSD_TEXT="󰍬 Live"
fi
${updateOsd}
'';
mic-status = pkgs.writeShellScriptBin "mic-status" ''
${micSource}
if [ -n "$src" ] && ${pkgs.wireplumber}/bin/wpctl get-volume "$src" | grep -q MUTED; then
echo true
else
echo false
fi
'';
bright-up = pkgs.writeShellScriptBin "bright-up" ''
${pkgs.brightnessctl}/bin/brightnessctl set 5%+
${brightGetText}
${updateOsd}
'';
bright-down = pkgs.writeShellScriptBin "bright-down" ''
${pkgs.brightnessctl}/bin/brightnessctl set 5%-
${brightGetText}
${updateOsd}
'';
wifi-toggle = pkgs.writeShellScriptBin "wifi-toggle" ''
if nmcli radio wifi | grep -q enabled; then
nmcli radio wifi off
else
nmcli radio wifi on
fi
${updateOsd}
'';
bluetooth-toggle = pkgs.writeShellScriptBin "bluetooth-toggle" ''
if bluetoothctl show | grep -q "Powered: yes"; then
bluetoothctl power off
else
bluetoothctl power on
fi
${updateOsd}
'';
waybar-toggle = pkgs.writeShellScriptBin "waybar-toggle" ''
if pidof waybar > /dev/null; then
pkill waybar
else
hyprctl dispatch exec waybar
fi
'';
nightshift-toggle = pkgs.writeShellScriptBin "nightshift-toggle" ''
if pidof "hyprsunset" > /dev/null; then
pkill hyprsunset
OSD_TEXT="󰖔 Night Shift Off"
else
${pkgs.hyprsunset}/bin/hyprsunset -t 4500 &
OSD_TEXT="󰖔 Night Shift On"
fi
${updateOsd}
'';
focus-toggle = pkgs.writeShellScriptBin "focus-toggle" ''
if test -f /tmp/hypr-focus-mode; then
rm /tmp/hypr-focus-mode
OSD_TEXT="󰈈 Focus Off"
${updateOsd}
hyprctl reload
hyprctl dispatch exec waybar
else
touch /tmp/hypr-focus-mode
OSD_TEXT="󰈈 Focus On"
${updateOsd}
pkill waybar || true
hyprctl keyword animations:enabled false
hyprctl keyword general:gaps_in 0
hyprctl keyword general:gaps_out 0
hyprctl keyword decoration:active_opacity 1
hyprctl keyword decoration:inactive_opacity 1
hyprctl keyword decoration:rounding 0
fi
'';
dnd-toggle = pkgs.writeShellScriptBin "dnd-toggle" ''
state=$(${pkgs.swaynotificationcenter}/bin/swaync-client -d)
if [ "$state" = "true" ]; then
OSD_TEXT="󰂛 Do Not Disturb On"
else
OSD_TEXT="󰂚 Do Not Disturb Off"
fi
${updateOsd}
'';
output-cycle = pkgs.writeShellScriptBin "output-cycle" ''
wpctl=${pkgs.wireplumber}/bin/wpctl
jq=${pkgs.jq}/bin/jq
pwdump=${pkgs.pipewire}/bin/pw-dump
# Sink IDs in pw-dump order.
ids=($("$pwdump" | "$jq" -r '.[] | select(.info.props."media.class"=="Audio/Sink") | .id'))
n=''${#ids[@]}
[ "$n" -eq 0 ] && exit 0
cur=$("$wpctl" inspect @DEFAULT_AUDIO_SINK@ 2>/dev/null | sed -n 's/^id \([0-9]*\),.*/\1/p')
next_index=0
for i in "''${!ids[@]}"; do
if [ "''${ids[$i]}" = "$cur" ]; then
next_index=$(( (i + 1) % n ))
break
fi
done
next=''${ids[$next_index]}
"$wpctl" set-default "$next"
desc=$("$pwdump" | "$jq" -r --argjson id "$next" '.[] | select(.id==$id) | .info.props."node.description"')
OSD_TEXT="󰓃 ''${desc:-Output}"
${updateOsd}
'';
input-cycle = pkgs.writeShellScriptBin "input-cycle" ''
wpctl=${pkgs.wireplumber}/bin/wpctl
jq=${pkgs.jq}/bin/jq
pwdump=${pkgs.pipewire}/bin/pw-dump
# Source IDs in pw-dump order.
ids=($("$pwdump" | "$jq" -r '.[] | select(.info.props."media.class"=="Audio/Source") | .id'))
n=''${#ids[@]}
[ "$n" -eq 0 ] && exit 0
cur=$("$wpctl" inspect @DEFAULT_AUDIO_SOURCE@ 2>/dev/null | sed -n 's/^id \([0-9]*\),.*/\1/p')
next_index=0
for i in "''${!ids[@]}"; do
if [ "''${ids[$i]}" = "$cur" ]; then
next_index=$(( (i + 1) % n ))
break
fi
done
next=''${ids[$next_index]}
"$wpctl" set-default "$next"
desc=$("$pwdump" | "$jq" -r --argjson id "$next" '.[] | select(.id==$id) | .info.props."node.description"')
OSD_TEXT="󰍬 ''${desc:-Input}"
${updateOsd}
'';
color-pick = pkgs.writeShellScriptBin "color-pick" ''
# hyprpicker -a already copies the color to the clipboard.
color=$(${pkgs.hyprpicker}/bin/hyprpicker -a 2>/dev/null)
if [ -n "$color" ]; then
OSD_TEXT="󰈊 $color"
else
OSD_TEXT="󰈊 Cancelled"
fi
${updateOsd}
'';
screenshot-edit = pkgs.writeShellScriptBin "screenshot-edit" ''
${pkgs.hyprshot}/bin/hyprshot -m region --raw 2>/dev/null \
| ${pkgs.satty}/bin/satty --filename -
'';
record-toggle = pkgs.writeShellScriptBin "record-toggle" ''
if pgrep -x wf-recorder >/dev/null; then
# -INT lets wf-recorder finalize the file cleanly.
pkill -INT -x wf-recorder
OSD_TEXT="󰕧 Recording saved"
else
dir="$HOME/Videos"
mkdir -p "$dir"
file="$dir/rec-$(date +%Y%m%d-%H%M%S).mp4"
${pkgs.wf-recorder}/bin/wf-recorder -f "$file" >/dev/null 2>&1 &
OSD_TEXT="󰑊 Recording"
fi
${updateOsd}
'';
power-cycle = pkgs.writeShellScriptBin "power-cycle" ''
ppd=${pkgs.power-profiles-daemon}/bin/powerprofilesctl
cur=$("$ppd" get)
case "$cur" in
power-saver) next=balanced; icon="󰾅" ;;
balanced) next=performance; icon="󰓅" ;;
performance) next=power-saver; icon="󰌪" ;;
*) next=balanced; icon="󰾅" ;;
esac
"$ppd" set "$next"
OSD_TEXT="$icon ''${next^}"
${updateOsd}
'';
airplane-toggle = pkgs.writeShellScriptBin "airplane-toggle" ''
# Reuse nmcli + bluetoothctl (unprivileged) instead of rfkill.
on=false
nmcli radio wifi 2>/dev/null | grep -q enabled && on=true
bluetoothctl show 2>/dev/null | grep -q "Powered: yes" && on=true
if $on; then
nmcli radio wifi off 2>/dev/null
bluetoothctl power off >/dev/null 2>&1 || true
OSD_TEXT="󰀝 Airplane On"
else
nmcli radio wifi on 2>/dev/null
bluetoothctl power on >/dev/null 2>&1 || true
OSD_TEXT="󰀞 Airplane Off"
fi
${updateOsd}
'';
clipboard-menu = pkgs.writeShellScriptBin "clipboard-menu" ''
list=$(${pkgs.cliphist}/bin/cliphist list)
selected=$(printf '%s\n' "$list" | cut -f2- | ${tofiMenu} --prompt-text "Clipboard: ")
[ -n "$selected" ] && printf '%s\n' "$list" \
| awk -F'\t' -v s="$selected" '$2 == s {print; exit}' \
| ${pkgs.cliphist}/bin/cliphist decode \
| ${pkgs.wl-clipboard}/bin/wl-copy
'';
emoji-picker = pkgs.writeShellScriptBin "emoji-picker" ''
export PATH="${pkgs.wtype}/bin:${pkgs.wl-clipboard}/bin:$PATH"
export BEMOJI_PICKER_CMD="${tofiMenu} --prompt-text 'emoji: '"
# -t types the emoji (wtype), -c also copies it.
exec ${pkgs.bemoji}/bin/bemoji -t -c
'';
icon-picker = pkgs.writeShellScriptBin "icon-picker" ''
selected=$(${tofiMenu} --font "${config.stylix.fonts.monospace.name}" --prompt-text 'icon: ' < ${nerdFontIconList})
[ -z "$selected" ] || icon=$(printf '%s\n' "$selected" | awk '{print $1}')
[ -n "''${icon:-}" ] || exit 0
${pkgs.wtype}/bin/wtype "$icon"
printf '%s' "$icon" | ${pkgs.wl-clipboard}/bin/wl-copy
'';
caffeine-toggle = pkgs.writeShellScriptBin "caffeine-toggle" ''
# Pause hypridle (stay awake) or resume it.
if systemctl --user is-active --quiet hypridle; then
systemctl --user stop hypridle
OSD_TEXT="󰅶 Keep Awake On"
else
systemctl --user start hypridle
OSD_TEXT="󰾫 Keep Awake Off"
fi
${updateOsd}
'';
}
+169
View File
@@ -0,0 +1,169 @@
{
config,
pkgs,
networkScript,
bluetoothScript,
caffeineToggleScript,
osdStatusScript,
nightshiftToggleScript,
...
}: let
gaps-out = config.theme.gaps-out;
c = config.lib.stylix.colors;
in {
programs.waybar.settings = [
{
layer = "top";
position = "top";
height = config.theme.bar-height;
margin = "${toString gaps-out} ${toString gaps-out} 0";
modules-center = ["custom/osd" "custom/osd-sep" "clock" "tray" "hyprland/workspaces" "custom/network" "custom/bluetooth" "battery" "group/drawer"];
# ── Modules ─────────────────────────────────────────────────────────
"hyprland/workspaces" = {
format = "{id}";
all-outputs = true;
move-to-monitor = true;
ignore-workspaces = ["[5-9]" "[1-9][0-9]+"];
on-scroll-down = "${pkgs.hyprland}/bin/hyprctl dispatch workspace e+1";
on-scroll-up = "${pkgs.hyprland}/bin/hyprctl dispatch workspace e-1";
persistent-workspaces."*" = [1 2 3 4];
cursor = true;
};
battery = {
interval = 20;
full-at = 100;
tooltip = true;
format = "{icon} ";
format-charging = " {icon} ";
format-icons = ["" "" "" "" ""];
tooltip-format = "{capacity}% · {time}";
tooltip-format-full = "Full\n{capacity}%";
tooltip-format-charging = "Charging\n{capacity}% · {time}";
on-click = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.nur.repos.anotherhadi.settuings}/bin/settuings --page power";
states = {
warning = 30;
critical = 15;
};
};
"custom/caffeine" = {
exec = "${pkgs.coreutils}/bin/printf '󰅶'";
exec-if = "! systemctl --user is-active --quiet hypridle";
format = "{}";
interval = 5;
on-click = "${caffeineToggleScript}/bin/caffeine-toggle";
tooltip = false;
};
"custom/nightshift" = {
exec = "${pkgs.coreutils}/bin/printf '󰖔'";
exec-if = "${pkgs.procps}/bin/pgrep -x hyprsunset";
format = "{}";
interval = 5;
on-click = "${nightshiftToggleScript}/bin/nightshift-toggle";
tooltip = false;
};
"custom/bluetooth" = {
exec = "${bluetoothScript}";
exec-if = "${pkgs.bluez}/bin/bluetoothctl list 2>/dev/null | grep -q Controller";
return-type = "json";
interval = 5;
on-click = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.nur.repos.anotherhadi.settuings}/bin/settuings --page bluetooth";
};
"custom/osd" = {
exec = "cat /tmp/waybar-osd";
exec-if = "${osdStatusScript}/bin/waybar-osd-status";
signal = 8;
interval = 1;
format = "{}";
};
"custom/osd-sep" = {
exec = "echo '|'";
exec-if = "${osdStatusScript}/bin/waybar-osd-status";
signal = 8;
interval = 1;
format = "{}";
tooltip = false;
};
pulseaudio = {
format = "{icon}";
format-bluetooth = "{icon}";
tooltip-format = "{volume}%";
format-muted = "<span size='12pt'>󰝟</span>";
scroll-step = 2;
on-click = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.nur.repos.anotherhadi.settuings}/bin/settuings --page audio";
format-icons = {
headphone = "";
hands-free = "";
headset = "";
phone = "";
portable = "";
car = "";
default = [
"󰕿"
"󰖀"
"󰕾"
];
};
};
"pulseaudio/slider" = {
min = 0;
max = 100;
cursor = true;
};
"custom/network" = {
exec = "${networkScript}";
return-type = "json";
interval = 10;
on-click = "${pkgs.ghostty}/bin/ghostty +new-window -e ${pkgs.nur.repos.anotherhadi.settuings}/bin/settuings --page network";
};
tray = {
icon-size = 13;
spacing = 12;
cursor = true;
};
clock = {
timezone = config.var.timeZone;
tooltip-format = "<tt><small>{calendar}</small></tt>";
format = "{:%H:%M}";
format-alt = "{:%H:%M %d %B %Y}";
calendar = {
mode = "month";
format = {
months = "<span color='#${c.base04}'><b>{}</b></span>";
weekdays = "<span color='#${c.base0A}'><b>{}</b></span>";
days = "<span color='#${c.base05}'>{}</span>";
today = "<span color='#${c.base0D}'><b><u>{}</u></b></span>";
};
};
};
"group/drawer" = {
orientation = "horizontal";
drawer = {
transition-duration = 300;
children-class = "drawer-child";
transition-left-to-right = false;
};
modules = ["custom/arrow-right" "pulseaudio" "custom/nightshift" "custom/caffeine"];
};
"custom/arrow-right" = {
format = " ";
tooltip = false;
cursor = true;
};
}
];
}
+172
View File
@@ -0,0 +1,172 @@
{config, ...}: let
c = config.lib.stylix.colors;
fg = "#${c.base05}";
module-bg = "#${c.base01}";
tooltip-bg = "#${c.base01}";
red = "#${c.base08}";
yellow = "#${c.base0A}";
green = "#${c.base0B}";
blue = "#${c.base0D}";
cyan = "#${c.base0C}";
inactive = "#${c.base03}";
highlight = "#${c.base02}";
font-size = "${toString config.stylix.fonts.sizes.applications}px";
font-size-clock = "${toString (config.stylix.fonts.sizes.applications + 2)}px";
module-padding = "14px";
in {
programs.waybar.style = ''
* {
font-family: '${config.stylix.fonts.sansSerif.name}';
border: none;
border-radius: 0;
min-height: 0;
margin: 0;
padding: 0;
text-shadow: none;
}
#waybar {
font-weight: 700;
background: transparent;
font-size: ${font-size};
color: ${fg};
}
.modules-center {
background: ${module-bg};
border-radius: 100px;
padding: 6px 14px;
box-shadow: none;
}
#clock,
#battery,
#tray,
#workspaces,
#custom-osd,
#custom-network,
#custom-bluetooth,
#custom-caffeine,
#custom-nightshift,
#pulseaudio {
padding: 1px ${module-padding};
}
#custom-arrow-right {
color: ${fg};
padding: 1px 8px;
}
#group-drawer {
padding: 0;
}
#custom-osd-sep {
padding: 0;
color: ${inactive};
}
#clock {
font-size: ${font-size-clock};
}
#workspaces button {
color: ${fg};
font-size: ${font-size};
border-radius: 100px;
padding: 0 3px;
margin: 0;
}
#workspaces button.empty {
color: ${inactive};
}
#workspaces button:hover {
background: transparent;
color: ${fg};
}
#workspaces button.active {
color: ${module-bg};
background: ${blue};
border-radius: 60px;
padding: 0 8px;
margin: 0;
}
#battery {
color: ${green};
}
#battery.charging,
#battery.full {
color: ${green};
}
#battery.critical,
#custom-network.disconnected {
color: ${red};
}
#battery.warning {
color: ${yellow};
}
#custom-network.ethernet,
#custom-network.wifi {
color: ${cyan};
}
#custom-bluetooth {
color: ${blue};
}
#custom-bluetooth.off {
color: ${inactive};
}
#custom-caffeine,
#custom-nightshift {
color: ${yellow};
}
#custom-osd {
font-weight: 700;
color: ${fg};
}
tooltip {
border-radius: 15px;
background: ${tooltip-bg};
}
tooltip label {
padding: 3px 10px;
color: ${fg};
font-weight: 700;
}
.popup * {
box-shadow: none;
outline: none;
border-radius: 10px;
}
menu {
border-radius: 10px;
font-weight: 700;
color: ${fg};
background: ${tooltip-bg};
}
menu > * {
padding: 3px 0px;
}
menu > *:hover {
border-radius: 10px;
background-color: ${highlight};
}
'';
}