Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions bin/omarchy-menu
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ show_font_menu() {
}

show_setup_menu() {
local options=" Audio\n Wifi\n󰂯 Bluetooth\n󱐋 Power Profile\n System Sleep\n󰍹 Monitors"
local options=" Audio\n Wifi\n󰂯 Bluetooth\n󱐋 Power Profile\n󰸌 Theme Schedule\n System Sleep\n󰍹 Monitors"
[[ -f ~/.config/hypr/bindings.lua ]] && options="$options\n Keybindings"
[[ -f ~/.config/hypr/input.lua ]] && options="$options\n Input"
options="$options\n Defaults\n󰱔 DNS\n Security\n Config"
Expand All @@ -352,6 +352,7 @@ show_setup_menu() {
*Wifi*) omarchy-launch-wifi ;;
*Bluetooth*) omarchy-launch-bluetooth ;;
*Power*) show_setup_power_menu ;;
*"Theme Schedule"*) show_setup_theme_schedule_menu ;;
*System*) show_setup_system_menu ;;
*Monitors*) open_in_editor "$(hypr_config_file monitors)" ;;
*Keybindings*) open_in_editor "$(hypr_config_file bindings)" ;;
Expand All @@ -364,13 +365,53 @@ show_setup_menu() {
esac
}

show_setup_theme_schedule_menu() {
local config_file="$HOME/.config/omarchy/theme-schedule.conf"

# Default values
local MODE="time" LIGHT_THEME="" DARK_THEME="" LIGHT_TIME="07:00" DARK_TIME="19:00"

if [[ -f "$config_file" ]]; then
source <(grep -E '^(MODE|LIGHT_TIME|DARK_TIME|LIGHT_THEME|DARK_THEME)=' "$config_file")
fi

local options="󰔎 Mode: ${MODE^}\n󰸌 Set Day Theme\n󰸌 Set Night Theme"
[[ "$MODE" == "time" ]] && options="$options\n󰔚 Set Day Start ($LIGHT_TIME)\n󰔚 Set Night Start ($DARK_TIME)"
options="$options\n Check & Apply Now"

case $(menu "Theme Schedule" "$options") in
*Mode*)
local new_mode="time"; [[ "$MODE" == "time" ]] && new_mode="auto"
omarchy-theme-schedule --mode "$new_mode" && show_setup_theme_schedule_menu ;;
*"Day Theme"*)
local theme; theme=$(menu "Select Day Theme" "$(omarchy-theme-list)" "" "$LIGHT_THEME")
[[ -n $theme && $theme != "CNCLD" ]] && omarchy-theme-schedule --light "$theme"
show_setup_theme_schedule_menu ;;
*"Night Theme"*)
local theme; theme=$(menu "Select Night Theme" "$(omarchy-theme-list)" "" "$DARK_THEME")
[[ -n $theme && $theme != "CNCLD" ]] && omarchy-theme-schedule --dark "$theme"
show_setup_theme_schedule_menu ;;
*"Day Start"*)
local time; time=$(omarchy-menu-input "Day Start (HH:MM)" "$LIGHT_TIME")
[[ $time =~ ^([01][0-9]|2[0-3]):[0-5][0-9]$ ]] && omarchy-theme-schedule --light-time "$time"
show_setup_theme_schedule_menu ;;
*"Night Start"*)
local time; time=$(omarchy-menu-input "Night Start (HH:MM)" "$DARK_TIME")
[[ $time =~ ^([01][0-9]|2[0-3]):[0-5][0-9]$ ]] && omarchy-theme-schedule --dark-time "$time"
show_setup_theme_schedule_menu ;;
*"Apply Now"*)
omarchy-theme-schedule --check && show_setup_theme_schedule_menu ;;
*) show_setup_menu ;;
esac
}

show_setup_power_menu() {
profile=$(menu "Power Profile" "$(omarchy-powerprofiles-list)" "" "$(powerprofilesctl get)")
local current; current=$(powerprofilesctl get)
local profile; profile=$(menu "Power Profile" "$(omarchy-powerprofiles-list)" "" "$current")

if [[ $profile == "CNCLD" || -z $profile ]]; then
back_to show_setup_menu
else
if [[ $profile != "CNCLD" && -n $profile && "$profile" != "$current" ]]; then
powerprofilesctl set "$profile"
omarchy-notification-send -g 󱐋 "Power Profile" "Switched to $profile"
fi
}

