android: settings: Store theme setting in shared preferences.

- Fixes some jankieness.
This commit is contained in:
bunnei 2020-04-24 20:14:52 -04:00
parent 2868ba6998
commit 9429e2a854
8 changed files with 170 additions and 40 deletions

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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<SettingViewHolde
mView.onSettingChanged();
}
public void onSingleChoiceClick(PremiumSingleChoiceSetting item) {
mClickedItem = item;
int value = getSelectionForSingleChoiceValue(item);
AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity());
builder.setTitle(item.getNameId());
builder.setSingleChoiceItems(item.getChoicesId(), value, this);
mDialog = builder.show();
}
public void onSingleChoiceClick(SingleChoiceSetting item) {
mClickedItem = item;
@ -169,6 +183,19 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
MainActivity.invokePremiumBilling(() -> 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<SettingViewHolde
mView.putSetting(setting);
}
closeDialog();
} else if (mClickedItem instanceof PremiumSingleChoiceSetting) {
PremiumSingleChoiceSetting scSetting = (PremiumSingleChoiceSetting) mClickedItem;
int value = getValueForSingleChoiceSelection(scSetting, which);
if (scSetting.getSelectedValue() != value) {
//mView.onSettingChanged();
}
// Get the backing Setting, which may be null (if for example it was missing from the file)
scSetting.setSelectedValue(value);
closeDialog();
} else if (mClickedItem instanceof StringSingleChoiceSetting) {
StringSingleChoiceSetting scSetting = (StringSingleChoiceSetting) mClickedItem;
@ -393,6 +432,17 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
}
}
private int getValueForSingleChoiceSelection(PremiumSingleChoiceSetting item, int which) {
int valuesId = item.getValuesId();
if (valuesId > 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<SettingViewHolde
return -1;
}
private int getSelectionForSingleChoiceValue(PremiumSingleChoiceSetting item) {
int value = item.getSelectedValue();
int valuesId = item.getValuesId();
if (valuesId > 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;
}
}

View File

@ -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<SettingsItem> 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));
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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]..."

View File

@ -36,12 +36,15 @@
<!-- Generic buttons (Shared with lots of stuff) -->
<string name="generic_buttons">Buttons</string>
<!-- Premium settings strings -->
<string name="design">Change Theme (Light, Dark)</string>
<string name="design_updated">Theme will update when exiting Settings</string>
<!-- Core settings strings -->
<string name="cpu_jit">Enable CPU JIT</string>
<string name="cpu_jit_description">Uses the Just-in-Time (JIT) compiler for CPU emulation. When enabled, game performance will be significantly improved.</string>
<string name="init_clock">System clock type</string>
<string name="init_clock_description">Set the emulated 3DS clock to either reflect that of your device or start at a simulated date and time.</string>
<string name="design">Change Theme (Light, Dark)</string>
<!-- System settings strings -->
<string name="init_time">System clock starting time override</string>
@ -98,7 +101,7 @@
<!-- Miscellaneous -->
<string name="clear">Clear</string>
<string name="slider_default">Default</string>
<string name="ini_saved">Saved settings to INI files</string>
<string name="ini_saved">Saved settings</string>
<string name="gameid_saved">Saved settings for %1$s</string>
<string name="error_saving">Error saving %1$s.ini: %2$s</string>