diff options
| author | Charles Lombardo <clombardo169@gmail.com> | 2022-11-11 20:44:30 -0500 |
|---|---|---|
| committer | Charles Lombardo <clombardo169@gmail.com> | 2022-12-02 13:31:57 -0500 |
| commit | b9fffa2e66025e7f4b3f8a4ff4e6c71a171452f8 (patch) | |
| tree | 63fd805aaec412e70022083cb06cd08c981051e0 /Source | |
| parent | 385dfb60a0da10ff899bafbdd3a8d90168022db9 (diff) | |
Android: Add theme mode switcher
Similar to app themes, theme modes have to be loaded before directory initialization is ready. So we save the proper key the same way.
Diffstat (limited to 'Source')
16 files changed, 170 insertions, 55 deletions
diff --git a/Source/Android/app/build.gradle b/Source/Android/app/build.gradle index f13c7f81b4..23f9e6e3d6 100644 --- a/Source/Android/app/build.gradle +++ b/Source/Android/app/build.gradle @@ -96,7 +96,7 @@ android { dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' - implementation 'androidx.appcompat:appcompat:1.5.0' + implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'androidx.exifinterface:exifinterface:1.3.3' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.2.1' diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java index 11fc2a0046..c7f2b0c54c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java @@ -34,6 +34,8 @@ public enum IntSetting implements AbstractIntSetting MAIN_EMULATION_ORIENTATION(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "EmulationOrientation", ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE), MAIN_INTERFACE_THEME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "InterfaceTheme", 0), + MAIN_INTERFACE_THEME_MODE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, + "InterfaceThemeMode", -1), MAIN_LAST_PLATFORM_TAB(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "LastPlatformTab", 0), MAIN_MOTION_CONTROLS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "MotionControls", 1), MAIN_IR_MODE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "IRMode", diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java index 1f073ace20..3c0838029b 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java @@ -8,6 +8,8 @@ import android.os.Build; import android.os.Bundle; import android.text.TextUtils; +import androidx.appcompat.app.AppCompatActivity; + import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.UserDataActivity; @@ -328,33 +330,37 @@ public final class SettingsFragmentPresenter AbstractIntSetting appTheme = new AbstractIntSetting() { - @Override public boolean isOverridden(Settings settings) + @Override + public boolean isOverridden(Settings settings) { return IntSetting.MAIN_INTERFACE_THEME.isOverridden(settings); } - @Override public boolean isRuntimeEditable() + @Override + public boolean isRuntimeEditable() { // This only affects app UI return true; } - @Override public boolean delete(Settings settings) + @Override + public boolean delete(Settings settings) { - ThemeHelper.deleteThemeKey(mView.getActivity()); + ThemeHelper.deleteThemeKey((AppCompatActivity) mView.getActivity()); return IntSetting.MAIN_INTERFACE_THEME.delete(settings); } - @Override public int getInt(Settings settings) + @Override + public int getInt(Settings settings) { return IntSetting.MAIN_INTERFACE_THEME.getInt(settings); } - @Override public void setInt(Settings settings, int newValue) + @Override + public void setInt(Settings settings, int newValue) { - ThemeHelper.saveTheme(mView.getActivity(), newValue); IntSetting.MAIN_INTERFACE_THEME.setInt(settings, newValue); - mView.getActivity().recreate(); + ThemeHelper.saveTheme((AppCompatActivity) mView.getActivity(), newValue); } }; @@ -369,6 +375,45 @@ public final class SettingsFragmentPresenter sl.add(new SingleChoiceSetting(mContext, appTheme, R.string.change_theme, 0, R.array.themeEntries, R.array.themeValues)); } + + AbstractIntSetting themeMode = new AbstractIntSetting() + { + @Override + public boolean isOverridden(Settings settings) + { + return IntSetting.MAIN_INTERFACE_THEME_MODE.isOverridden(settings); + } + + @Override + public boolean isRuntimeEditable() + { + // This only affects app UI + return true; + } + + @Override + public boolean delete(Settings settings) + { + ThemeHelper.deleteThemeModeKey((AppCompatActivity) mView.getActivity()); + return IntSetting.MAIN_INTERFACE_THEME_MODE.delete(settings); + } + + @Override + public int getInt(Settings settings) + { + return IntSetting.MAIN_INTERFACE_THEME_MODE.getInt(settings); + } + + @Override + public void setInt(Settings settings, int newValue) + { + IntSetting.MAIN_INTERFACE_THEME_MODE.setInt(settings, newValue); + ThemeHelper.saveThemeMode((AppCompatActivity) mView.getActivity(), newValue); + } + }; + + sl.add(new SingleChoiceSetting(mContext, themeMode, R.string.change_theme_mode, 0, + R.array.themeModeEntries, R.array.themeModeValues)); } private void addAudioSettings(ArrayList<SettingsItem> sl) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java index f872802a9f..15cf635615 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java @@ -13,6 +13,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatDelegate; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.preference.PreferenceManager; @@ -87,6 +88,16 @@ public final class DirectoryInitialization .apply(); } + if (IntSetting.MAIN_INTERFACE_THEME_MODE.getIntGlobal() != + preferences.getInt(ThemeHelper.CURRENT_THEME_MODE, + AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)) + { + preferences.edit() + .putInt(ThemeHelper.CURRENT_THEME_MODE, + IntSetting.MAIN_INTERFACE_THEME_MODE.getIntGlobal()) + .apply(); + } + if (wiimoteIniWritten) { // This has to be done after calling NativeLibrary.Initialize(), diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ThemeHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ThemeHelper.java index ff96e033c0..040e20990a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ThemeHelper.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ThemeHelper.java @@ -10,7 +10,10 @@ import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; import androidx.core.content.ContextCompat; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsControllerCompat; import androidx.preference.PreferenceManager; import com.google.android.material.appbar.AppBarLayout; @@ -23,6 +26,7 @@ import org.dolphinemu.dolphinemu.ui.main.ThemeProvider; public class ThemeHelper { public static final String CURRENT_THEME = "current_theme"; + public static final String CURRENT_THEME_MODE = "current_theme_mode"; public static final int DEFAULT = 0; public static final int MONET = 1; @@ -38,6 +42,7 @@ public class ThemeHelper // requested theme id is ready before the onCreate method of any given Activity. SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()); + setThemeMode(activity); switch (preferences.getInt(CURRENT_THEME, DEFAULT)) { case DEFAULT: @@ -70,22 +75,88 @@ public class ThemeHelper } } - public static void saveTheme(@NonNull Activity activity, int themeValue) + private static void setThemeMode(@NonNull AppCompatActivity activity) { - SharedPreferences preferences = - PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()); - preferences.edit().putInt(CURRENT_THEME, themeValue).apply(); + int themeMode = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()) + .getInt(CURRENT_THEME_MODE, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); + activity.getDelegate().setLocalNightMode(themeMode); + + WindowInsetsControllerCompat windowController = + WindowCompat.getInsetsController(activity.getWindow(), + activity.getWindow().getDecorView()); + int systemReportedThemeMode = + activity.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; + + switch (themeMode) + { + case AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM: + switch (systemReportedThemeMode) + { + case Configuration.UI_MODE_NIGHT_NO: + setLightModeSystemBars(windowController); + break; + case Configuration.UI_MODE_NIGHT_YES: + setDarkModeSystemBars(windowController); + break; + } + break; + case AppCompatDelegate.MODE_NIGHT_NO: + setLightModeSystemBars(windowController); + break; + case AppCompatDelegate.MODE_NIGHT_YES: + setDarkModeSystemBars(windowController); + break; + } } - public static void deleteThemeKey(@NonNull Activity activity) + private static void setLightModeSystemBars(@NonNull WindowInsetsControllerCompat windowController) { - SharedPreferences preferences = - PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()); - preferences.edit().remove(CURRENT_THEME).apply(); - activity.setTheme(R.style.Theme_Dolphin_Main); + windowController.setAppearanceLightStatusBars(true); + windowController.setAppearanceLightNavigationBars(true); + } + + private static void setDarkModeSystemBars(@NonNull WindowInsetsControllerCompat windowController) + { + windowController.setAppearanceLightStatusBars(false); + windowController.setAppearanceLightNavigationBars(false); + } + + public static void saveTheme(@NonNull AppCompatActivity activity, int themeValue) + { + PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()) + .edit() + .putInt(CURRENT_THEME, themeValue) + .apply(); + activity.recreate(); + } + + public static void deleteThemeKey(@NonNull AppCompatActivity activity) + { + PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()) + .edit() + .remove(CURRENT_THEME) + .apply(); activity.recreate(); } + public static void saveThemeMode(@NonNull AppCompatActivity activity, int themeModeValue) + { + PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()) + .edit() + .putInt(CURRENT_THEME_MODE, themeModeValue) + .apply(); + setThemeMode(activity); + } + + public static void deleteThemeModeKey(@NonNull AppCompatActivity activity) + { + PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()) + .edit() + .remove(CURRENT_THEME_MODE) + .apply(); + setThemeMode(activity); + } + public static void setCorrectTheme(AppCompatActivity activity) { int currentTheme = ((ThemeProvider) activity).getThemeId(); @@ -110,7 +181,7 @@ public class ThemeHelper } } - public static void setNavigationBarColor(Activity activity, @ColorInt int color) + public static void setNavigationBarColor(@NonNull Activity activity, @ColorInt int color) { int gestureType = InsetsHelper.getSystemGestureType(activity.getApplicationContext()); int orientation = activity.getResources().getConfiguration().orientation; diff --git a/Source/Android/app/src/main/res/drawable/ic_back.xml b/Source/Android/app/src/main/res/drawable/ic_back.xml deleted file mode 100644 index 344d5e6974..0000000000 --- a/Source/Android/app/src/main/res/drawable/ic_back.xml +++ /dev/null @@ -1,9 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path - android:fillColor="?attr/colorOnSurface" - android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/> -</vector> diff --git a/Source/Android/app/src/main/res/drawable/tv_card_background.xml b/Source/Android/app/src/main/res/drawable/tv_card_background.xml index ee4320d5b3..58ae5f09a8 100644 --- a/Source/Android/app/src/main/res/drawable/tv_card_background.xml +++ b/Source/Android/app/src/main/res/drawable/tv_card_background.xml @@ -2,7 +2,7 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" - android:drawable="@color/dolphin_primary"/> + android:drawable="@color/dolphin_blue"/> <item android:drawable="@color/tv_card_unselected"/> </selector> diff --git a/Source/Android/app/src/main/res/values-night/bools.xml b/Source/Android/app/src/main/res/values-night/bools.xml deleted file mode 100644 index 85800a2f2c..0000000000 --- a/Source/Android/app/src/main/res/values-night/bools.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources> - <bool name="lightSystemBars">false</bool> -</resources> diff --git a/Source/Android/app/src/main/res/values-v27/themes.xml b/Source/Android/app/src/main/res/values-v27/themes.xml deleted file mode 100644 index ec8f103c8d..0000000000 --- a/Source/Android/app/src/main/res/values-v27/themes.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources> - <style name="Theme.V27.Dolphin" parent="Theme.Dolphin"> - <item name="android:windowLightNavigationBar">@bool/lightSystemBars</item> - </style> - - <style name="Theme.Dolphin.Main" parent="Theme.V27.Dolphin" /> -</resources> diff --git a/Source/Android/app/src/main/res/values-v29/themes.xml b/Source/Android/app/src/main/res/values-v29/themes.xml index 232c5aeefa..ac6105b3bb 100644 --- a/Source/Android/app/src/main/res/values-v29/themes.xml +++ b/Source/Android/app/src/main/res/values-v29/themes.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <style name="Theme.V29.Dolphin" parent="Theme.V27.Dolphin"> + <style name="Theme.V29.Dolphin" parent="Theme.Dolphin"> <item name="android:enforceStatusBarContrast">false</item> <item name="android:enforceNavigationBarContrast">false</item> </style> diff --git a/Source/Android/app/src/main/res/values/arrays.xml b/Source/Android/app/src/main/res/values/arrays.xml index 0089d6eef6..4b789407b3 100644 --- a/Source/Android/app/src/main/res/values/arrays.xml +++ b/Source/Android/app/src/main/res/values/arrays.xml @@ -507,6 +507,17 @@ <item>4</item> </integer-array> + <string-array name="themeModeEntries"> + <item>Follow System</item> + <item>Light</item> + <item>Dark</item> + </string-array> + <integer-array name="themeModeValues"> + <item>-1</item> + <item>1</item> + <item>2</item> + </integer-array> + <string-array name="synchronizeGpuThreadEntries"> <item>Never</item> <item>On Idle Skipping</item> diff --git a/Source/Android/app/src/main/res/values/bools.xml b/Source/Android/app/src/main/res/values/bools.xml deleted file mode 100644 index fbc2def833..0000000000 --- a/Source/Android/app/src/main/res/values/bools.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources> - <bool name="lightSystemBars">true</bool> -</resources> diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index f35b5adb60..e262eb65c5 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -196,6 +196,7 @@ <string name="show_titles_in_game_list">Show Titles in Game List</string> <string name="show_titles_in_game_list_description">Show the title and creator below each game cover.</string> <string name="change_theme">Change App Theme</string> + <string name="change_theme_mode">Change Theme Mode</string> <!-- Online Update Region Select Fragment --> <string name="region_select_title">Please select a region</string> diff --git a/Source/Android/app/src/main/res/values/styles.xml b/Source/Android/app/src/main/res/values/styles.xml index 9c71db19ee..c5d03d9e5c 100644 --- a/Source/Android/app/src/main/res/values/styles.xml +++ b/Source/Android/app/src/main/res/values/styles.xml @@ -42,7 +42,7 @@ <style name="DolphinTVDialog" parent="Theme.Material3.DayNight.Dialog.Alert"> <item name="colorSurface">@color/dolphin_inverseOnSurface</item> - <item name="colorPrimary">@color/dolphin_primary</item> + <item name="colorPrimary">@color/dolphin_blue</item> </style> <style name="DolphinButton" parent="Widget.Material3.Button.TextButton.Dialog"> diff --git a/Source/Android/app/src/main/res/values/themes.xml b/Source/Android/app/src/main/res/values/themes.xml index f9c1727adf..177febe54b 100644 --- a/Source/Android/app/src/main/res/values/themes.xml +++ b/Source/Android/app/src/main/res/values/themes.xml @@ -47,9 +47,6 @@ <item name="android:windowAllowEnterTransitionOverlap">true</item> <item name="android:windowAllowReturnTransitionOverlap">true</item> - <item name="homeAsUpIndicator">@drawable/ic_back</item> - - <item name="android:windowLightStatusBar" tools:targetApi="m">@bool/lightSystemBars</item> <item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">default</item> <item name="materialAlertDialogTheme">@style/DolphinMaterialDialog</item> @@ -58,7 +55,7 @@ <item name="materialDividerStyle">@style/DolphinDivider</item> </style> - <!-- Trick for API >= 27 specific changes --> + <!-- Trick for API >= 29 specific changes --> <style name="Theme.Dolphin.Main" parent="Theme.Dolphin" /> <style name="Theme.Dolphin.Main.Material" parent="Theme.Dolphin.Main"> diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index bd7f28fe3c..9c50002204 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -39,10 +39,12 @@ bool IsSettingSaveable(const Config::Location& config_location) // TODO: Kill the current Android controller mappings system if (config_location.section == "Android") { - static constexpr std::array<const char*, 12> android_setting_saveable = { - "ControlScale", "ControlOpacity", "EmulationOrientation", "JoystickRelCenter", - "LastPlatformTab", "MotionControls", "PhoneRumble", "ShowInputOverlay", - "IRMode", "IRAlwaysRecenter", "ShowGameTitles", "InterfaceTheme"}; + static constexpr std::array<const char*, 13> android_setting_saveable = { + "ControlScale", "ControlOpacity", "EmulationOrientation", + "JoystickRelCenter", "LastPlatformTab", "MotionControls", + "PhoneRumble", "ShowInputOverlay", "IRMode", + "IRAlwaysRecenter", "ShowGameTitles", "InterfaceTheme", + "InterfaceThemeMode"}; return std::any_of( android_setting_saveable.cbegin(), android_setting_saveable.cend(), |