Expand Down
204 changes: 204 additions & 0 deletions bin/omarchy-theme-schedule
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#!/bin/bash

# omarchy:summary=Schedule dark and light themes based on time or sunrise/sunset
# omarchy:args=[--light <theme>] [--dark <theme>] [--mode <time|auto>] [--light-time <HH:MM>] [--dark-time <HH:MM>] [--check]
# omarchy:examples=omarchy theme schedule --mode auto --light "Catppuccin Latte" --dark "Tokyo Night"

set -o pipefail

# --- Infrastructure ---
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/omarchy"
CONFIG_FILE="$CONFIG_DIR/theme-schedule.conf"
LOG_FILE="$CONFIG_DIR/theme-schedule.log"
LOCK_DIR="/tmp/omarchy-theme-schedule.lock.dir"

log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

# --- Atomic Locking ---
if ! mkdir "$LOCK_DIR" 2>/dev/null; then
if [[ $(find "$LOCK_DIR" -maxdepth 0 -mmin +30 2>/dev/null) ]]; then
rmdir "$LOCK_DIR"
mkdir "$LOCK_DIR" || exit 0
else
exit 0
fi
fi
trap 'rmdir "$LOCK_DIR" 2>/dev/null' EXIT

# --- Helpers ---
show_help() {
cat <<EOF
Usage: omarchy theme schedule [options]

Automate theme switching based on time or local sunrise/sunset.

Options:
--light <theme> Theme to use for daytime
--dark <theme> Theme to use for nighttime
--mode <time|auto> Switching mode: 'time' (fixed) or 'auto' (astronomy)
--light-time <HH:MM> Time to switch to light theme (default: 07:00)
--dark-time <HH:MM> Time to switch to dark theme (default: 19:00)
--check Evaluate conditions and apply the correct theme
--help Show this help message

Examples:
omarchy theme schedule --mode auto --light "Catppuccin Latte" --dark "Tokyo Night"
omarchy theme schedule --mode time --light-time 08:30 --dark-time 20:15
EOF
}

validate_theme() {
local theme="$1"
if ! omarchy-theme-list | grep -qFx "$theme"; then
echo "Error: Theme '$theme' is not a valid Omarchy theme."
return 1
fi
return 0
}

load_config() {
MODE="time"
LIGHT_TIME="07:00"
DARK_TIME="19:00"
LIGHT_THEME=""
DARK_THEME=""

if [[ -f "$CONFIG_FILE" ]]; then
# shellcheck disable=SC1090
source <(grep -E '^(MODE|LIGHT_TIME|DARK_TIME|LIGHT_THEME|DARK_THEME)=' "$CONFIG_FILE")
fi
}

save_config() {
mkdir -p "$CONFIG_DIR"
cat > "$CONFIG_FILE" <<EOL
MODE="$MODE"
LIGHT_TIME="$LIGHT_TIME"
DARK_TIME="$DARK_TIME"
LIGHT_THEME="$LIGHT_THEME"
DARK_THEME="$DARK_THEME"
EOL
}

setup_systemd() {
# Enable the timer. The files themselves are managed by Omarchy installation/refresh.
systemctl --user enable --now omarchy-theme-schedule.timer >/dev/null 2>&1
log "Systemd units synchronized."
}

notify() {
omarchy-notification-send -g "󰸌" "Theme Schedule" "$1"
}

