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}