-
-
Save ImranR98/8d6423fdc11022162cf416cc6de0d9af to your computer and use it in GitHub Desktop.
#!/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 | |
} | |
# 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 | |
[ "$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])" | |
# Ensure it is 0 or 1; if not, log the error and exit | |
[ "$GTK_UNIVERSAL_PREF_IS_DARK" == 0 ] || [ "$GTK_UNIVERSAL_PREF_IS_DARK" == 1 ] || log "$GTK_UNIVERSAL_PREF_FILE is not valid" 1 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" |
im getting the same error too
im getting the same error too
Should be fixed now. It should now create the settings.ini
file if needed.
It looks like it stopped detecting theme changes. :(
Also, sometimes it will show me this error:
ERROR: vie 27 ago 2021 20:14:07 CDT: /home/mrtn/.config/gtk-3.0/settings.ini is not valid
CRASHED.
What about making this script more cron-friendly? Better than doing the checks in an infinite while loop.
Edit: About the error, it looks like sometimes it will randomly append a 0 to the dark preference theme, so that's when it gets triggered.
What about making this script more cron-friendly? Better than doing the checks in an infinite while loop.
Edit: About the error, it looks like sometimes it will randomly append a 0 to the dark preference theme, so that's when it gets triggered.
Yep, turns out extra newlines in the settings.ini
file were causing problems. Fixed now, thanks for pointing that out.
Also you're right about the while loop; no point making a custom timing function when Linux already has a widely used solution. Have made the changes.
still not working, test on eos 6.
Moving forward, elementaryOS's dark theme preference will be natively supported by GTK apps. Not sure what the status of that is since I'm not using eOS anymore, but you could look into that. Was working fine for me on eOS 6 a few months ago, so I'm not sure what changed. Probably won't make any more changes to this script.
Moving forward, elementaryOS's dark theme preference will be natively supported by GTK apps. Not sure what the status of that is since I'm not using eOS anymore, but you could look into that. Was working fine for me on eOS 6 a few months ago, so I'm not sure what changed. Probably won't make any more changes to this script.
thanks for your repply. Eos6 still not support dark mode in flatpak apps.
Should be fixed now.