{ pkgs, lib, config, ... }: let timerScript = pkgs.writeShellScriptBin "timer.sh" '' #!${pkgs.bash}/bin/bash CUR_TIME=$(${pkgs.coreutils}/bin/date +%s) STATUS=$(${pkgs.coreutils}/bin/cat /var/tmp/timer_status || echo "READY") if [ "$STATUS" = "READY" ]; then echo "" elif [ "$STATUS" = "FINISHED" ]; then ${pkgs.pulseaudio}/bin/paplay "${config.home.homeDirectory}/.config/eww/timer.wav" & echo "READY" > /var/tmp/timer_status echo "" elif [ "$STATUS" -gt "$CUR_TIME" ]; then DIFF=$(( STATUS - CUR_TIME )) echo $(${pkgs.coreutils}/bin/date -d "@$DIFF" +%M:%S) else echo "FINISHED" > /var/tmp/timer_status echo "" fi ''; calendarScript = pkgs.writeShellScriptBin "calendar.sh" '' #!${pkgs.bash}/bin/bash ${pkgs.coreutils}/bin/date +'%Y %B\n%d %A' ''; in { programs.eww = { enable = true; package = pkgs.eww; }; # Dependencies home.packages = with pkgs; [ hyprland brightnessctl lxqt.pavucontrol-qt wttrbar bluetui wlogout walker lm_sensors pulseaudio socat jq procps gawk gnugrep gnused systemd iproute2 dbus ]; home.file.".config/eww/eww.yuck".text = '' ;; Variables and Polls (defpoll time :interval "1s" "${pkgs.coreutils}/bin/date +'%A, %Y-%m-%d %H:%M:%S'") (defpoll weather :interval "3600s" "${pkgs.wttrbar}/bin/wttrbar --main-indicator=FeelsLikeC --date-format=%d.%m.%Y --location=Helsinki | ${pkgs.jq}/bin/jq .FeelsLikeC") (defpoll cpu-usage :interval "2s" "${pkgs.procps}/bin/top -bn1 | ${pkgs.gnugrep}/bin/grep '^%Cpu' | ${pkgs.gawk}/bin/awk '{print 100 - \$8}'") (defpoll memory :interval "2s" "${pkgs.procps}/bin/free -h | ${pkgs.gnugrep}/bin/grep '^Mem:' | ${pkgs.gawk}/bin/awk '{print \$3 \"/\" \$2}'") (defpoll load :interval "2s" "${pkgs.coreutils}/bin/cat /proc/loadavg | ${pkgs.gawk}/bin/awk '{print \$1}'") (defpoll temperature :interval "5s" "${pkgs.lm_sensors}/bin/sensors | ${pkgs.gnugrep}/bin/grep 'Tctl:' | ${pkgs.gawk}/bin/awk '{print \$2}' | ${pkgs.gnused}/bin/sed 's/+//'") (defpoll volume :interval "2s" "${pkgs.pulseaudio}/bin/pactl get-sink-volume @DEFAULT_SINK@ | ${pkgs.gawk}/bin/awk '{print \$5}' | ${pkgs.gnused}/bin/sed 's/%//'") (defpoll mute :interval "2s" "${pkgs.pulseaudio}/bin/pactl get-sink-mute @DEFAULT_SINK@ | ${pkgs.gnugrep}/bin/grep -q 'Mute: yes' && echo 'true' || echo 'false'") (defpoll backlight :interval "2s" "${pkgs.brightnessctl}/bin/brightnessctl g") (defpoll battery :interval "10s" "${pkgs.coreutils}/bin/cat /sys/class/power_supply/BAT0/capacity 2>/dev/null || echo '0'") (defpoll battery-status :interval "10s" "${pkgs.coreutils}/bin/cat /sys/class/power_supply/BAT0/status 2>/dev/null || echo 'Unknown'") (defpoll failed-units :interval "30s" "${pkgs.systemd}/bin/systemctl --failed --no-legend | ${pkgs.coreutils}/bin/wc -l") (defpoll processes :interval "10s" "${pkgs.procps}/bin/ps -e --no-headers | ${pkgs.coreutils}/bin/wc -l") (defpoll sockets :interval "10s" "${pkgs.iproute2}/bin/ss -tuln | ${pkgs.coreutils}/bin/tail -n +2 | ${pkgs.coreutils}/bin/wc -l") (defpoll keyboard-layout :interval "5s" "${pkgs.hyprland}/bin/hyprctl getoption general:kb_layout -j | ${pkgs.jq}/bin/jq -r .str") ;; Hyprland workspace tracking (defpoll workspaces :interval "1s" "${pkgs.hyprland}/bin/hyprctl workspaces -j") (defpoll active-workspace :interval "1s" "${pkgs.hyprland}/bin/hyprctl activeworkspace -j | ${pkgs.jq}/bin/jq -r .id") (defpoll current-window :interval "1s" "${pkgs.hyprland}/bin/hyprctl activewindow -j | ${pkgs.jq}/bin/jq -r .title") ;; Widgets (defwidget bar [] (box :orientation "h" :class "bar" :space-evenly false (box :class "left" :halign "start" :spacing 8 ;; Start menu with eventbox for hover (eventbox :onhover "${pkgs.pulseaudio}/bin/paplay ${config.home.homeDirectory}/.config/eww/beep.ogg &" (button :class "startmenu" :onclick "${pkgs.walker}/bin/walker" "⚡")) (box :class "workspaces" :spacing 4 (for ws in workspaces (button :onclick "${pkgs.hyprland}/bin/hyprctl dispatch workspace ''${ws.id}" :class { ws.id == active-workspace ? "active" : "" } "''${ws.name}"))) (label :class "clock" :text time) (label :class "timer" :text (timer-widget))) (box :class "center" :halign "center" (label :text {current-window ? current-window : "No Windows"})) (box :class "right" :halign "end" :spacing 8 (label :class "cpu" :text " {cpu-usage}%") (label :class "memory" :text " {memory}") (label :class "temperature" :text " {temperature}") ;; Pulseaudio with eventbox for hover (eventbox :onhover "${pkgs.pulseaudio}/bin/paplay ${config.home.homeDirectory}/.config/eww/beep.ogg &" :onclick "${pkgs.lxqt.pavucontrol-qt}/bin/pavucontrol-qt" (label :class "pulseaudio" :text {mute ? "" : ""} " {volume}%")) (label :class "battery" :text {battery-status == "Charging" ? "󰂄" : "󰁹"} " {battery}%") ;; Bluetooth with eventbox for hover (eventbox :onhover "${pkgs.pulseaudio}/bin/paplay ${config.home.homeDirectory}/.config/eww/beep.ogg &" :onclick "${pkgs.bluetui}/bin/bluetui" (button :class "bluetooth" "")) ;; Exit with eventbox for hover (eventbox :onhover "${pkgs.pulseaudio}/bin/paplay ${config.home.homeDirectory}/.config/eww/beep.ogg &" :onclick "${pkgs.wlogout}/bin/wlogout" (button :class "exit" "")))) ;; Timer logic (defpoll timer-display :interval "1s" "${timerScript}/bin/timer.sh") (defwidget timer-widget [] (label :text timer-display)) ;; Window (defwindow bar :monitor 0 :geometry (geometry :x "0%" :y "0%" :width "100%" :height "40px") :stacking "fg" :windowtype "dock" :reserve (struts :distance "40px" :side "top") (bar)) ''; home.file.".config/eww/eww.css".text = '' * { font-family: "JetBrainsMono Nerd Font", monospace; font-size: 14px; color: #ff9999; background-color: transparent; } .bar { background-color: #1a0000; border-bottom: 1px solid #ff4d4d; padding: 0 16px; min-height: 40px; } .left, .center, .right { padding: 8px 0; } button, label { padding: 4px 12px; border-radius: 4px; background-color: transparent; } button:hover, eventbox:hover > * { background-color: rgba(255, 77, 77, 0.2); } .active { background-color: rgba(255, 77, 77, 0.3); box-shadow: 0 0 8px rgba(255, 77, 77, 0.5); } .cpu, .memory, .temperature, .pulseaudio, .battery { padding: 4px 8px; } .exit { background-color: rgba(255, 77, 77, 0.3); margin-left: 8px; } .exit:hover { background-color: rgba(255, 77, 77, 0.5); } .bluetooth { background-color: rgba(77, 77, 255, 0.2); } .bluetooth:hover { background-color: rgba(77, 77, 255, 0.4); } ''; # Ensure EWW starts with Hyprland wayland.windowManager.hyprland.settings.exec-once = [ "${pkgs.eww}/bin/eww daemon" "sleep 1 && ${pkgs.eww}/bin/eww open bar" ]; }