From 6117dca845d7d46ea7bb12c5dedf4fc6c2a91158 Mon Sep 17 00:00:00 2001 From: soraefir Date: Sat, 13 Jun 2026 14:04:33 +0200 Subject: [PATCH] add quick actions tab --- .../home/wayland/apps/eww/bar/css/_clock.scss | 70 +++++++++++----- .../wayland/apps/eww/bar/scripts/brightness | 28 +++++++ .../wayland/apps/eww/bar/scripts/nightlight | 13 +++ .../wayland/apps/eww/bar/scripts/power-save | 9 ++ .../wayland/apps/eww/bar/scripts/screenshot | 5 ++ .../home/wayland/apps/eww/bar/scripts/volume | 20 ++++- .../wayland/apps/eww/bar/scripts/wallpaper | 2 + .../wayland/apps/eww/bar/windows/clock.yuck | 84 ++++++++++++++++--- modules/nixos/system/hw/base/default.nix | 3 +- modules/nixos/system/hw/power/default.nix | 1 + 10 files changed, 198 insertions(+), 37 deletions(-) create mode 100755 modules/home/wayland/apps/eww/bar/scripts/brightness create mode 100755 modules/home/wayland/apps/eww/bar/scripts/nightlight create mode 100755 modules/home/wayland/apps/eww/bar/scripts/power-save create mode 100755 modules/home/wayland/apps/eww/bar/scripts/screenshot create mode 100755 modules/home/wayland/apps/eww/bar/scripts/wallpaper diff --git a/modules/home/wayland/apps/eww/bar/css/_clock.scss b/modules/home/wayland/apps/eww/bar/css/_clock.scss index 87aeba9..bc31216 100644 --- a/modules/home/wayland/apps/eww/bar/css/_clock.scss +++ b/modules/home/wayland/apps/eww/bar/css/_clock.scss @@ -1,29 +1,20 @@ + calendar { - padding: 5pt; + padding: 2pt 1pt; + font-size: 10pt; - :selected { - @include color-accent; - } - - .header { + header { + padding: 2pt 0; @include color-body; } - .highlight { - @include color-accent; - font-weight: bold; - } - - label { - font-size: 20pt; - @include color-accent; - } - - :indeterminate { - color: $base03; - } + :selected { @include color-accent; } + .highlight { @include color-accent; font-weight: bold; } + :indeterminate { color: $base03; } } +.cal-box .sys-section-header { margin-bottom: 4pt; } + .hour, .month { font-weight: bolder; @@ -46,7 +37,36 @@ calendar { // Clock window accents .weather-accent { background-color: $base0A; } +.cal-accent { background-color: $base0B; } +.bri-accent { background-color: $base09; } .vol-accent { background-color: $base0D; } +.quick-accent { background-color: $base0E; } + +// Quick actions +.quick-grid { margin-top: 2pt; } + +.quick-btn { + @include background-base2; + @include border-radius; + padding: 8pt 4pt; + margin: 4px; + min-width: 0; + min-height: 0; + border: none; + + &:hover { + @include background-active; + .quick-icon, .quick-label {color: $base01;} + } +} + +.quick-btn-active { + .quick-icon { @include color-accent; } + .quick-label { @include color-accent; } +} + +.quick-icon { font-size: 1.5em; @include color-body; } +.quick-label { font-size: 0.68em; margin-top: 3pt; @include color-body; } // Weather section .weather-main { margin-bottom: 8pt; } @@ -57,10 +77,18 @@ calendar { // Volume section .ctrl-row { margin-bottom: 4pt; } -.ctrl-icon { font-size: 1.1em; min-width: 22pt; @include color-body; } -.ctrl-muted { @include color-inactive; } +.ctrl-icon { font-size: 1.1em; min-width: 22pt; @include border-radius; @include color-body; } +.ctrl-icon:hover { @include background-active; } +.ctrl-muted { @include color-inactive; } .ctrl-value { font-size: 0.72em; min-width: 28pt; @include color-active; } +scale.ctrl-slider.ctrl-slider-muted { + trough { + highlight { background-color: $base03; } + slider { background-color: $base03; } + } +} + scale.ctrl-slider { padding: 2pt 4pt; trough { diff --git a/modules/home/wayland/apps/eww/bar/scripts/brightness b/modules/home/wayland/apps/eww/bar/scripts/brightness new file mode 100755 index 0000000..995994f --- /dev/null +++ b/modules/home/wayland/apps/eww/bar/scripts/brightness @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +BACKLIGHT="/sys/class/backlight" +DEV=$(ls "$BACKLIGHT" 2>/dev/null | head -n1) + +gen_output() { + if [ -z "$DEV" ]; then + echo '{"percent":0,"available":false}' + return + fi + max=$(cat "$BACKLIGHT/$DEV/max_brightness") + cur=$(cat "$BACKLIGHT/$DEV/actual_brightness" 2>/dev/null || cat "$BACKLIGHT/$DEV/brightness") + percent=$(awk -v c="$cur" -v m="$max" 'BEGIN{print int(c/m*100+0.5)}') + printf '{"percent":%d,"available":true}\n' "$percent" +} + +case "$1" in + set) + [ -z "$DEV" ] && exit 0 + brightnessctl -d "$DEV" set "${2}%" -q 2>/dev/null + ;; + *) + gen_output + [ -z "$DEV" ] && exit 0 + # Poll for changes every 2s (sysfs files don't support inotify reliably) + while true; do sleep 2; gen_output; done + ;; +esac diff --git a/modules/home/wayland/apps/eww/bar/scripts/nightlight b/modules/home/wayland/apps/eww/bar/scripts/nightlight new file mode 100755 index 0000000..5f26012 --- /dev/null +++ b/modules/home/wayland/apps/eww/bar/scripts/nightlight @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +case "$1" in + status) + pgrep -x wlsunset >/dev/null 2>&1 && echo true || echo false + ;; + *) + if pgrep -x wlsunset >/dev/null 2>&1; then + pkill -x wlsunset && echo false + else + wlsunset -T 4500 -t 3200 & echo true + fi + ;; +esac diff --git a/modules/home/wayland/apps/eww/bar/scripts/power-save b/modules/home/wayland/apps/eww/bar/scripts/power-save new file mode 100755 index 0000000..2fa337d --- /dev/null +++ b/modules/home/wayland/apps/eww/bar/scripts/power-save @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +current=$(eww state 2>/dev/null | grep '^power-save:' | awk '{print $2}') +if [ "$current" = "true" ]; then + powerprofilesctl set balanced 2>/dev/null || true + echo false +else + powerprofilesctl set power-saver 2>/dev/null || true + echo true +fi diff --git a/modules/home/wayland/apps/eww/bar/scripts/screenshot b/modules/home/wayland/apps/eww/bar/scripts/screenshot new file mode 100755 index 0000000..090b123 --- /dev/null +++ b/modules/home/wayland/apps/eww/bar/scripts/screenshot @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +DIR="$HOME/Pictures/Screenshots" +mkdir -p "$DIR" +FILE="$DIR/$(date +%Y-%m-%d_%H-%M-%S).png" +grim -g "$(slurp)" "$FILE" && wl-copy < "$FILE" diff --git a/modules/home/wayland/apps/eww/bar/scripts/volume b/modules/home/wayland/apps/eww/bar/scripts/volume index 307ac45..3e52f06 100755 --- a/modules/home/wayland/apps/eww/bar/scripts/volume +++ b/modules/home/wayland/apps/eww/bar/scripts/volume @@ -12,13 +12,14 @@ gen_output() { lvl=$(awk -v n="$percent" 'BEGIN{print int(n/34)}') sink_muted=$(ismuted "SINK") source_muted=$(ismuted "SOURCE") + sink=$(wpctl inspect @DEFAULT_AUDIO_SINK@ 2>/dev/null | grep -m1 'node\.nick' | sed 's/.*= "\(.*\)"/\1/') - [ "$sink_muted" = 0 ] && icon="󰝟" || icon="${volicons[$lvl]}" + [ "$sink_muted" = 0 ] && icon="󰝟" || icon="${volicons[$lvl]}" [ "$source_muted" = 0 ] && mic_icon="󰍭" || mic_icon="󰍬" - printf '{"icon":"%s","percent":%s,"sink_muted":%s,"mic_icon":"%s","microphone":%s,"source_muted":%s}\n' \ + printf '{"icon":"%s","percent":%s,"sink_muted":%s,"mic_icon":"%s","microphone":%s,"source_muted":%s,"sink":"%s"}\n' \ "$icon" "$percent" "$([ "$sink_muted" = 0 ] && echo true || echo false)" \ - "$mic_icon" "$(vol SOURCE)" "$([ "$source_muted" = 0 ] && echo true || echo false)" + "$mic_icon" "$(vol SOURCE)" "$([ "$source_muted" = 0 ] && echo true || echo false)" "$sink" } case "$1" in @@ -26,7 +27,18 @@ case "$1" in setvol) setvol "$2" "$3" ;; *) gen_output - pw-cli -m 2>/dev/null | rg --line-buffered "PipeWire:Interface:Client" | while read -r _; do + + tmp=$(mktemp -d) + pipe="$tmp/vol-events" + mkfifo "$pipe" + trap 'rm -rf "$tmp"; kill 0 2>/dev/null' EXIT INT TERM + + # 1s polling fallback + (while true; do sleep 1; echo poll; done) > "$pipe" & + # PipeWire property-change events (fires on mute/volume change) + (pw-cli -m 2>/dev/null | grep --line-buffered "changed") > "$pipe" & + + while IFS= read -r _ < "$pipe"; do gen_output done ;; diff --git a/modules/home/wayland/apps/eww/bar/scripts/wallpaper b/modules/home/wayland/apps/eww/bar/scripts/wallpaper new file mode 100755 index 0000000..219a78d --- /dev/null +++ b/modules/home/wayland/apps/eww/bar/scripts/wallpaper @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +nohup bash "$HOME/.config/script/wallpaper.sh" >/dev/null 2>&1 & diff --git a/modules/home/wayland/apps/eww/bar/windows/clock.yuck b/modules/home/wayland/apps/eww/bar/windows/clock.yuck index 361cb43..649894f 100644 --- a/modules/home/wayland/apps/eww/bar/windows/clock.yuck +++ b/modules/home/wayland/apps/eww/bar/windows/clock.yuck @@ -4,9 +4,13 @@ "scripts/weather") (deflisten volume - :initial '{"icon":"󰕾","percent":50,"sink_muted":false,"mic_icon":"󰍬","microphone":50,"source_muted":false}' + :initial '{"icon":"󰕾","percent":50,"sink_muted":false,"mic_icon":"󰍬","microphone":50,"source_muted":false,"sink":""}' "scripts/volume") +(deflisten brightness + :initial '{"percent":0,"available":false}' + "scripts/brightness") + ; --- Weather --- (defwidget weather-section [] @@ -14,9 +18,9 @@ (section-header :title {weather.city != "" ? "Weather · ${weather.city}" : "Weather"} :accent "weather-accent") - (box :orientation "h" :space-evenly false :valign "center" :class "weather-main" - (label :class "weather-icon" :text {weather.icon}) - (box :orientation "v" :space-evenly false + (box :orientation "h" :space-evenly false :halign "center" :class "weather-main" + (label :class "weather-icon" :valign "center" :text {weather.icon}) + (box :orientation "v" :space-evenly false :valign "center" (label :class "weather-temp" :text "${weather.temp}°C") (label :class "weather-desc" :text {weather.desc}))) (box :orientation "h" :space-evenly true :class "weather-stats" @@ -40,13 +44,16 @@ (label :text icon)) (scale :min 0 :max 100 :value value - :hexpand true :class "ctrl-slider" - :onchange onchange) - (label :class "ctrl-value" :halign "end" :text "${value}%"))) + :hexpand true + :class "ctrl-slider ${muted ? 'ctrl-slider-muted' : ''}" + :onchange {muted ? "true" : onchange}) + (label :class "ctrl-value ${muted ? 'ctrl-muted' : ''}" :halign "end" :text "${value}%"))) (defwidget volume-section [] (box :orientation "v" :space-evenly false :class "sys-section" - (section-header :title "Volume" :accent "vol-accent") + (section-header + :title {volume.sink != "" ? "Volume · ${volume.sink}" : "Volume"} + :accent "vol-accent") (vol-row :icon {volume.icon} :value {volume.percent} @@ -60,13 +67,68 @@ :onchange "scripts/volume setvol SOURCE {}" :onclick "scripts/volume mute SOURCE"))) +; --- Quick Actions --- + +(defvar power-save false) +(defvar night-light false) + +(defwidget quick-btn [icon label onclick active] + (button :class "quick-btn ${active ? 'quick-btn-active' : ''}" + :onclick onclick + (box :orientation "v" :space-evenly false :halign "center" :valign "center" + (label :class "quick-icon" :text icon) + (label :class "quick-label" :text label)))) + +(defwidget quick-section [] + (box :orientation "v" :space-evenly false :class "sys-section" + (section-header :title "Quick Actions" :accent "quick-accent") + (box :orientation "h" :homogeneous true :class "quick-grid" + (quick-btn + :icon "󰸉" :label "Wallpaper" + :onclick "scripts/wallpaper" + :active false) + (quick-btn + :icon "󱐋" :label "Power Save" + :onclick "eww update power-save=$(scripts/power-save)" + :active {power-save}) + (quick-btn + :icon "󰌵" :label "Night Light" + :onclick "eww update night-light=$(scripts/nightlight)" + :active {night-light}) + (quick-btn + :icon "󰹑" :label "Screenshot" + :onclick "scripts/screenshot" + :active false)))) + +; --- Brightness --- + +(defwidget brightness-section [] + (box :orientation "v" :space-evenly false :class "sys-section" + :visible {brightness.available} + (section-header :title "Brightness" :accent "bri-accent") + (box :orientation "h" :space-evenly false :valign "center" :class "ctrl-row" + (label :class "ctrl-icon" :text "󰃠") + (scale + :min 1 :max 100 :value {brightness.percent} + :hexpand true + :class "ctrl-slider" + :onchange "scripts/brightness set {}") + (label :class "ctrl-value" :halign "end" :text "${brightness.percent}%")))) + ; --- Root --- (defwidget clock-win [] (box :class "sys-win" :orientation "v" :space-evenly false + (volume-section) + (brightness-section) + (box :class "section-sep") + (quick-section) + (box :class "section-sep") (weather-section) (box :class "section-sep") - (calendar) - (box :class "section-sep") - (volume-section))) + (box :orientation "v" :space-evenly false :class "sys-section cal-box" + (section-header :title "Calendar" :accent "cal-accent") + (calendar :show-week-numbers false)) + )) + diff --git a/modules/nixos/system/hw/base/default.nix b/modules/nixos/system/hw/base/default.nix index 16c7c86..148e082 100644 --- a/modules/nixos/system/hw/base/default.nix +++ b/modules/nixos/system/hw/base/default.nix @@ -1,4 +1,5 @@ -{ ... }: { +{ lib, ... }: { services.fwupd.enable = true; hardware.enableAllFirmware = false; + services.power-profiles-daemon.enable = lib.mkDefault true; } diff --git a/modules/nixos/system/hw/power/default.nix b/modules/nixos/system/hw/power/default.nix index 2ea5a82..87aedc0 100644 --- a/modules/nixos/system/hw/power/default.nix +++ b/modules/nixos/system/hw/power/default.nix @@ -1,5 +1,6 @@ { lib, config, pkgs, ... }: { config = lib.mkIf (config.syscfg.make.power) { + services.power-profiles-daemon.enable = false; # conflicts with TLP services.tlp = { enable = true; settings = {