Skip to content

Instantly share code, notes, and snippets.

@uriel1998
Forked from ImranR98/eOSUDS.sh
Last active Oct 12, 2021
Embed
What would you like to do?
elementaryOS 6 has great dark themes, but they only apply to "curated" appcenter apps. This script forces the system theme to work with regular Debian packages as well as non-curated Flatpak apps. It also optionally changes the wallpaper based on the theme. It also supports changing themes for the Mailspring email app (both .deb and Snap versions).
#!/usr/bin/bash
# =======================================
# eOS-Universal-Dark-Style
# =======================================
# elementaryOS 6 has great dark themes, but they only apply to "curated" appcenter apps
# This script forces the system theme to work with regular Debian packages as well as non-curated Flatpak apps
# It also optionally changes the wallpaper based on the theme
# It also supports changing themes for the Mailspring email app (both .deb and Snap versions)
# =======================================
# Instructions
# =======================================
# 1. Save this script and make it executable
# 2. Change the configuration variables below as needed
# 3. Use a cron job to run the script automatically on a desired schedule; you can learn about cron by running `man crontab` in a terminal
# Note that system updates can reset the forced Flatpak theming, so running the script frequently (every few minutes) is recommended
# =======================================
# Configuration
# =======================================
#LIGHT_THEME_WALLPAPER='/usr/share/backgrounds/odin.jpg' # Leave empty to disable wallpaper switching on light theme
#DARK_THEME_WALLPAPER='/usr/share/backgrounds/odin-dark.jpg' # Leave empty to disable wallpaper switching on dark theme
#MAILSPRING_LIGHT_THEME='ui-light' # Leave empty to disable Mailspring theme switching on light theme
#MAILSPRING_DARK_THEME='ui-dark' # Leave empty to disable Mailspring theme switching on dark theme
SHOW_DEBUG_MESSAGES=0 # If debug logs should be printed, set to 1
# =======================================
# Script functions
# =======================================
# Echoes provided string with a date prefix. If $2 is 1, redirects to stderr with ERROR prefix. If $3 is 1, echoes a crash message to stderr and exits with code 1
# If $4 is 1, the message is treated as a debug log (only shown if the relevant configuration variable above is set)
log() {
if [ "$2" == 1 ]; then
echo -e "ERROR: $(date): $1" >&2
elif [ "$4" == 1 ]; then
if [ "$SHOW_DEBUG_MESSAGES" == 1 ]; then
echo -e "DEBUG: $(date): $1"
fi
else
echo -e "MESSG: $(date): $1"
fi
if [ "$3" == 1 ]; then
echo -e "CRASHED." >&2
exit 1
fi
}
# Echoes 1 if the system dark style is set, 0 otherwise
getSystemDarkStylePref() {
#[ "$(gsettings get org.freedesktop prefers-color-scheme)" = "'dark'" ] && echo 1 || echo 0
echo 1
}
# Changes the universal GTK dark theme preference based on the provided argument (if they are different)
changeGTKUniversalDarkPrefIfNeeded() {
# Ensure the provided argument is valid before making the change
echo "$1 HI"
[ "$1" == 0 ] || [ "$1" == 1 ] || log "GTK universal dark preference can only be set to 0 or 1" 1 1
# The location of the universal GTK dark preference config file
GTK_UNIVERSAL_PREF_FILE=~/.config/gtk-3.0/settings.ini
# Ensure the file exists (if not, create it)
if [ ! -f "$GTK_UNIVERSAL_PREF_FILE" ]; then
echo -e '[Settings]\ngtk-application-prefer-dark-theme=1\n' > "$GTK_UNIVERSAL_PREF_FILE"
fi
# Grab the pref
GTK_UNIVERSAL_PREF_IS_DARK="$(cat "$GTK_UNIVERSAL_PREF_FILE" | grep -o [0-1])"
# If needed, make the change
if [ "$GTK_UNIVERSAL_PREF_IS_DARK" != "$1" ]; then
sed -i "s/gtk-application-prefer-dark-theme=.*/gtk-application-prefer-dark-theme=$1/" "$GTK_UNIVERSAL_PREF_FILE"
log "GTK universal dark preference has been set to $1"
else
log "GTK universal dark preference is already $1, no changes made" 0 0 1
fi
}
# Changes the wallpaper to the one given in the argument (if not already set)
# If the argument is empty, does nothing (does NOT throw an error)
changeWallpaperIfNeeded() {
if [ ! -z "$1" ]; then
CURRENT_WALLPAPER="$(gsettings get org.gnome.desktop.background picture-uri | head -c -2 | tail -c +9)"
if [ "$CURRENT_WALLPAPER" != "$1" ]; then
# This if statement allows the wallpaper change to work even when running from a cron job
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
PID=$(pgrep gnome-session)
export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$PID/environ | tr '\0' '\n' | cut -d= -f2-)
fi
gsettings set org.gnome.desktop.background picture-uri file://"$1"
log "Wallpaper has been set to $1"
else
log "Wallpaper is already $1, no changes made" 0 0 1
fi
else
log "Wallpaper argument is empty, no changes made" 0 0 1
fi
}
# Changes the Mailspring theme to the provided string if a Mailspring config can be found (indicating it is installed)
# If not installed or if no theme provided, does nothing (does NOT throw an error)
# Warning: This abruptly kills the Mailspring process and restarts it in the background
changeMailSpringThemeIfNeeded() {
if [ ! -z "$1" ]; then
MAILSPRING_CONFIG_FILE=~/.config/Mailspring/config.json
if [ ! -f "$MAILSPRING_CONFIG_FILE" ]; then MAILSPRING_CONFIG_FILE=~/snap/mailspring/common/config.json; fi
if [ -f "$MAILSPRING_CONFIG_FILE" ] && [ ! -z "$1" ]; then
CURRENT_MAILSPRING_THEME="$(cat "$MAILSPRING_CONFIG_FILE" | grep \"theme\": | tr -d ' ' | tail -c +10 | head -c -3)"
if [ "$CURRENT_MAILSPRING_THEME" != "$1" ]; then
sed -i "s/\"theme\":.*/\"theme\": \"$1\",/g" "$MAILSPRING_CONFIG_FILE"
log "Mailspring theme has been set to $1"
pkill -f mailspring > /dev/null 2>&1
log "Mailspring process has been killed"
mailspring -b </dev/null &>/dev/null &
log "Mailspring process has been started in background"
else
log "Mailspring theme is already $1, no changes made" 0 0 1
fi
else
log "Mailspring not installed, no changes made" 0 0 1
fi
else
log "Mailspring theme argument is empty, no changes made" 0 0 1
fi
}
# First, installs the current system theme into the Flatpak runtimes used by all non-curated (non-appcenter) apps (if not already installed)
# If the current theme is an elementary theme (io.elementary.stylesheet.*) and if the $1 argument is 1, it makes these changes before installing the theme:
# - Renames it by adding a -dark suffix
# - Modifies it so the default stylesheet is dark themed; this is needed as elementary themes do not have traditional separate dark variants
# Then, forces all the apps to use the current theme by adding an environment variable override (if not already set)
changeNonElementaryFlatpakThemesIfNeeded() {
# The location of Flatpak runtimes
FLATPAK_RUNTIME_DIR=~/.local/share/flatpak/runtime
# Where themes are stored in a Flatpak runtime
RUNTIME_THEME_SUBDIR='active/files/share/themes'
# Grab the current system theme
THEME="$(gsettings get org.gnome.desktop.interface gtk-theme | head -c -2 | tail -c +2)"
# Set the variable that indicates whether to add the '-dark' prefix to the theme based on the $1 argument and whether the current theme is an elementary one
USE_CUSTOM_ELEMENTARY_DARK="$([ "$1" == 1 ] && [ ! -z "$(echo "$THEME" | grep -e "^io\.elementary\.stylesheet\..*")" ] && echo 1 || echo 0)"
# Grab the list of app IDs for all non-appcenter installed Flatpaks
TARGET_APP_IDS=($(flatpak list --columns=application,origin,runtime | awk -F "\t" '{if ($2 != "appcenter" && $3 != "") print $1}'))
# For each target app ID...
for APP_ID in "${TARGET_APP_IDS[@]}"; do
# Grab the appropriate Flatpak runtime
RUNTIME="$(flatpak info --show-runtime "$APP_ID")"
# Ensure the runtime has a theme directory
RUNTIME_THEME_DIR="$FLATPAK_RUNTIME_DIR"/"$RUNTIME"/"$RUNTIME_THEME_SUBDIR"
if [ ! -d "$RUNTIME_THEME_DIR" ]; then mkdir -p "$RUNTIME_THEME_DIR"; fi
# Check to see if the current theme (or the current theme plus the '-dark' suffix if needed) is already installed in the runtime
THEME_IN_RUNTIME_SEARCH_RESULT="$([ "$USE_CUSTOM_ELEMENTARY_DARK" -eq 1 ] && echo "$(ls "$RUNTIME_THEME_DIR" | grep "$THEME"-dark)" || echo "$(ls "$RUNTIME_THEME_DIR" | grep "$THEME")")"
# If not, find where the theme is stored (in the system or user directory) and copy it into the runtime theme folder
# Add '-dark' suffix to it if needed and make the necessary changes
if [ -z "$THEME_IN_RUNTIME_SEARCH_RESULT" ]; then
# Find where the theme is stored
TARGET_THEME_LOCATION=''
POSSIBLE_THEME_LOCATIONS=(/usr/share/themes ~/.local/share/themes)
for LOCATION in "${POSSIBLE_THEME_LOCATIONS[@]}"; do
if [ ! -z "$(ls "$LOCATION" | grep -e ^"$THEME"$)" ]; then TARGET_THEME_LOCATION="$LOCATION"/"$THEME"; fi
done
[ ! -z "$TARGET_THEME_LOCATION" ] || log "Location of the currently set theme - $THEME - could not be found" 1 1
# If there is not need to make the '-dark' modifications, copy the theme into the Flatpak runtime; else, modify it in a temporary directory first, then copy it
if [ ! "$USE_CUSTOM_ELEMENTARY_DARK" -eq 1 ]; then
cp -r "$TARGET_THEME_LOCATION" "$RUNTIME_THEME_DIR"
log "$THEME theme has been installed into $RUNTIME Flatpak runtime"
else
TEMP_DIR="$(mktemp -d)"
cp -r "$TARGET_THEME_LOCATION" "$TEMP_DIR"
cp -r "$TEMP_DIR"/"$THEME" "$TEMP_DIR"/"$THEME"-dark
mv "$TEMP_DIR"/"$THEME"-dark/plank "$TEMP_DIR"/"$THEME"-dark/plank-light
mv "$TEMP_DIR"/"$THEME"-dark/plank-dark "$TEMP_DIR"/"$THEME"-dark/plank
mv "$TEMP_DIR"/"$THEME"-dark/gtk-3.0/gtk.css "$TEMP_DIR"/"$THEME"-dark/gtk-3.0/gtk-light.css
mv "$TEMP_DIR"/"$THEME"-dark/gtk-3.0/gtk-dark.css "$TEMP_DIR"/"$THEME"-dark/gtk-3.0/gtk.css
cp -r "$TEMP_DIR"/"$THEME"-dark "$RUNTIME_THEME_DIR"
rm -r "$TEMP_DIR"
log "$THEME theme has been modified to $THEME-dark and installed into $RUNTIME Flatpak runtime"
fi
else
log "$THEME theme is already installed in the $RUNTIME Flatpak runtime, no changes made" 0 0 1
fi
# Now that the theme is installed, do the override if needed
CURRENT_APP_THEME="$(flatpak override --user --show "$APP_ID" | grep GTK_THEME= | tail -c +11)"
FINAL_OVERRIDE_THEME_NAME="$([ "$USE_CUSTOM_ELEMENTARY_DARK" == 1 ] && echo "$(echo "$THEME" | head -c -1 | tail -c +1)-dark" || echo "$THEME")"
if [ "$CURRENT_APP_THEME" != "$FINAL_OVERRIDE_THEME_NAME" ]; then
flatpak override --user --env=GTK_THEME="$FINAL_OVERRIDE_THEME_NAME" "$APP_ID"
log "Flatpak environment variable override 'GTK_THEME=$FINAL_OVERRIDE_THEME_NAME' has been added for $APP_ID"
else
log "Flatpak environment variable override 'GTK_THEME=$FINAL_OVERRIDE_THEME_NAME' is already set for $APP_ID, no changes made" 0 0 1
fi
done
}
# =======================================
# Actual execution
# =======================================
# 1. Change the universal GTK dark theme preference if needed
# 2. Change the wallpaper if needed
# 3. Change the Mailspring theme if needed
# 4. Change the theme of all non-elementary Flatpak apps if needed
SYSTEM_DARK_PREF="$(getSystemDarkStylePref)"
changeGTKUniversalDarkPrefIfNeeded "$SYSTEM_DARK_PREF"
changeWallpaperIfNeeded "$([ "$SYSTEM_DARK_PREF" == 1 ] && echo "$DARK_THEME_WALLPAPER" || echo "$LIGHT_THEME_WALLPAPER")"
changeMailSpringThemeIfNeeded "$([ "$SYSTEM_DARK_PREF" == 1 ] && echo "$MAILSPRING_DARK_THEME" || echo "$MAILSPRING_LIGHT_THEME")"
changeNonElementaryFlatpakThemesIfNeeded "$SYSTEM_DARK_PREF"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment