1package eu.siacs.conversations;
  2
  3import android.annotation.SuppressLint;
  4import android.app.Application;
  5import android.content.Context;
  6import android.content.SharedPreferences;
  7import android.preference.PreferenceManager;
  8
  9import androidx.appcompat.app.AppCompatDelegate;
 10
 11import com.google.android.material.color.DynamicColors;
 12import com.google.android.material.color.DynamicColorsOptions;
 13
 14import eu.siacs.conversations.services.EmojiInitializationService;
 15import eu.siacs.conversations.utils.ExceptionHelper;
 16import eu.siacs.conversations.utils.ThemeHelper;
 17
 18public class Conversations extends Application {
 19
 20    @SuppressLint("StaticFieldLeak")
 21    private static Context CONTEXT;
 22
 23    public static Context getContext() {
 24        return Conversations.CONTEXT;
 25    }
 26
 27    @Override
 28    public void onCreate() {
 29        super.onCreate();
 30        CONTEXT = this.getApplicationContext();
 31        EmojiInitializationService.execute(getApplicationContext());
 32        ExceptionHelper.init(getApplicationContext());
 33        applyThemeSettings();
 34    }
 35
 36    public void applyThemeSettings() {
 37        final var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 38        if (sharedPreferences == null) {
 39            return;
 40        }
 41        applyThemeSettings(sharedPreferences);
 42    }
 43
 44    private void applyThemeSettings(final SharedPreferences sharedPreferences) {
 45        AppCompatDelegate.setDefaultNightMode(getDesiredNightMode(this, sharedPreferences));
 46        var dynamicColorsOptions =
 47                new DynamicColorsOptions.Builder()
 48                        .setPrecondition((activity, t) -> isDynamicColorsDesired(activity))
 49                        .build();
 50        DynamicColors.applyToActivitiesIfAvailable(this, dynamicColorsOptions);
 51    }
 52
 53    public static int getDesiredNightMode(final Context context) {
 54        final var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
 55        if (sharedPreferences == null) {
 56            return AppCompatDelegate.getDefaultNightMode();
 57        }
 58        return getDesiredNightMode(context, sharedPreferences);
 59    }
 60
 61    public static boolean isDynamicColorsDesired(final Context context) {
 62        final var preferences = PreferenceManager.getDefaultSharedPreferences(context);
 63        if (isCustomColorsDesired(context)) return false;
 64        return preferences.getBoolean(AppSettings.DYNAMIC_COLORS, false);
 65    }
 66
 67    public static boolean isCustomColorsDesired(final Context context) {
 68        final var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
 69        final String theme =
 70                sharedPreferences.getString(AppSettings.THEME, context.getString(R.string.theme));
 71        return "custom".equals(theme);
 72    }
 73
 74    private static int getDesiredNightMode(
 75            final Context context, final SharedPreferences sharedPreferences) {
 76        var theme =
 77                sharedPreferences.getString(AppSettings.THEME, context.getString(R.string.theme));
 78
 79        // Migrate old themes to equivalent custom
 80        if ("oledblack".equals(theme)) {
 81            theme = "custom";
 82            final var p = PreferenceManager.getDefaultSharedPreferences(context);
 83            p
 84                .edit()
 85                .putString(AppSettings.THEME, "custom")
 86                .putBoolean("custom_theme_automatic", false)
 87                .putBoolean("custom_theme_dark", true)
 88                .putBoolean("custom_theme_color_match", true)
 89                .putInt("custom_dark_theme_primary", context.getColor(R.color.white))
 90                .putInt("custom_dark_theme_primary_dark", context.getColor(android.R.color.black))
 91                .putInt("custom_dark_theme_accent", context.getColor(R.color.yeller))
 92                .putInt("custom_dark_theme_background_primary", context.getColor(android.R.color.black))
 93                .commit();
 94        }
 95
 96        // Migrate old themes to equivalent custom
 97        if ("obsidian".equals(theme)) {
 98            theme = "custom";
 99            final var p = PreferenceManager.getDefaultSharedPreferences(context);
100            p
101                .edit()
102                .putString(AppSettings.THEME, "custom")
103                .putBoolean("custom_theme_automatic", false)
104                .putBoolean("custom_theme_dark", true)
105                .putInt("custom_dark_theme_primary", context.getColor(R.color.black_perpy))
106                .putInt("custom_dark_theme_primary_dark", context.getColor(R.color.black_perpy))
107                .putInt("custom_dark_theme_accent", context.getColor(R.color.yeller))
108                .putInt("custom_dark_theme_background_primary", context.getColor(R.color.blacker_perpy))
109                .commit();
110        }
111
112        if ("custom".equals(theme)) {
113            if (sharedPreferences.getBoolean("custom_theme_automatic", false)) return AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
114            return sharedPreferences.getBoolean("custom_theme_dark", false) ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO;
115        }
116
117        return getDesiredNightMode(theme);
118    }
119
120    public static int getDesiredNightMode(final String theme) {
121        if ("automatic".equals(theme)) {
122            return AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
123        } else if ("light".equals(theme)) {
124            return AppCompatDelegate.MODE_NIGHT_NO;
125        } else {
126            return AppCompatDelegate.MODE_NIGHT_YES;
127        }
128    }
129}