First commit

This commit is contained in:
2026-02-22 17:28:02 +01:00
parent 7a70268785
commit 6bacf1878e
9011 changed files with 114470 additions and 0 deletions
@@ -0,0 +1,226 @@
{ config, pkgs, lib, ... }:
let
cfg = config.dataPro.wallpaper; # custom namespace
# Where we keep a runtime-editable config for the user.
runtimeConfDir = "${config.xdg.configHome}/wallpaper";
runtimeConfPath = "${runtimeConfDir}/wallpaper.conf";
rotateScript = pkgs.writeShellScript "wallpaper-rotate" ''
set -euo pipefail
export PATH=${lib.makeBinPath [
pkgs.coreutils
pkgs.findutils
pkgs.gnugrep
pkgs.gawk
pkgs.util-linux
pkgs.swww
]}
# Defaults (can be overridden by wallpaper.conf)
SOURCE_DIR="${cfg.sourceDir}"
TARGET_DIR="${cfg.targetDir}"
ROTATION_DIR="${cfg.rotationDir}"
TRANSITION_TYPE="fade"
TRANSITION_DURATION="2.5"
TRANSITION_FPS="60"
PICK_MODE="random" # random | sequential
LAST_FILE="${config.xdg.stateHome}/wallpaper/last.txt"
# Load user config if present (KEY=VALUE lines; '#' comments allowed)
if [ -f "${runtimeConfPath}" ]; then
# shellcheck disable=SC1090
. "${runtimeConfPath}"
fi
mkdir -p "$TARGET_DIR" "${config.xdg.stateHome}/wallpaper"
# Ensure swww-daemon is running
if ! pgrep -x swww-daemon >/dev/null 2>&1; then
swww-daemon >/dev/null 2>&1 &
sleep 0.3
fi
# Pick image
if [ ! -d "$ROTATION_DIR" ]; then
echo "Rotation directory does not exist: $ROTATION_DIR" >&2
exit 0
fi
# Build list once per run
mapfile -d '' -t imgs < <(
find "$ROTATION_DIR" -type f \
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.webp' \) \
-print0
)
if [ "${#imgs[@]}" -eq 0 ]; then
echo "No images found in: $ROTATION_DIR" >&2
exit 0
fi
img=""
if [ "$PICK_MODE" = "sequential" ]; then
last=""
if [ -f "$LAST_FILE" ]; then
last="$(cat "$LAST_FILE" || true)"
fi
# Sort for stable order
IFS=$'\n' sorted=($(printf '%s\n' "${imgs[@]}" | sort))
unset IFS
# Find next after last
next=""
found_last=0
for f in "${sorted[@]}"; do
if [ "$found_last" -eq 1 ]; then
next="$f"
break
fi
if [ "$f" = "$last" ]; then
found_last=1
fi
done
if [ -z "$next" ]; then
next="${sorted[0]}"
fi
img="$next"
printf '%s' "$img" > "$LAST_FILE"
else
# random
img="$(printf '%s\0' "${imgs[@]}" | shuf -z -n 1 | tr -d '\0')"
fi
# Smooth transition wallpaper set
swww img "$img" \
--transition-type "$TRANSITION_TYPE" \
--transition-duration "$TRANSITION_DURATION" \
--transition-fps "$TRANSITION_FPS"
'';
in
{
options.dataPro.wallpaper = {
enable = lib.mkEnableOption "Hourly wallpaper rotation with swww (Hyprland/Wayland)";
# You asked to make this easy to change:
sourceDir = lib.mkOption {
type = lib.types.str;
default = "${config.home.homeDirectory}/nixos/files/wallpaper/picture";
description = "Folder containing wallpapers to rotate (source of truth).";
};
targetDir = lib.mkOption {
type = lib.types.str;
default = "${config.home.homeDirectory}/wallpaper";
description = "Folder in the user's home where wallpapers are copied to.";
};
rotationDir = lib.mkOption {
type = lib.types.str;
default = "${config.home.homeDirectory}/wallpaper/picture";
description = "Folder used by the rotator to pick wallpapers from (usually inside targetDir).";
};
};
config = lib.mkIf cfg.enable {
home.packages = [
pkgs.swww
pkgs.coreutils
pkgs.findutils
pkgs.gnugrep
pkgs.gawk
pkgs.util-linux
];
# Copy wallpapers from sourceDir into rotationDir (real copy) at activation.
home.activation.wallpaperCopy = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
set -euo pipefail
mkdir -p "${cfg.targetDir}" "${cfg.rotationDir}"
if [ -d "${cfg.sourceDir}" ]; then
# Copy source into rotationDir (contents only).
cp -a "${cfg.sourceDir}/." "${cfg.rotationDir}/"
fi
'';
# Install a runtime-editable config into ~/.config/wallpaper/wallpaper.conf
# First-time copy from repo if present; then never overwrite if user edited it.
home.activation.wallpaperConf = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
set -euo pipefail
mkdir -p "${runtimeConfDir}"
if [ ! -f "${runtimeConfPath}" ]; then
if [ -f "${config.home.homeDirectory}/nixos/files/conf/wallpaper/wallpaper.conf" ]; then
cp -a "${config.home.homeDirectory}/nixos/files/conf/wallpaper/wallpaper.conf" "${runtimeConfPath}"
else
cat > "${runtimeConfPath}" <<'EOF'
# wallpaper.conf — runtime settings for the wallpaper rotator (swww)
# Lines are KEY=VALUE. '#' starts a comment.
# Folder to copy wallpapers from (source of truth)
#SOURCE_DIR="$HOME/nixos/files/wallpaper/picture"
# Where wallpapers are copied to (a folder in your home)
#TARGET_DIR="$HOME/wallpaper"
# Folder used for rotation (where images are selected from)
#ROTATION_DIR="$HOME/wallpaper/picture"
# random | sequential
#PICK_MODE="random"
# swww transition settings
#TRANSITION_TYPE="fade"
#TRANSITION_DURATION="2.5"
#TRANSITION_FPS="60"
EOF
fi
fi
'';
# Start swww daemon on graphical session start
systemd.user.services.swww-daemon = {
Unit = {
Description = "swww wallpaper daemon";
After = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
};
Service = {
ExecStart = "${pkgs.swww}/bin/swww-daemon";
Restart = "on-failure";
};
Install = {
WantedBy = [ "graphical-session.target" ];
};
};
# Rotate wallpaper hourly
systemd.user.services.wallpaper-rotate = {
Unit = {
Description = "Rotate wallpaper (hourly)";
After = [ "swww-daemon.service" ];
};
Service = {
Type = "oneshot";
ExecStart = "${rotateScript}";
};
};
systemd.user.timers.wallpaper-rotate = {
Unit = {
Description = "Hourly wallpaper rotation timer";
};
Timer = {
OnBootSec = "2m";
OnUnitActiveSec = "1h";
Unit = "wallpaper-rotate.service";
};
Install = {
WantedBy = [ "timers.target" ];
};
};
};
}