diff --git a/configs/nixos/modules/desktop/default.nix b/configs/nixos/modules/desktop/default.nix index 800cc22..cfe5592 100644 --- a/configs/nixos/modules/desktop/default.nix +++ b/configs/nixos/modules/desktop/default.nix @@ -19,6 +19,7 @@ modules.desktop.utilities.audio.enable = lib.mkDefault true; modules.desktop.utilities.clipboard.enable = lib.mkDefault true; modules.desktop.utilities.osd.enable = lib.mkDefault true; + modules.desktop.utilities.network.enable = lib.mkDefault true; modules.desktop.utilities.recording.enable = lib.mkDefault true; modules.desktop.utilities.screenshot.enable = lib.mkDefault true; modules.desktop.utilities.theming.enable = lib.mkDefault true; diff --git a/configs/nixos/modules/desktop/session/hyprland/default.nix b/configs/nixos/modules/desktop/session/hyprland/default.nix index 2490799..769e751 100644 --- a/configs/nixos/modules/desktop/session/hyprland/default.nix +++ b/configs/nixos/modules/desktop/session/hyprland/default.nix @@ -4,6 +4,9 @@ ... }: # The Hyprland compositor. +let + glyph = code: builtins.fromJSON ''"\u${code}"''; +in { options.modules.desktop.session.hyprland.enable = lib.mkEnableOption "the Hyprland compositor"; @@ -227,5 +230,19 @@ }; } ]; + + registry.waybar.${config.networking.hostName}."hyprland/workspaces" = { + position = "left"; + order = 10; + settings = { + on-click = "activate"; + format = "{id} {windows}"; + format-window-separator = " "; + window-rewrite-default = glyph "f2d0"; + window-rewrite = lib.mapAttrs' ( + _name: windowIcon: lib.nameValuePair "class<${windowIcon.class}>" (glyph windowIcon.icon) + ) (lib.attrByPath [ config.networking.hostName ] { } config.registry.window-icon); + }; + }; }; } diff --git a/configs/nixos/modules/desktop/session/waybar.nix b/configs/nixos/modules/desktop/session/waybar.nix index 9fef276..b8c29de 100644 --- a/configs/nixos/modules/desktop/session/waybar.nix +++ b/configs/nixos/modules/desktop/session/waybar.nix @@ -34,37 +34,6 @@ let # through JSON so the glyph survives as bytes rather than an editor paste. g = code: builtins.fromJSON ''"\u${code}"''; - networkStatus = pkgs.writeShellScript "waybar-network-status" '' - active=$( - ${lib.getExe' pkgs.networkmanager "nmcli"} -t -f DEVICE,TYPE,STATE,CONNECTION device status \ - | ${lib.getExe' pkgs.gawk "awk"} -F: '$3 == "connected" && $2 != "loopback" { print; exit }' - ) - - if [ -z "$active" ]; then - ${lib.getExe pkgs.jq} -cn \ - --arg text "${g "f127"} off" \ - --arg tooltip "Network disconnected" \ - --arg class "disconnected" \ - '{ text: $text, tooltip: $tooltip, class: $class }' - exit 0 - fi - - IFS=: read -r device type _state connection <<< "$active" - - case "$type" in - wifi) icon="${g "f1eb"}" ;; - ethernet) icon="LAN" ;; - *) icon="NET" ;; - esac - - ipaddr=$(${lib.getExe' pkgs.iproute2 "ip"} -4 -o addr show dev "$device" | ${lib.getExe' pkgs.gawk "awk"} '{ print $4; exit }') - - ${lib.getExe pkgs.jq} -cn \ - --arg text "$icon $connection" \ - --arg tooltip "$device: ''${ipaddr:-no IPv4}" \ - --arg class "$type" \ - '{ text: $text, tooltip: $tooltip, class: $class }' - ''; in { options.modules.desktop.session.waybar.enable = lib.mkEnableOption "the Waybar status bar"; @@ -105,20 +74,6 @@ in }; registry.waybar.${config.networking.hostName} = { - "hyprland/workspaces" = { - position = "left"; - order = 10; - settings = { - on-click = "activate"; - format = "{id} {windows}"; - format-window-separator = " "; - window-rewrite-default = g "f2d0"; - window-rewrite = lib.mapAttrs' ( - _name: windowIcon: lib.nameValuePair "class<${windowIcon.class}>" (g windowIcon.icon) - ) (lib.attrByPath [ config.networking.hostName ] { } config.registry.window-icon); - }; - }; - clock = { position = "center"; order = 10; @@ -133,41 +88,6 @@ in }; }; - mpris = { - order = 30; - settings = { - format = "${g "f001"} {title}"; - format-paused = "${g "f04c"} {title}"; - max-length = 40; - on-click = "play-pause"; - on-scroll-up = "next"; - on-scroll-down = "previous"; - }; - }; - - wireplumber = { - order = 40; - settings = { - format = "{icon} {volume}%"; - format-muted = "${g "f026"} muted"; - format-icons = [ - (g "f026") - (g "f027") - (g "f028") - ]; - on-click = "${lib.getExe' pkgs.wireplumber "wpctl"} set-mute @DEFAULT_AUDIO_SINK@ toggle"; - }; - }; - - "custom/network" = { - order = 60; - settings = { - return-type = "json"; - exec = "${networkStatus}"; - interval = 5; - }; - }; - battery = { order = 70; settings = { diff --git a/configs/nixos/modules/desktop/utilities/audio.nix b/configs/nixos/modules/desktop/utilities/audio.nix index bbbb140..b832d65 100644 --- a/configs/nixos/modules/desktop/utilities/audio.nix +++ b/configs/nixos/modules/desktop/utilities/audio.nix @@ -5,6 +5,9 @@ ... }: # PipeWire as the desktop audio server. +let + glyph = code: builtins.fromJSON ''"\u${code}"''; +in { options.modules.desktop.utilities.audio.enable = lib.mkEnableOption "the PipeWire audio server"; @@ -15,7 +18,7 @@ locked = true; action = { kind = "exec"; - command = "${pkgs.playerctl}/bin/playerctl play-pause"; + command = "${lib.getExe pkgs.playerctl} play-pause"; }; }; @@ -24,7 +27,7 @@ locked = true; action = { kind = "exec"; - command = "${pkgs.playerctl}/bin/playerctl next"; + command = "${lib.getExe pkgs.playerctl} next"; }; }; @@ -33,7 +36,35 @@ locked = true; action = { kind = "exec"; - command = "${pkgs.playerctl}/bin/playerctl previous"; + command = "${lib.getExe pkgs.playerctl} previous"; + }; + }; + }; + + registry.waybar.${config.networking.hostName} = { + mpris = { + order = 30; + settings = { + format = "${glyph "f001"} {title}"; + format-paused = "${glyph "f04c"} {title}"; + max-length = 40; + on-click = "play-pause"; + on-scroll-up = "next"; + on-scroll-down = "previous"; + }; + }; + + wireplumber = { + order = 40; + settings = { + format = "{icon} {volume}%"; + format-muted = "${glyph "f026"} muted"; + format-icons = [ + (glyph "f026") + (glyph "f027") + (glyph "f028") + ]; + on-click = "${lib.getExe' pkgs.wireplumber "wpctl"} set-mute @DEFAULT_AUDIO_SINK@ toggle"; }; }; }; diff --git a/configs/nixos/modules/desktop/utilities/network.nix b/configs/nixos/modules/desktop/utilities/network.nix new file mode 100644 index 0000000..02b40d7 --- /dev/null +++ b/configs/nixos/modules/desktop/utilities/network.nix @@ -0,0 +1,57 @@ +{ + config, + lib, + pkgs, + ... +}: +# Desktop network status integrations. +let + glyph = code: builtins.fromJSON ''"\u${code}"''; + + networkStatus = pkgs.writeShellScript "waybar-network-status" '' + active=$( + ${lib.getExe' pkgs.networkmanager "nmcli"} -t -f DEVICE,TYPE,STATE,CONNECTION device status \ + | ${lib.getExe' pkgs.gawk "awk"} -F: '$3 == "connected" && $2 != "loopback" { print; exit }' + ) + + if [ -z "$active" ]; then + ${lib.getExe pkgs.jq} -cn \ + --arg text "${glyph "f127"} off" \ + --arg tooltip "Network disconnected" \ + --arg class "disconnected" \ + '{ text: $text, tooltip: $tooltip, class: $class }' + exit 0 + fi + + IFS=: read -r device type _state connection <<< "$active" + + case "$type" in + wifi) icon="${glyph "f1eb"}" ;; + ethernet) icon="LAN" ;; + *) icon="NET" ;; + esac + + ipaddr=$(${lib.getExe' pkgs.iproute2 "ip"} -4 -o addr show dev "$device" | ${lib.getExe' pkgs.gawk "awk"} '{ print $4; exit }') + + ${lib.getExe pkgs.jq} -cn \ + --arg text "$icon $connection" \ + --arg tooltip "$device: ''${ipaddr:-no IPv4}" \ + --arg class "$type" \ + '{ text: $text, tooltip: $tooltip, class: $class }' + ''; +in +{ + options.modules.desktop.utilities.network.enable = + lib.mkEnableOption "desktop network status integration"; + + config = lib.mkIf config.modules.desktop.utilities.network.enable { + registry.waybar.${config.networking.hostName}."custom/network" = { + order = 60; + settings = { + return-type = "json"; + exec = "${networkStatus}"; + interval = 5; + }; + }; + }; +}