First commit
This commit is contained in:
@@ -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" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user