summaryrefslogtreecommitdiff
path: root/.config/niri/theme-switcher.sh
blob: 6d1f5488c3edfeeefb12832bea7da534e3b40a13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/bin/bash

# Day/night theme switcher + wallpaper/color applier.
# Two wallpapers: day.jpg (9:00-18:00) and night.jpg (18:00-9:00).
#
# Usage:
#   ./theme-switcher.sh            one-shot: apply based on current time, then exit
#   ./theme-switcher.sh day|light  force light theme, then exit
#   ./theme-switcher.sh night|dark force dark theme, then exit
#   ./theme-switcher.sh --daemon   continuous time-based loop (used at login)

WALLPAPERS="$HOME/Pictures/wallpapers"
STATE_FILE="/tmp/current_theme_state"
WALLPAPER_STATE_FILE="/tmp/current_wallpaper_state"
BACKDROP_STATE_FILE="/tmp/current_backdrop_state"
PID_FILE="/tmp/theme-switcher.daemon.pid"
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"
}

# Resolve TARGET_STATE / MODE / WALLPAPER. Optional $1 forces day|night.
resolve_target() {
  local force="${1:-}"
  if [ "$force" = "day" ] || [ "$force" = "light" ]; then
    TARGET_STATE="light"
    MODE="light"
    WALLPAPER="$WALLPAPERS/day.jpg"
  elif [ "$force" = "night" ] || [ "$force" = "dark" ]; then
    TARGET_STATE="dark"
    MODE="dark"
    WALLPAPER="$WALLPAPERS/night.jpg"
  else
    local HOUR
    HOUR=$(date +%H)
    HOUR=$((10#$HOUR))
    if [ "$HOUR" -ge 9 ] && [ "$HOUR" -lt 18 ]; then
      TARGET_STATE="light"
      MODE="light"
      WALLPAPER="$WALLPAPERS/day.jpg"
    else
      TARGET_STATE="dark"
      MODE="dark"
      WALLPAPER="$WALLPAPERS/night.jpg"
    fi
  fi
}

# 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)
  # Already in the correct theme: don't re-run wallust/matugen every loop tick.
  # Still self-heal a drifted backdrop below, then bail out.
  if [ "$CURRENT_THEME" = "$TARGET_STATE" ]; then
    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
    return 0
  fi
  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

  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/waybar/.config/waybar/theme.css"

    ln -sf \
      "settings-${TARGET_STATE}.ini" \
      "$HOME/dotfiles-gentoo/gtk/.config/gtk-3.0/settings.ini"

    echo "$TARGET_STATE" >"$STATE_FILE"
    echo "$WALLPAPER" >"$WALLPAPER_STATE_FILE"
    log "switched to $TARGET_STATE ($WALLPAPER)"
    return 0
  else
    log "FAILED to apply $TARGET_STATE ($WALLPAPER)"
    return 1
  fi
}

daemon_loop() {
  # Refuse to run a second daemon instance (e.g. manual run while one is alive).
  if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE" 2>/dev/null)" 2>/dev/null; then
    log "daemon already running (pid $(cat "$PID_FILE")), exiting"
    exit 0
  fi
  echo $$ >"$PID_FILE"

  while true; do
    resolve_target
    apply_target || true # failure is retried on the next loop, state is left untouched
    sleep 60
  done
}

case "${1:-}" in
--daemon | -d) daemon_loop ;;
"" | day | light | night | dark)
  resolve_target "${1:-}"
  apply_target
  exit $?
  ;;
-h | --help)
  echo "usage: $0 [day|night|--daemon]" >&2
  exit 0
  ;;
*)
  echo "usage: $0 [day|night|--daemon]" >&2
  exit 1
  ;;
esac