diff --git a/modules/nixos/desktop/hyprland/options.nix b/modules/nixos/desktop/hyprland/options.nix index db684f2..00c4f51 100644 --- a/modules/nixos/desktop/hyprland/options.nix +++ b/modules/nixos/desktop/hyprland/options.nix @@ -18,14 +18,16 @@ in options.${namespace}.desktop.hyprland = { enable = mkEnableOption "enable hyprland desktop environment"; + # These options are convenience aliases that feed into mjallen.wallpaper.* + # when the hyprland wallpaper sub-module is active. wallpaperSource = mkOpt (types.enum [ "bing" "nasa" ]) "bing" "Source for the wallpaper (bing or nasa)"; - wallpaper = mkOpt types.path "/var/lib/wallpapers/current.jpg" "Path to the wallpaper folder"; + wallpaper = mkOpt types.path "/var/lib/wallpapers/current.jpg" "Path to the active wallpaper file"; - wallpaperDir = mkOpt types.path "/var/lib/wallpapers" "Path to the wallpaper folder"; + wallpaperDir = mkOpt types.path "/var/lib/wallpapers" "Path to the wallpaper directory"; defaultWallpaper = mkOpt types.path "${defaultWallpaper}/default.jpg" "Default wallpaper"; }; diff --git a/modules/nixos/desktop/hyprland/wallpapers/default.nix b/modules/nixos/desktop/hyprland/wallpapers/default.nix index 851e2d0..b3d02ab 100644 --- a/modules/nixos/desktop/hyprland/wallpapers/default.nix +++ b/modules/nixos/desktop/hyprland/wallpapers/default.nix @@ -7,176 +7,20 @@ }: let cfg = config.${namespace}.desktop.hyprland; - - # The script to use based on the selected wallpaper source - wallpaper-command = if cfg.wallpaperSource == "nasa" then "nasa-wallpaper" else "bing-wallpaper"; - - # System activation script to ensure wallpaper is available early in boot - wallpaper-activation-script = '' - # Create wallpaper directory if it doesn't exist - mkdir -p ${cfg.wallpaperDir} - - # Copy default wallpaper as fallback if it doesn't exist - if [ ! -f ${cfg.wallpaperDir}/fallback.jpg ]; then - cp ${cfg.defaultWallpaper} ${cfg.wallpaperDir}/fallback.jpg - fi - - # If no current wallpaper exists, use the fallback - if [ ! -f ${cfg.wallpaperDir}/current.jpg ]; then - cp ${cfg.wallpaperDir}/fallback.jpg ${cfg.wallpaperDir}/current.jpg - fi - - # Create symlink for Plymouth and SDDM - ln -sf ${cfg.wallpaperDir}/current.jpg /run/wallpaper.jpg - ''; - - bing-wallpaper = pkgs.writeScriptBin "bing-wallpaper" '' - # Directory to store wallpapers - WALLPAPER_DIR="${cfg.wallpaperDir}" - IMG_PATH="$WALLPAPER_DIR/current.jpg" - FALLBACK_PATH="$WALLPAPER_DIR/fallback.jpg" - - # Ensure directory exists - mkdir -p "$WALLPAPER_DIR" - - # Copy to the standard location for other services - ln -sf "$IMG_PATH" /run/wallpaper.jpg - - # Try to download new wallpaper - if ${lib.getExe pkgs.curl} -s --connect-timeout 5 --max-time 10 "https://www.bing.com" > /dev/null; then - URL=$(${lib.getExe pkgs.curl} -s "https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1" | \ - ${lib.getExe pkgs.jq} -r '.images[0].url') - FULL_URL="https://www.bing.com$URL" - if ${lib.getExe pkgs.curl} -s -o "$IMG_PATH.tmp" "$FULL_URL"; then - mv "$IMG_PATH.tmp" "$IMG_PATH" - echo "Downloaded $FULL_URL to $IMG_PATH successfully" - else - echo "Failed to download Bing wallpaper, using previous or fallback" - # If current doesn't exist, use fallback - if [ ! -f "$IMG_PATH" ] && [ -f "$FALLBACK_PATH" ]; then - cp "$FALLBACK_PATH" "$IMG_PATH" - fi - fi - else - echo "Network unavailable, using previous or fallback wallpaper" - # If current doesn't exist, use fallback - if [ ! -f "$IMG_PATH" ] && [ -f "$FALLBACK_PATH" ]; then - cp "$FALLBACK_PATH" "$IMG_PATH" - fi - fi - ''; - - nasa-wallpaper = pkgs.writeScriptBin "nasa-wallpaper" '' - # Directory to store wallpapers - WALLPAPER_DIR="${cfg.wallpaperDir}" - IMG_PATH="$WALLPAPER_DIR/current.jpg" - FALLBACK_PATH="$WALLPAPER_DIR/fallback.jpg" - - # Ensure directory exists - mkdir -p "$WALLPAPER_DIR" - - # Copy to the standard location for other services - ln -sf "$IMG_PATH" /run/wallpaper.jpg - - # Try to download new wallpaper - if ${lib.getExe pkgs.curl} -s --connect-timeout 5 --max-time 10 "https://api.nasa.gov" > /dev/null; then - APOD_URL="https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY" - IMAGE_URL=$(${lib.getExe pkgs.curl} -s "$APOD_URL" | ${lib.getExe pkgs.jq} -r '.hdurl // .url') - if ${lib.getExe pkgs.curl} -s -o "$IMG_PATH.tmp" "$IMAGE_URL"; then - mv "$IMG_PATH.tmp" "$IMG_PATH" - echo "Downloaded $IMAGE_URL to $IMG_PATH successfully" - else - echo "Failed to download NASA wallpaper, using previous or fallback" - # If current doesn't exist, use fallback - if [ ! -f "$IMG_PATH" ] && [ -f "$FALLBACK_PATH" ]; then - cp "$FALLBACK_PATH" "$IMG_PATH" - fi - fi - else - echo "Network unavailable, using previous or fallback wallpaper" - # If current doesn't exist, use fallback - if [ ! -f "$IMG_PATH" ] && [ -f "$FALLBACK_PATH" ]; then - cp "$FALLBACK_PATH" "$IMG_PATH" - fi - fi - ''; in { imports = [ ../options.nix ]; + # Wire the hyprland wallpaper options through to the shared wallpaper module, + # and provide the hyprctl hot-reload command so hyprpaper picks up the new image. config = lib.mkIf cfg.enable { - environment.systemPackages = [ - bing-wallpaper - nasa-wallpaper - ]; - - # Add system activation script to ensure wallpaper is available early - system.activationScripts.wallpaper = wallpaper-activation-script; - - systemd = { - services = { - preload-wallpaper = { - enable = true; - wants = [ "network-online.target" ]; - after = [ "network-online.target" ]; - # before = [ "display-manager.service" ]; - # requiredBy = [ - # "plymouth-quit-wait.service" - # "display-manager.service" - # ]; - # wantedBy = [ "display-manager.service" ]; - path = [ - pkgs.bash - pkgs.jq - pkgs.curl - bing-wallpaper - nasa-wallpaper - ]; - script = '' - ${wallpaper-command} - ''; - serviceConfig = { - Type = "oneshot"; - TimeoutSec = "10s"; # Limit how long we wait for network - }; - }; - }; - user = { - services = { - reload-wallpaper = { - enable = true; - path = [ - pkgs.bash - pkgs.jq - pkgs.curl - pkgs.hyprland - bing-wallpaper - nasa-wallpaper - ]; - script = '' - ${wallpaper-command} - ${lib.getExe' pkgs.hyprland "hyprctl"} hyprpaper wallpaper ,${cfg.wallpaper}, - ''; - serviceConfig = { - Type = "oneshot"; - }; - }; - }; - # Create a timer to run the service periodically - timers = { - reload-wallpaper = { - description = "Timer for reload-wallpaper"; - wantedBy = [ "timers.target" ]; - - # Timer configuration - timerConfig = { - OnCalendar = "daily"; # Check every day - Persistent = true; # Run immediately if last run was missed - Unit = "reload-wallpaper.service"; - }; - }; - }; - }; + ${namespace}.wallpaper = { + enable = true; + source = cfg.wallpaperSource; + path = cfg.wallpaper; + dir = cfg.wallpaperDir; + defaultWallpaper = cfg.defaultWallpaper; + reloadCommand = "${lib.getExe' pkgs.hyprland "hyprctl"} hyprpaper wallpaper ,${cfg.wallpaper},"; }; }; } diff --git a/modules/nixos/desktop/plasma/default.nix b/modules/nixos/desktop/plasma/default.nix index bcfe48f..2c72e59 100644 --- a/modules/nixos/desktop/plasma/default.nix +++ b/modules/nixos/desktop/plasma/default.nix @@ -1,30 +1,55 @@ { config, lib, + pkgs, namespace, ... }: let - inherit (lib.${namespace}) mkBoolOpt; + inherit (lib.${namespace}) mkBoolOpt mkOpt; cfg = config.${namespace}.desktop.plasma; + wallpaperCfg = config.${namespace}.wallpaper; in { options.${namespace}.desktop.plasma = { enable = lib.mkEnableOption "KDE Plasma 6 desktop environment"; wayland.enable = mkBoolOpt true "Use the Wayland session (default) instead of X11"; - }; - config = lib.mkIf cfg.enable { - services = { - desktopManager.plasma6.enable = true; + wallpaper = { + enable = mkBoolOpt false "Enable automatic wallpaper management (Bing/NASA daily download)"; - displayManager.sddm = { - enable = true; - wayland.enable = cfg.wayland.enable; - }; + source = mkOpt (lib.types.enum [ + "bing" + "nasa" + ]) "bing" "Source for the wallpaper (bing or nasa)"; }; - - xdg.portal.extraPortals = [ ]; }; + + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + { + services = { + desktopManager.plasma6.enable = true; + + displayManager.sddm = { + enable = true; + wayland.enable = cfg.wayland.enable; + }; + }; + + xdg.portal.extraPortals = [ ]; + } + + # Wallpaper management: wire the shared wallpaper module in when requested. + # plasma-apply-wallpaperimage hot-reloads the wallpaper in the running session. + (lib.mkIf cfg.wallpaper.enable { + ${namespace}.wallpaper = { + enable = true; + source = cfg.wallpaper.source; + reloadCommand = "${lib.getExe' pkgs.kdePackages.plasma-workspace "plasma-apply-wallpaperimage"} /run/wallpaper.jpg"; + }; + }) + ] + ); } diff --git a/modules/nixos/wallpaper/default.nix b/modules/nixos/wallpaper/default.nix new file mode 100644 index 0000000..8889f91 --- /dev/null +++ b/modules/nixos/wallpaper/default.nix @@ -0,0 +1,173 @@ +{ + config, + lib, + pkgs, + namespace, + ... +}: +let + cfg = config.${namespace}.wallpaper; + + wallpaper-command = if cfg.source == "nasa" then "nasa-wallpaper" else "bing-wallpaper"; + + # System activation script to ensure wallpaper is available early in boot + wallpaper-activation-script = '' + # Create wallpaper directory if it doesn't exist + mkdir -p ${cfg.dir} + + # Copy default wallpaper as fallback if it doesn't exist + if [ ! -f ${cfg.dir}/fallback.jpg ]; then + cp ${cfg.defaultWallpaper} ${cfg.dir}/fallback.jpg + fi + + # If no current wallpaper exists, use the fallback + if [ ! -f ${cfg.dir}/current.jpg ]; then + cp ${cfg.dir}/fallback.jpg ${cfg.dir}/current.jpg + fi + + # Create symlink for Plymouth and display manager + ln -sf ${cfg.dir}/current.jpg /run/wallpaper.jpg + ''; + + bing-wallpaper = pkgs.writeScriptBin "bing-wallpaper" '' + # Directory to store wallpapers + WALLPAPER_DIR="${cfg.dir}" + IMG_PATH="$WALLPAPER_DIR/current.jpg" + FALLBACK_PATH="$WALLPAPER_DIR/fallback.jpg" + + # Ensure directory exists + mkdir -p "$WALLPAPER_DIR" + + # Update symlink + ln -sf "$IMG_PATH" /run/wallpaper.jpg + + # Try to download new wallpaper + if ${lib.getExe pkgs.curl} -s --connect-timeout 5 --max-time 10 "https://www.bing.com" > /dev/null; then + URL=$(${lib.getExe pkgs.curl} -s "https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1" | \ + ${lib.getExe pkgs.jq} -r '.images[0].url') + FULL_URL="https://www.bing.com$URL" + if ${lib.getExe pkgs.curl} -s -o "$IMG_PATH.tmp" "$FULL_URL"; then + mv "$IMG_PATH.tmp" "$IMG_PATH" + echo "Downloaded $FULL_URL to $IMG_PATH successfully" + else + echo "Failed to download Bing wallpaper, using previous or fallback" + if [ ! -f "$IMG_PATH" ] && [ -f "$FALLBACK_PATH" ]; then + cp "$FALLBACK_PATH" "$IMG_PATH" + fi + fi + else + echo "Network unavailable, using previous or fallback wallpaper" + if [ ! -f "$IMG_PATH" ] && [ -f "$FALLBACK_PATH" ]; then + cp "$FALLBACK_PATH" "$IMG_PATH" + fi + fi + ''; + + nasa-wallpaper = pkgs.writeScriptBin "nasa-wallpaper" '' + # Directory to store wallpapers + WALLPAPER_DIR="${cfg.dir}" + IMG_PATH="$WALLPAPER_DIR/current.jpg" + FALLBACK_PATH="$WALLPAPER_DIR/fallback.jpg" + + # Ensure directory exists + mkdir -p "$WALLPAPER_DIR" + + # Update symlink + ln -sf "$IMG_PATH" /run/wallpaper.jpg + + # Try to download new wallpaper + if ${lib.getExe pkgs.curl} -s --connect-timeout 5 --max-time 10 "https://api.nasa.gov" > /dev/null; then + APOD_URL="https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY" + IMAGE_URL=$(${lib.getExe pkgs.curl} -s "$APOD_URL" | ${lib.getExe pkgs.jq} -r '.hdurl // .url') + if ${lib.getExe pkgs.curl} -s -o "$IMG_PATH.tmp" "$IMAGE_URL"; then + mv "$IMG_PATH.tmp" "$IMG_PATH" + echo "Downloaded $IMAGE_URL to $IMG_PATH successfully" + else + echo "Failed to download NASA wallpaper, using previous or fallback" + if [ ! -f "$IMG_PATH" ] && [ -f "$FALLBACK_PATH" ]; then + cp "$FALLBACK_PATH" "$IMG_PATH" + fi + fi + else + echo "Network unavailable, using previous or fallback wallpaper" + if [ ! -f "$IMG_PATH" ] && [ -f "$FALLBACK_PATH" ]; then + cp "$FALLBACK_PATH" "$IMG_PATH" + fi + fi + ''; + + reloadScript = lib.optionalString (cfg.reloadCommand != null) cfg.reloadCommand; +in +{ + imports = [ ./options.nix ]; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ + bing-wallpaper + nasa-wallpaper + ]; + + # Ensure wallpaper directory and symlink exist before the display manager starts + system.activationScripts.wallpaper = wallpaper-activation-script; + + systemd = { + services = { + # System-level: download on boot after network is available + preload-wallpaper = { + enable = true; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + path = [ + pkgs.bash + pkgs.jq + pkgs.curl + bing-wallpaper + nasa-wallpaper + ]; + script = '' + ${wallpaper-command} + ''; + serviceConfig = { + Type = "oneshot"; + TimeoutSec = "10s"; + }; + }; + }; + + user = { + services = { + # User-level: daily refresh + optional DE hot-reload + reload-wallpaper = { + enable = true; + path = [ + pkgs.bash + pkgs.jq + pkgs.curl + bing-wallpaper + nasa-wallpaper + ]; + script = '' + ${wallpaper-command} + ${reloadScript} + ''; + serviceConfig = { + Type = "oneshot"; + }; + }; + }; + + timers = { + reload-wallpaper = { + description = "Timer for reload-wallpaper"; + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = "daily"; + Persistent = true; + Unit = "reload-wallpaper.service"; + }; + }; + }; + }; + }; + }; +} diff --git a/modules/nixos/wallpaper/options.nix b/modules/nixos/wallpaper/options.nix new file mode 100644 index 0000000..4268e19 --- /dev/null +++ b/modules/nixos/wallpaper/options.nix @@ -0,0 +1,36 @@ +{ + lib, + pkgs, + namespace, + ... +}: +with lib; +let + inherit (lib.${namespace}) mkOpt; + + # Default fallback wallpaper (included in the system) + defaultWallpaper = pkgs.runCommand "default-wallpaper" { } '' + mkdir -p $out + cp ${pkgs.nixos-artwork.wallpapers.nineish-dark-gray}/share/backgrounds/nixos/nix-wallpaper-nineish-dark-gray.png $out/default.jpg + ''; +in +{ + options.${namespace}.wallpaper = { + enable = mkEnableOption "shared wallpaper management (download, symlink, and boot integration)"; + + source = mkOpt (types.enum [ + "bing" + "nasa" + ]) "bing" "Source for the wallpaper (bing or nasa)"; + + path = mkOpt types.path "/var/lib/wallpapers/current.jpg" "Path to the active wallpaper file"; + + dir = mkOpt types.path "/var/lib/wallpapers" "Directory where wallpapers are stored"; + + defaultWallpaper = mkOpt types.path "${defaultWallpaper}/default.jpg" "Default fallback wallpaper"; + + reloadCommand = + mkOpt (types.nullOr types.str) null + "Optional shell command run after downloading a new wallpaper to notify the desktop environment. If null, no reload command is run."; + }; +} diff --git a/systems/aarch64-linux/macbook-pro-nixos/default.nix b/systems/aarch64-linux/macbook-pro-nixos/default.nix index 7598623..9f95356 100755 --- a/systems/aarch64-linux/macbook-pro-nixos/default.nix +++ b/systems/aarch64-linux/macbook-pro-nixos/default.nix @@ -65,7 +65,10 @@ enable = false; wallpaperSource = "bing"; }; - plasma.enable = lib.mkForce true; + plasma = { + enable = lib.mkForce true; + wallpaper.enable = true; + }; }; hardware = { battery = {