check_and_apply() {
load_config

if [[ -z "$LIGHT_THEME" || -z "$DARK_THEME" ]]; then
return
fi

local target_mode="light"

if [[ "$MODE" == "auto" ]]; then
local data
data=$(curl -fsS --max-time 10 "https://wttr.in?format=j1" 2>/dev/null | jq -er '[.weather[0].astronomy[0].sunrise, .weather[0].astronomy[0].sunset] | select(all(. != null and . != "")) | @tsv' 2>/dev/null)

if [[ $? -eq 0 ]]; then
local sunrise sunset
IFS=$'\t' read -r sunrise sunset <<< "$data"

local now_epoch sunrise_epoch sunset_epoch
now_epoch=$(date +%s)
sunrise_epoch=$(date -d "today $sunrise" +%s 2>/dev/null || echo 0)
sunset_epoch=$(date -d "today $sunset" +%s 2>/dev/null || echo 0)

if (( sunrise_epoch > 0 && sunset_epoch > 0 )); then
if (( now_epoch < sunrise_epoch || now_epoch >= sunset_epoch )); then
target_mode="dark"
else
target_mode="light"
fi
else
MODE="time"
fi
else
MODE="time"
fi
fi

if [[ "$MODE" == "time" ]]; then
local current_time
current_time=$(date +%H:%M)
if [[ "$current_time" < "$LIGHT_TIME" ]] || [[ "$current_time" > "$DARK_TIME" ]] || [[ "$current_time" == "$DARK_TIME" ]]; then
target_mode="dark"
else
target_mode="light"
fi
fi

local target_theme
[[ "$target_mode" == "light" ]] && target_theme="$LIGHT_THEME" || target_theme="$DARK_THEME"

local current_theme
current_theme=$(omarchy-theme-current)

if [[ "$current_theme" != "$target_theme" ]]; then
log "Applying theme change: $current_theme -> $target_theme ($target_mode mode)"
omarchy-theme-set "$target_theme"
notify "Switched to $target_theme ($target_mode mode)"
else
# Redundancy Check: Ensure only one waybar is running
if [[ $(pgrep -x waybar | wc -l) -gt 1 ]]; then
log "Cleaning up duplicate Waybar instances."
omarchy-restart-waybar
fi
fi
}

# --- Entry Point ---
load_config

if [[ $# -eq 0 ]]; then
show_help
exit 0
fi

NEED_SAVE=false
MSG=""

while [[ $# -gt 0 ]]; do
case $1 in
--light)
validate_theme "$2" || exit 1
LIGHT_THEME="$2"; NEED_SAVE=true
MSG="${MSG:+$MSG\n}Day theme: $2"; shift 2 ;;
--dark)
validate_theme "$2" || exit 1
DARK_THEME="$2"; NEED_SAVE=true
MSG="${MSG:+$MSG\n}Night theme: $2"; shift 2 ;;
--mode)
MODE="$2"; NEED_SAVE=true
MSG="${MSG:+$MSG\n}Mode: ${2^}"; shift 2 ;;
--light-time)
LIGHT_TIME="$2"; NEED_SAVE=true
MSG="${MSG:+$MSG\n}Day start: $2"; shift 2 ;;
--dark-time)
DARK_TIME="$2"; NEED_SAVE=true
MSG="${MSG:+$MSG\n}Night start: $2"; shift 2 ;;
--check)
check_and_apply; exit 0 ;;
--help)
show_help; exit 0 ;;
*)
echo "Unknown option: $1"; show_help; exit 1 ;;
esac
done

if [[ "$NEED_SAVE" == "true" ]]; then
save_config
setup_systemd
[[ -n "$MSG" ]] && notify "Schedule Updated:\n$MSG"
check_and_apply
fi
10 changes: 10 additions & 0 deletions config/systemd/user/omarchy-theme-schedule.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Unit]
Description=Omarchy Theme Scheduler
After=graphical-session.target

[Service]
Type=oneshot
ExecStartPre=/usr/bin/systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE
ExecStart=%h/.local/share/omarchy/bin/omarchy-theme-schedule --check
StandardOutput=append:%h/.config/omarchy/theme-schedule.log
StandardError=append:%h/.config/omarchy/theme-schedule.log
9 changes: 9 additions & 0 deletions config/systemd/user/omarchy-theme-schedule.timer
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
Description=Omarchy Theme Scheduler Timer

[Timer]
OnCalendar=*:0/15
Persistent=true

[Install]
WantedBy=timers.target
6 changes: 6 additions & 0 deletions migrations/1778733053.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

# Enable the theme scheduler timer if it was recently added
if [[ -f "$HOME/.config/systemd/user/omarchy-theme-schedule.timer" ]]; then
systemctl --user enable --now omarchy-theme-schedule.timer || true
fi