#!/bin/bash # Manual theme switcher + wallpaper/color applier. # No time-based switching: you pick the wallpaper and mode explicitly. # # Usage: # ./theme-switcher.sh apply in light/dark mode, remember it # ./theme-switcher.sh --last apply the last manually-set wallpaper+mode # ./theme-switcher.sh -h | --help show this help WALLPAPERS="$HOME/Pictures/wallpapers" STATE_FILE="/tmp/current_theme_state" WALLPAPER_STATE_FILE="/tmp/current_wallpaper_state" BACKDROP_STATE_FILE="/tmp/current_backdrop_state" LAST_FILE="${XDG_STATE_HOME:-$HOME/.local/state}/theme-switcher/last" LOG="/tmp/theme-switcher.log" SCRIPT_DIR="$(cd "$(dirname "$(realpath "$0")")" && pwd)" SET_BACKDROP="$SCRIPT_DIR/set-backdrop.sh" log() { printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >>"$LOG" } # Persist the last manually-chosen wallpaper + mode so --last survives reboots. save_last() { mkdir -p "$(dirname "$LAST_FILE")" printf '%s\n%s\n' "$WALLPAPER" "$MODE" >"$LAST_FILE" } # Load the last chosen wallpaper + mode. Falls back to the old default so a # fresh boot (nothing saved yet) never lands on a blank wallpaper. load_last() { if [ -f "$LAST_FILE" ]; then WALLPAPER=$(sed -n '1p' "$LAST_FILE") MODE=$(sed -n '2p' "$LAST_FILE") case "$MODE" in light) TARGET_STATE="light" ;; *) TARGET_STATE="dark"; MODE="dark" ;; esac else WALLPAPER="$WALLPAPERS/night.jpg" TARGET_STATE="dark" MODE="dark" fi } # Resolve TARGET_STATE / MODE from an explicit mode argument. resolve_explicit() { local mode="$1" case "$mode" in day | light) TARGET_STATE="light"; MODE="light" ;; night | dark) TARGET_STATE="dark"; MODE="dark" ;; *) echo "mode must be day|night (got: $mode)" >&2 exit 1 ;; esac } # Apply the resolved target once. Returns 0 on success. apply_target() { if [ ! -f "$WALLPAPER" ]; then log "wallpaper missing: $WALLPAPER" return 1 fi local CURRENT_THEME CURRENT_WALLPAPER EXPECTED_BACKDROP ACTUAL_BACKDROP CURRENT_THEME=$(cat "$STATE_FILE" 2>/dev/null || true) CURRENT_WALLPAPER=$(cat "$WALLPAPER_STATE_FILE" 2>/dev/null || true) # Self-heal the Overview backdrop if it drifted from the expected image. EXPECTED_BACKDROP=$(cat "$BACKDROP_STATE_FILE" 2>/dev/null || true) ACTUAL_BACKDROP=$(awww query -n backdrop -j 2>/dev/null | jq -r '.["backdrop"][0].displaying.image // empty') if [ -n "$EXPECTED_BACKDROP" ] && [ "$ACTUAL_BACKDROP" != "$EXPECTED_BACKDROP" ]; then "$SET_BACKDROP" "$WALLPAPER" fi # Already in this exact theme AND wallpaper: skip the heavy color work. if [ "$CURRENT_THEME" = "$TARGET_STATE" ] && [ "$CURRENT_WALLPAPER" = "$WALLPAPER" ]; then return 0 fi log "switching to $TARGET_STATE ($WALLPAPER)" if sh "$SCRIPT_DIR/apply-colors.sh" "$WALLPAPER" "$MODE"; then if [ "$CURRENT_THEME" != "$TARGET_STATE" ]; then darkman set "$TARGET_STATE" fi ln -sf \ "theme-${TARGET_STATE}.css" \ "$HOME/dotfiles-gentoo/.config/waybar/theme.css" ln -sf \ "settings-${TARGET_STATE}.ini" \ "$HOME/dotfiles-gentoo/.config/gtk-3.0/settings.ini" echo "$TARGET_STATE" >"$STATE_FILE" echo "$WALLPAPER" >"$WALLPAPER_STATE_FILE" save_last log "switched to $TARGET_STATE ($WALLPAPER)" return 0 else log "FAILED to apply $TARGET_STATE ($WALLPAPER)" return 1 fi } usage() { cat >&2 < | --last apply in light/dark mode and remember it --last apply the last manually-set wallpaper + mode EOF } case "${1:-}" in --last) load_last apply_target exit $? ;; -h | --help) usage exit 0 ;; "") usage exit 1 ;; *) WALLPAPER="${1:-}" MODEARG="${2:-}" if [ -z "$MODEARG" ]; then echo "missing mode (day|night)" >&2 usage exit 1 fi resolve_explicit "$MODEARG" apply_target exit $? ;; esac