summaryrefslogtreecommitdiff
path: root/.config/niri/theme-switcher.sh
blob: 01786d8461990bdf68b83de7fde150ee212645c6 (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
136
137
138
139
140
141
142
143
#!/bin/bash

# Manual theme switcher + wallpaper/color applier.
# No time-based switching: you pick the wallpaper and mode explicitly.
#
# Usage:
#   ./theme-switcher.sh <image> <day|night>   apply <image> 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 <<EOF
usage: $0 <image> <day|night> | --last
  <image> <day|night>   apply <image> 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