android: Button to reset all settings
This commit is contained in:
		| @@ -32,5 +32,7 @@ enum class BooleanSetting( | ||||
|  | ||||
|         fun from(key: String): BooleanSetting? = | ||||
|             BooleanSetting.values().firstOrNull { it.key == key } | ||||
|  | ||||
|         fun clear() = BooleanSetting.values().forEach { it.boolean = it.defaultValue } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -30,5 +30,7 @@ enum class FloatSetting( | ||||
|         private val NOT_RUNTIME_EDITABLE = emptyList<FloatSetting>() | ||||
|  | ||||
|         fun from(key: String): FloatSetting? = FloatSetting.values().firstOrNull { it.key == key } | ||||
|  | ||||
|         fun clear() = FloatSetting.values().forEach { it.float = it.defaultValue } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -119,5 +119,7 @@ enum class IntSetting( | ||||
|         ) | ||||
|  | ||||
|         fun from(key: String): IntSetting? = IntSetting.values().firstOrNull { it.key == key } | ||||
|  | ||||
|         fun clear() = IntSetting.values().forEach { it.int = it.defaultValue } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| package org.yuzu.yuzu_emu.features.settings.model | ||||
|  | ||||
| import androidx.lifecycle.ViewModel | ||||
|   | ||||
| @@ -31,5 +31,7 @@ enum class StringSetting( | ||||
|         ) | ||||
|  | ||||
|         fun from(key: String): StringSetting? = StringSetting.values().firstOrNull { it.key == key } | ||||
|  | ||||
|         fun clear() = StringSetting.values().forEach { it.string = it.defaultValue } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting | ||||
| class HeaderSetting( | ||||
|     setting: AbstractSetting?, | ||||
|     titleId: Int, | ||||
|     descriptionId: Int? | ||||
|     descriptionId: Int | ||||
| ) : SettingsItem(setting, titleId, descriptionId) { | ||||
|     override val type = TYPE_HEADER | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,12 @@ | ||||
| // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| package org.yuzu.yuzu_emu.features.settings.model.view | ||||
|  | ||||
| class RunnableSetting( | ||||
|     titleId: Int, | ||||
|     descriptionId: Int, | ||||
|     val runnable: () -> Unit | ||||
| ) : SettingsItem(null, titleId, descriptionId) { | ||||
|     override val type = TYPE_RUNNABLE | ||||
| } | ||||
| @@ -16,7 +16,7 @@ import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting | ||||
| abstract class SettingsItem( | ||||
|     var setting: AbstractSetting?, | ||||
|     val nameId: Int, | ||||
|     val descriptionId: Int? | ||||
|     val descriptionId: Int | ||||
| ) { | ||||
|     abstract val type: Int | ||||
|  | ||||
| @@ -34,5 +34,6 @@ abstract class SettingsItem( | ||||
|         const val TYPE_SUBMENU = 4 | ||||
|         const val TYPE_STRING_SINGLE_CHOICE = 5 | ||||
|         const val TYPE_DATETIME_SETTING = 6 | ||||
|         const val TYPE_RUNNABLE = 7 | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,9 +6,6 @@ package org.yuzu.yuzu_emu.features.settings.model.view | ||||
| import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.IntSetting | ||||
| import org.yuzu.yuzu_emu.utils.Log | ||||
|  | ||||
| class SwitchSetting( | ||||
|     setting: AbstractSetting, | ||||
|   | ||||
| @@ -8,7 +8,6 @@ import android.content.Intent | ||||
| import android.os.Bundle | ||||
| import android.view.Menu | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.Toast | ||||
| import androidx.activity.viewModels | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| @@ -21,9 +20,15 @@ import com.google.android.material.color.MaterialColors | ||||
| import org.yuzu.yuzu_emu.NativeLibrary | ||||
| import org.yuzu.yuzu_emu.R | ||||
| import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding | ||||
| import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.FloatSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.IntSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.Settings | ||||
| import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel | ||||
| import org.yuzu.yuzu_emu.features.settings.model.StringSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | ||||
| import org.yuzu.yuzu_emu.utils.* | ||||
| import java.io.IOException | ||||
|  | ||||
| class SettingsActivity : AppCompatActivity(), SettingsActivityView { | ||||
|     private val presenter = SettingsActivityPresenter(this) | ||||
| @@ -165,6 +170,26 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { | ||||
|         presenter.onSettingChanged() | ||||
|     } | ||||
|  | ||||
|     fun onSettingsReset() { | ||||
|         // Prevents saving to a non-existent settings file | ||||
|         presenter.onSettingsReset() | ||||
|  | ||||
|         // Reset the static memory representation of each setting | ||||
|         BooleanSetting.clear() | ||||
|         FloatSetting.clear() | ||||
|         IntSetting.clear() | ||||
|         StringSetting.clear() | ||||
|  | ||||
|         // Delete settings file because the user may have changed values that do not exist in the UI | ||||
|         val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG) | ||||
|         if (!settingsFile.delete()) { | ||||
|             throw IOException("Failed to delete $settingsFile") | ||||
|         } | ||||
|  | ||||
|         showToastMessage(getString(R.string.settings_reset), true) | ||||
|         finish() | ||||
|     } | ||||
|  | ||||
|     private val settingsFragment: SettingsFragment? | ||||
|         get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as SettingsFragment? | ||||
|  | ||||
|   | ||||
| @@ -70,6 +70,10 @@ class SettingsActivityPresenter(private val activityView: SettingsActivityView) | ||||
|         shouldSave = true | ||||
|     } | ||||
|  | ||||
|     fun onSettingsReset() { | ||||
|         shouldSave = false | ||||
|     } | ||||
|  | ||||
|     fun saveState(outState: Bundle) { | ||||
|         outState.putBoolean(KEY_SHOULD_SAVE, shouldSave) | ||||
|     } | ||||
|   | ||||
| @@ -79,6 +79,10 @@ class SettingsAdapter( | ||||
|                 DateTimeViewHolder(ListItemSettingBinding.inflate(inflater), this) | ||||
|             } | ||||
|  | ||||
|             SettingsItem.TYPE_RUNNABLE -> { | ||||
|                 RunnableViewHolder(ListItemSettingBinding.inflate(inflater), this) | ||||
|             } | ||||
|  | ||||
|             else -> { | ||||
|                 // TODO: Create an error view since we can't return null now | ||||
|                 HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this) | ||||
|   | ||||
| @@ -6,8 +6,8 @@ package org.yuzu.yuzu_emu.features.settings.ui | ||||
| import android.content.SharedPreferences | ||||
| import android.os.Build | ||||
| import android.text.TextUtils | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.preference.PreferenceManager | ||||
| import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||||
| import org.yuzu.yuzu_emu.R | ||||
| import org.yuzu.yuzu_emu.YuzuApplication | ||||
| import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting | ||||
| @@ -26,7 +26,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|     private lateinit var gameId: String | ||||
|     private var settingsList: ArrayList<SettingsItem>? = null | ||||
|  | ||||
|     private val settingsActivity get() = fragmentView.activityView as AppCompatActivity | ||||
|     private val settingsActivity get() = fragmentView.activityView as SettingsActivity | ||||
|     private val settings get() = fragmentView.activityView!!.settings | ||||
|  | ||||
|     private lateinit var preferences: SharedPreferences | ||||
| @@ -111,6 +111,12 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|                     Settings.SECTION_AUDIO | ||||
|                 ) | ||||
|             ) | ||||
|             add( | ||||
|                 RunnableSetting( | ||||
|                     R.string.reset_to_default, | ||||
|                     0 | ||||
|                 ) { resetSettings() } | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -338,7 +344,9 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|                 override var int: Int | ||||
|                     get() = preferences.getInt(Settings.PREF_THEME, 0) | ||||
|                     set(value) { | ||||
|                         preferences.edit().putInt(Settings.PREF_THEME, value).apply() | ||||
|                         preferences.edit() | ||||
|                             .putInt(Settings.PREF_THEME, value) | ||||
|                             .apply() | ||||
|                         settingsActivity.recreate() | ||||
|                     } | ||||
|                 override val key: String? = null | ||||
| @@ -375,7 +383,9 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|                 override var int: Int | ||||
|                     get() = preferences.getInt(Settings.PREF_THEME_MODE, -1) | ||||
|                     set(value) { | ||||
|                         preferences.edit().putInt(Settings.PREF_THEME_MODE, value).apply() | ||||
|                         preferences.edit() | ||||
|                             .putInt(Settings.PREF_THEME_MODE, value) | ||||
|                             .apply() | ||||
|                         ThemeHelper.setThemeMode(settingsActivity) | ||||
|                     } | ||||
|                 override val key: String? = null | ||||
| @@ -400,14 +410,17 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|                 override var boolean: Boolean | ||||
|                     get() = preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false) | ||||
|                     set(value) { | ||||
|                         preferences.edit().putBoolean(Settings.PREF_BLACK_BACKGROUNDS, value).apply() | ||||
|                         preferences.edit() | ||||
|                             .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, value) | ||||
|                             .apply() | ||||
|                         settingsActivity.recreate() | ||||
|                     } | ||||
|                 override val key: String? = null | ||||
|                 override val section: String? = null | ||||
|                 override val isRuntimeEditable: Boolean = false | ||||
|                 override val valueAsString: String | ||||
|                     get() = preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false).toString() | ||||
|                     get() = preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false) | ||||
|                         .toString() | ||||
|                 override val defaultValue: Any = false | ||||
|             } | ||||
|  | ||||
| @@ -420,4 +433,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun resetSettings() { | ||||
|         MaterialAlertDialogBuilder(settingsActivity) | ||||
|             .setTitle(R.string.reset_all_settings) | ||||
|             .setMessage(R.string.reset_all_settings_description) | ||||
|             .setPositiveButton(android.R.string.ok) { _, _ -> | ||||
|                 settingsActivity.onSettingsReset() | ||||
|             } | ||||
|             .setNegativeButton(android.R.string.cancel, null) | ||||
|             .show() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -21,7 +21,7 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA | ||||
|     override fun bind(item: SettingsItem) { | ||||
|         setting = item as DateTimeSetting | ||||
|         binding.textSettingName.setText(item.nameId) | ||||
|         if (item.descriptionId!! > 0) { | ||||
|         if (item.descriptionId != 0) { | ||||
|             binding.textSettingDescription.setText(item.descriptionId) | ||||
|             binding.textSettingDescription.visibility = View.VISIBLE | ||||
|         } else { | ||||
|   | ||||
| @@ -0,0 +1,35 @@ | ||||
| // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| package org.yuzu.yuzu_emu.features.settings.ui.viewholder | ||||
|  | ||||
| import android.view.View | ||||
| import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding | ||||
| import org.yuzu.yuzu_emu.features.settings.model.view.RunnableSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem | ||||
| import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter | ||||
|  | ||||
| class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : | ||||
|     SettingViewHolder(binding.root, adapter) { | ||||
|     private lateinit var setting: RunnableSetting | ||||
|  | ||||
|     override fun bind(item: SettingsItem) { | ||||
|         setting = item as RunnableSetting | ||||
|         binding.textSettingName.setText(item.nameId) | ||||
|         if (item.descriptionId != 0) { | ||||
|             binding.textSettingDescription.setText(item.descriptionId) | ||||
|             binding.textSettingDescription.visibility = View.VISIBLE | ||||
|         } else { | ||||
|             binding.textSettingDescription.visibility = View.GONE | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun onClick(clicked: View) { | ||||
|         setting.runnable.invoke() | ||||
|     } | ||||
|  | ||||
|     override fun onLongClick(clicked: View): Boolean { | ||||
|         // no-op | ||||
|         return true | ||||
|     } | ||||
| } | ||||
| @@ -18,7 +18,7 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti | ||||
|         setting = item | ||||
|         binding.textSettingName.setText(item.nameId) | ||||
|         binding.textSettingDescription.visibility = View.VISIBLE | ||||
|         if (item.descriptionId!! > 0) { | ||||
|         if (item.descriptionId != 0) { | ||||
|             binding.textSettingDescription.setText(item.descriptionId) | ||||
|         } else if (item is SingleChoiceSetting) { | ||||
|             val resMgr = binding.textSettingDescription.context.resources | ||||
|   | ||||
| @@ -16,7 +16,7 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda | ||||
|     override fun bind(item: SettingsItem) { | ||||
|         setting = item as SliderSetting | ||||
|         binding.textSettingName.setText(item.nameId) | ||||
|         if (item.descriptionId!! > 0) { | ||||
|         if (item.descriptionId != 0) { | ||||
|             binding.textSettingDescription.setText(item.descriptionId) | ||||
|             binding.textSettingDescription.visibility = View.VISIBLE | ||||
|         } else { | ||||
|   | ||||
| @@ -16,7 +16,7 @@ class SubmenuViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAd | ||||
|     override fun bind(item: SettingsItem) { | ||||
|         this.item = item as SubmenuSetting | ||||
|         binding.textSettingName.setText(item.nameId) | ||||
|         if (item.descriptionId!! > 0) { | ||||
|         if (item.descriptionId != 0) { | ||||
|             binding.textSettingDescription.setText(item.descriptionId) | ||||
|             binding.textSettingDescription.visibility = View.VISIBLE | ||||
|         } else { | ||||
|   | ||||
| @@ -18,7 +18,7 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter | ||||
|     override fun bind(item: SettingsItem) { | ||||
|         setting = item as SwitchSetting | ||||
|         binding.textSettingName.setText(item.nameId) | ||||
|         if (item.descriptionId!! > 0) { | ||||
|         if (item.descriptionId != 0) { | ||||
|             binding.textSettingDescription.setText(item.descriptionId) | ||||
|             binding.textSettingDescription.visibility = View.VISIBLE | ||||
|         } else { | ||||
|   | ||||
| @@ -22,7 +22,7 @@ import java.util.* | ||||
| object SettingsFile { | ||||
|     const val FILE_NAME_CONFIG = "config" | ||||
|  | ||||
|     private val sectionsMap = BiMap<String?, String?>() | ||||
|     private var sectionsMap = BiMap<String?, String?>() | ||||
|  | ||||
|     /** | ||||
|      * Reads a given .ini file from disk and returns it as a HashMap of Settings, themselves | ||||
| @@ -154,7 +154,7 @@ object SettingsFile { | ||||
|         } else generalSectionName | ||||
|     } | ||||
|  | ||||
|     private fun getSettingsFile(fileName: String): File { | ||||
|     fun getSettingsFile(fileName: String): File { | ||||
|         return File( | ||||
|             DirectoryInitialization.userDirectory + "/config/" + fileName + ".ini" | ||||
|         ) | ||||
| @@ -182,13 +182,11 @@ object SettingsFile { | ||||
|     private fun settingFromLine(line: String): AbstractSetting? { | ||||
|         val splitLine = line.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() | ||||
|         if (splitLine.size != 2) { | ||||
|             Log.warning("Skipping invalid config line \"$line\"") | ||||
|             return null | ||||
|         } | ||||
|         val key = splitLine[0].trim { it <= ' ' } | ||||
|         val value = splitLine[1].trim { it <= ' ' } | ||||
|         if (value.isEmpty()) { | ||||
|             Log.warning("Skipping null value in config line \"$line\"") | ||||
|             return null | ||||
|         } | ||||
|  | ||||
| @@ -216,7 +214,7 @@ object SettingsFile { | ||||
|             return stringSetting | ||||
|         } | ||||
|  | ||||
|         return StringSetting.from(key) | ||||
|         return null | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -143,8 +143,12 @@ | ||||
|     <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> | ||||
|     <string name="loading">Loading...</string> | ||||
|     <string name="loading">Loading…</string> | ||||
|     <string name="reset_setting_confirmation">Do you want to reset this setting back to its default value?</string> | ||||
|     <string name="reset_to_default">Reset to default</string> | ||||
|     <string name="reset_all_settings">Reset all settings?</string> | ||||
|     <string name="reset_all_settings_description">All Advanced Settings will be reset to their default configuration. This can not be undone.</string> | ||||
|     <string name="settings_reset">Settings reset</string> | ||||
|  | ||||
|     <!-- GPU driver installation --> | ||||
|     <string name="select_gpu_driver">Select GPU driver</string> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user