Timed OS light/dark theme switching

tl;dr: A GitHub gist with commands walk-through is available here.

What

The ability to adjust themes, and in particular the dark mode, have been one of the most trendy tech features of 2019/2020. Many sites and apps now allow to to flip between the “normal” and the “dark mode”.

Why

Although I don’t belong to the die hard zealots one can find on the internet, I do appreciate this feature when in dark environment as I’m rather light sensitive and most devices have the lowest brightness on too-high for me. It is a nice surprise that Ubuntu 20.04 came with the global theme and a couple default ones. This let’s me to decide when it’s dark and then switch to the dark mode. Since many pages, e.g. stackoverflow.com or duckduckgo.com, now detect OS’s theme mode they will also be in switch into the mode. Neat. So, when the light goes down, my dark mode goes on, and we’re all happy.

But obviously the night comes everyday so why should I sent those 3 seconds of manual labour when I can make it automatic?

How

I won’t into too much details but basically the proposed solution is using a service manager systemd and more specifically its systemctl command. There are two “services”, one for each theme flip, and they are run daily at specific time.

For the servicd to automagically detect your services and timers they can be be placed in ~/.config/systemd/user. It’s likely that there isn’t such directory so create it. The code also expects that there is a directory ~/.scripts where some random utility scripts are placed.

The walkthrough code is below. Please note that none of the files are expected to be where they are so you have to create them and fill with the content that the cat command returned. Also, the script changes default terminal profile and it’s expectating that there are two called “Dark” and “Light” for day and night, respectively.

user@host:~/$ mkdir -p ~/.config/systemd/user
user@host:~/$ mkdir -p ~/.scripts

user@host:~/$ cat ~/.config/systemd/user/dark.service  # Create this file
[Unit]
Description=Automatically change the "Window Theme" to "light" in the morning.

[Service]
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
ExecStart=~/.scripts/profile_changer.sh light

user@host:~/$ cat .config/systemd/user/light.timer
[Unit]
Description=Automatically change the "Window Theme" to "light" in the morning.

[Timer]
OnCalendar=*-*-* 06:00:00
Persistent=true

[Install]
WantedBy=default.target

user@host:~/$ cat .config/systemd/userdark.service  # Create this file
[Unit]
Description=Automatically change the "Window Theme" to "dark" in the evening.

[Service]
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
ExecStart=~/.scripts/profile_changer.sh dark

user@host:~/$ cat .config/systemd/user/dark.timer  # Create this file
[Unit]
Description=Automatically change the "Window Theme" to "dark" in the evening.

[Timer]
OnCalendar=*-*-* 19:00:00
Persistent=true

[Install]
WantedBy=default.target

user@host:~/$ cat .scripts/profile_changer.sh  # Create this file
#!/bin/bash

get_uuid() {
  # Print the UUID linked to the profile name sent in parameter
  local profile_name=$1
  profiles=($(gsettings get org.gnome.Terminal.ProfilesList list | tr -d "[]\',"))
  for i in ${!profiles[*]}
    do
      local uuid="$(dconf read /org/gnome/terminal/legacy/profiles:/:${profiles[i]}/visible-name)"
      if [[ "${uuid,,}" = "'${profile_name,,}'" ]]
        then echo "${profiles[i]}"
        return 0
      fi
  done
  echo "$profile_name"
}

if [ $1 == "dark" ]; then
  THEME='Yaru-dark'
elif [ $1 == "light" ]; then
  THEME='Yaru-light'
fi
UUID=$(get_uuid $1)

/usr/bin/gsettings set org.gnome.desktop.interface gtk-theme $THEME
/usr/bin/gsettings set org.gnome.Terminal.ProfilesList default $UUID

user@host:~$ chmod a+x .scripts/profile_changer.sh  # Make script executable
user@host:~$ systemctl --user daemon-reload
user@host:~$ systemctl --user enable dark.timer light.timer
user@host:~$ systemctl --user start dark.timer light.timer

The last three commands will refresh the service daemon to and make it look for any file changes, enable timer services to be run in the background on startup and start them now.

That’s less work than expected initially. As most of the time, most of the work came from the StackExchange, from the AskUbuntu thread. Lucky that most of the time there’s someone with a similar question and someone with good answer.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s