Răsfoiți Sursa

android: Button to reset all settings

Charles Lombardo 3 ani în urmă
părinte
comite
ee57aa83a4
21 a modificat fișierele cu 138 adăugiri și 23 ștergeri
  1. 2 0
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt
  2. 2 0
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/FloatSetting.kt
  3. 2 0
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt
  4. 3 0
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingsViewModel.kt
  5. 2 0
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt
  6. 1 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/HeaderSetting.kt
  7. 12 0
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/RunnableSetting.kt
  8. 2 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
  9. 0 3
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SwitchSetting.kt
  10. 26 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
  11. 4 0
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt
  12. 4 0
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
  13. 30 6
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
  14. 1 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt
  15. 35 0
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/RunnableViewHolder.kt
  16. 1 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt
  17. 1 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt
  18. 1 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SubmenuViewHolder.kt
  19. 1 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt
  20. 3 5
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt
  21. 5 1
      src/android/app/src/main/res/values/strings.xml

+ 2 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt

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

+ 2 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/FloatSetting.kt

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

+ 2 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt

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

+ 3 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingsViewModel.kt

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

+ 2 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt

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

+ 1 - 1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/HeaderSetting.kt

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

+ 12 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/RunnableSetting.kt

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

+ 2 - 1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt

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

+ 0 - 3
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SwitchSetting.kt

@@ -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,

+ 26 - 1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt

@@ -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?
 

+ 4 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt

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

+ 4 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt

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

+ 30 - 6
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt

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

+ 1 - 1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt

@@ -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 {

+ 35 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/RunnableViewHolder.kt

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

+ 1 - 1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt

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

+ 1 - 1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt

@@ -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 {

+ 1 - 1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SubmenuViewHolder.kt

@@ -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 {

+ 1 - 1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt

@@ -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 {

+ 3 - 5
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt

@@ -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
     }
 
     /**

+ 5 - 1
src/android/app/src/main/res/values/strings.xml

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