From 9429e2a8549ff6c4691ae1827af0168079174e54 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 24 Apr 2020 20:14:52 -0400 Subject: [PATCH] android: settings: Store theme setting in shared preferences. - Fixes some jankieness. --- .../view/PremiumSingleChoiceSetting.java | 62 +++++++++++++++++ .../ui/SettingsActivityPresenter.java | 3 +- .../features/settings/ui/SettingsAdapter.java | 69 +++++++++++++++++++ .../ui/SettingsFragmentPresenter.java | 23 ++++--- .../ui/viewholder/SingleChoiceViewHolder.java | 14 ++++ .../org/citra/citra_emu/utils/ThemeUtil.java | 27 ++------ src/android/app/src/main/jni/default_ini.h | 5 -- .../app/src/main/res/values/strings.xml | 7 +- 8 files changed, 170 insertions(+), 40 deletions(-) create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/PremiumSingleChoiceSetting.java diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/PremiumSingleChoiceSetting.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/PremiumSingleChoiceSetting.java new file mode 100644 index 000000000..93a96d73b --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/PremiumSingleChoiceSetting.java @@ -0,0 +1,62 @@ +package org.citra.citra_emu.features.settings.model.view; + +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +import org.citra.citra_emu.CitraApplication; +import org.citra.citra_emu.R; +import org.citra.citra_emu.features.settings.model.Setting; +import org.citra.citra_emu.features.settings.ui.SettingsFragmentView; + +public final class PremiumSingleChoiceSetting extends SettingsItem { + private int mDefaultValue; + + private int mChoicesId; + private int mValuesId; + private SettingsFragmentView mView; + + private static SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(CitraApplication.getAppContext()); + + public PremiumSingleChoiceSetting(String key, String section, int titleId, int descriptionId, + int choicesId, int valuesId, int defaultValue, Setting setting, SettingsFragmentView view) { + super(key, section, setting, titleId, descriptionId); + mValuesId = valuesId; + mChoicesId = choicesId; + mDefaultValue = defaultValue; + mView = view; + } + + public int getChoicesId() { + return mChoicesId; + } + + public int getValuesId() { + return mValuesId; + } + + public int getSelectedValue() { + return mPreferences.getInt(getSetting().getKey(), 0); + } + + /** + * Write a value to the backing int. If that int was previously null, + * initializes a new one and returns it, so it can be added to the Hashmap. + * + * @param selection New value of the int. + * @return null if overwritten successfully otherwise; a newly created IntSetting. + */ + public void setSelectedValue(int selection) { + if (selection == getSelectedValue()) { + return; + } + final SharedPreferences.Editor editor = mPreferences.edit(); + editor.putInt(getKey(), selection); + editor.apply(); + mView.showToastMessage(CitraApplication.getAppContext().getString(R.string.design_updated), false); + } + + @Override + public int getType() { + return TYPE_SINGLE_CHOICE; + } +} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsActivityPresenter.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsActivityPresenter.java index daee05ca7..a57c54535 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsActivityPresenter.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsActivityPresenter.java @@ -109,9 +109,10 @@ public final class SettingsActivityPresenter { if (mSettings != null && finishing && mShouldSave) { Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI..."); mSettings.saveSettings(mView); - ThemeUtil.applyTheme(mSettings); } + ThemeUtil.applyTheme(); + NativeLibrary.ReloadSettings(); } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.java index eca7e12e9..bae1796e9 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.java @@ -21,6 +21,7 @@ import org.citra.citra_emu.features.settings.model.StringSetting; import org.citra.citra_emu.features.settings.model.view.CheckBoxSetting; import org.citra.citra_emu.features.settings.model.view.DateTimeSetting; import org.citra.citra_emu.features.settings.model.view.InputBindingSetting; +import org.citra.citra_emu.features.settings.model.view.PremiumSingleChoiceSetting; import org.citra.citra_emu.features.settings.model.view.SettingsItem; import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting; import org.citra.citra_emu.features.settings.model.view.SliderSetting; @@ -143,6 +144,19 @@ public final class SettingsAdapter extends RecyclerView.Adapter onSingleChoiceClick(item)); } + public void onSingleChoiceClick(PremiumSingleChoiceSetting item, int position) { + mClickedPosition = position; + + if (!item.isPremium() || MainActivity.isPremiumActive()) { + // Setting is either not Premium, or the user has Premium + onSingleChoiceClick(item); + return; + } + + // User needs Premium, invoke the billing flow + MainActivity.invokePremiumBilling(() -> onSingleChoiceClick(item)); + } + public void onStringSingleChoiceClick(StringSingleChoiceSetting item, int position) { mClickedItem = item; mClickedPosition = position; @@ -317,6 +344,18 @@ public final class SettingsAdapter extends RecyclerView.Adapter 0) { + int[] valuesArray = mContext.getResources().getIntArray(valuesId); + return valuesArray[which]; + } else { + return which; + } + } + private int getSelectionForSingleChoiceValue(SingleChoiceSetting item) { int value = item.getSelectedValue(); int valuesId = item.getValuesId(); @@ -411,4 +461,23 @@ public final class SettingsAdapter extends RecyclerView.Adapter 0) { + int[] valuesArray = mContext.getResources().getIntArray(valuesId); + for (int index = 0; index < valuesArray.length; index++) { + int current = valuesArray[index]; + if (current == value) { + return index; + } + } + } else { + return value; + } + + return -1; + } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.java index db7780358..a7bd969db 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.java @@ -16,12 +16,13 @@ import org.citra.citra_emu.features.settings.model.view.CheckBoxSetting; import org.citra.citra_emu.features.settings.model.view.DateTimeSetting; import org.citra.citra_emu.features.settings.model.view.HeaderSetting; import org.citra.citra_emu.features.settings.model.view.InputBindingSetting; +import org.citra.citra_emu.features.settings.model.view.PremiumHeader; +import org.citra.citra_emu.features.settings.model.view.PremiumSingleChoiceSetting; import org.citra.citra_emu.features.settings.model.view.SettingsItem; import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting; import org.citra.citra_emu.features.settings.model.view.SliderSetting; import org.citra.citra_emu.features.settings.model.view.StringSingleChoiceSetting; import org.citra.citra_emu.features.settings.model.view.SubmenuSetting; -import org.citra.citra_emu.features.settings.model.view.PremiumHeader; import org.citra.citra_emu.features.settings.utils.SettingsFile; import org.citra.citra_emu.utils.Log; @@ -144,7 +145,7 @@ public final class SettingsFragmentPresenter { Setting design = premiumSection.getSetting(SettingsFile.KEY_DESIGN); sl.add(new PremiumHeader()); - sl.add(new SingleChoiceSetting(SettingsFile.KEY_DESIGN, Settings.SECTION_PREMIUM, R.string.design, 0, R.array.designNames, R.array.designValues, 0, design)); + sl.add(new PremiumSingleChoiceSetting(SettingsFile.KEY_DESIGN, Settings.SECTION_PREMIUM, R.string.design, 0, R.array.designNames, R.array.designValues, 0, design, mView)); } private void addGeneralSettings(ArrayList sl) { @@ -194,15 +195,15 @@ public final class SettingsFragmentPresenter { final int facing = Objects.requireNonNull(characteristics.get(CameraCharacteristics.LENS_FACING)); int stringId = R.string.camera_facing_external; switch (facing) { - case CameraCharacteristics.LENS_FACING_FRONT: - stringId = R.string.camera_facing_front; - break; - case CameraCharacteristics.LENS_FACING_BACK: - stringId = R.string.camera_facing_back; - break; - case CameraCharacteristics.LENS_FACING_EXTERNAL: - stringId = R.string.camera_facing_external; - break; + case CameraCharacteristics.LENS_FACING_FRONT: + stringId = R.string.camera_facing_front; + break; + case CameraCharacteristics.LENS_FACING_BACK: + stringId = R.string.camera_facing_back; + break; + case CameraCharacteristics.LENS_FACING_EXTERNAL: + stringId = R.string.camera_facing_external; + break; } supportedCameraNameList.add(String.format("%1$s (%2$s)", id, stringId)); } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.java index f735b7752..a175af9f8 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.java @@ -5,6 +5,7 @@ import android.view.View; import android.widget.TextView; import org.citra.citra_emu.R; +import org.citra.citra_emu.features.settings.model.view.PremiumSingleChoiceSetting; import org.citra.citra_emu.features.settings.model.view.SettingsItem; import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting; import org.citra.citra_emu.features.settings.model.view.StringSingleChoiceSetting; @@ -45,6 +46,17 @@ public final class SingleChoiceViewHolder extends SettingViewHolder { mTextSettingDescription.setText(choices[i]); } } + } else if (item instanceof PremiumSingleChoiceSetting) { + PremiumSingleChoiceSetting setting = (PremiumSingleChoiceSetting) item; + int selected = setting.getSelectedValue(); + Resources resMgr = mTextSettingDescription.getContext().getResources(); + String[] choices = resMgr.getStringArray(setting.getChoicesId()); + int[] values = resMgr.getIntArray(setting.getValuesId()); + for (int i = 0; i < values.length; ++i) { + if (values[i] == selected) { + mTextSettingDescription.setText(choices[i]); + } + } } else { mTextSettingDescription.setVisibility(View.GONE); } @@ -55,6 +67,8 @@ public final class SingleChoiceViewHolder extends SettingViewHolder { int position = getAdapterPosition(); if (mItem instanceof SingleChoiceSetting) { getAdapter().onSingleChoiceClick((SingleChoiceSetting) mItem, position); + } else if (mItem instanceof PremiumSingleChoiceSetting) { + getAdapter().onSingleChoiceClick((PremiumSingleChoiceSetting) mItem, position); } else if (mItem instanceof StringSingleChoiceSetting) { getAdapter().onStringSingleChoiceClick((StringSingleChoiceSetting) mItem, position); } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/ThemeUtil.java b/src/android/app/src/main/java/org/citra/citra_emu/utils/ThemeUtil.java index bb76a08e8..74ef3867f 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/ThemeUtil.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/ThemeUtil.java @@ -1,25 +1,16 @@ package org.citra.citra_emu.utils; +import android.content.SharedPreferences; import android.os.Build; +import android.preference.PreferenceManager; import androidx.appcompat.app.AppCompatDelegate; -import org.citra.citra_emu.features.settings.model.Setting; -import org.citra.citra_emu.features.settings.model.Settings; +import org.citra.citra_emu.CitraApplication; import org.citra.citra_emu.features.settings.utils.SettingsFile; public class ThemeUtil { - - public static void applyTheme() { - Settings settings = new Settings(); - - try { - settings.loadSettings(null); - applyTheme(settings); - } catch (Exception e) { - applyTheme(0); - } - } + private static SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(CitraApplication.getAppContext()); private static void applyTheme(int designValue) { switch (designValue) { @@ -37,13 +28,7 @@ public class ThemeUtil { } } - public static void applyTheme(Settings settings) { - Setting design = settings.getSection(Settings.SECTION_PREMIUM).getSetting((SettingsFile.KEY_DESIGN)); - if (design == null) { - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); - return; - } - - applyTheme(Integer.parseInt(design.getValueAsString())); + public static void applyTheme() { + applyTheme(mPreferences.getInt(SettingsFile.KEY_DESIGN, 0)); } } diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h index 35d99e300..894a7f8b1 100644 --- a/src/android/app/src/main/jni/default_ini.h +++ b/src/android/app/src/main/jni/default_ini.h @@ -7,11 +7,6 @@ namespace DefaultINI { const char* sdl2_config_file = R"( -[Premium] -# What Android design to use -# 0 (default): Light, 1: Dark, 2: System default -design = - [Controls] # The input devices and parameters for each 3DS native input # It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..." diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 6c4575970..34873a6fb 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -36,12 +36,15 @@ Buttons + + Change Theme (Light, Dark) + Theme will update when exiting Settings + Enable CPU JIT Uses the Just-in-Time (JIT) compiler for CPU emulation. When enabled, game performance will be significantly improved. System clock type Set the emulated 3DS clock to either reflect that of your device or start at a simulated date and time. - Change Theme (Light, Dark) System clock starting time override @@ -98,7 +101,7 @@ Clear Default - Saved settings to INI files + Saved settings Saved settings for %1$s Error saving %1$s.ini: %2$s