android: Implement paired settings

Enables and disables editing on settings that rely on other boolean settings.
This commit is contained in:
Charles Lombardo 2023-08-22 23:32:10 -04:00
parent 369d06292f
commit d786d19880
9 changed files with 335 additions and 241 deletions

View file

@ -6,14 +6,17 @@ package org.yuzu.yuzu_emu.features.settings.model
import org.yuzu.yuzu_emu.utils.NativeConfig import org.yuzu.yuzu_emu.utils.NativeConfig
interface AbstractSetting { interface AbstractSetting {
val key: String? val key: String
val category: Settings.Category val category: Settings.Category
val defaultValue: Any val defaultValue: Any
val valueAsString: String val valueAsString: String
get() = "" get() = ""
val isRuntimeModifiable: Boolean val isRuntimeModifiable: Boolean
get() = NativeConfig.getIsRuntimeModifiable(key!!) get() = NativeConfig.getIsRuntimeModifiable(key)
val pairedSettingKey: String
get() = NativeConfig.getPairedSettingKey(key)
fun reset() fun reset()
} }

View file

@ -4,8 +4,15 @@
package org.yuzu.yuzu_emu.features.settings.model.view package org.yuzu.yuzu_emu.features.settings.model.view
import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting 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.ByteSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.LongSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
/** /**
* ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments. * ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments.
@ -37,11 +44,239 @@ abstract class SettingsItem(
const val TYPE_DATETIME_SETTING = 6 const val TYPE_DATETIME_SETTING = 6
const val TYPE_RUNNABLE = 7 const val TYPE_RUNNABLE = 7
const val FASTMEM_COMBINED = "fastmem_combined"
val emptySetting = object : AbstractSetting { val emptySetting = object : AbstractSetting {
override val key: String = "" override val key: String = ""
override val category: Settings.Category = Settings.Category.Ui override val category: Settings.Category = Settings.Category.Ui
override val defaultValue: Any = false override val defaultValue: Any = false
override fun reset() {} override fun reset() {}
} }
// Extension for putting SettingsItems into a hashmap without repeating yourself
fun HashMap<String, SettingsItem>.put(item: SettingsItem) {
put(item.setting.key, item)
}
// List of all general
val settingsItems = HashMap<String, SettingsItem>().apply {
put(
SwitchSetting(
BooleanSetting.RENDERER_USE_SPEED_LIMIT,
R.string.frame_limit_enable,
R.string.frame_limit_enable_description
)
)
put(
SliderSetting(
ShortSetting.RENDERER_SPEED_LIMIT,
R.string.frame_limit_slider,
R.string.frame_limit_slider_description,
1,
200,
"%"
)
)
put(
SingleChoiceSetting(
IntSetting.CPU_ACCURACY,
R.string.cpu_accuracy,
0,
R.array.cpuAccuracyNames,
R.array.cpuAccuracyValues
)
)
put(
SwitchSetting(
BooleanSetting.PICTURE_IN_PICTURE,
R.string.picture_in_picture,
R.string.picture_in_picture_description
)
)
put(
SwitchSetting(
BooleanSetting.USE_DOCKED_MODE,
R.string.use_docked_mode,
R.string.use_docked_mode_description
)
)
put(
SingleChoiceSetting(
IntSetting.REGION_INDEX,
R.string.emulated_region,
0,
R.array.regionNames,
R.array.regionValues
)
)
put(
SingleChoiceSetting(
IntSetting.LANGUAGE_INDEX,
R.string.emulated_language,
0,
R.array.languageNames,
R.array.languageValues
)
)
put(
SwitchSetting(
BooleanSetting.USE_CUSTOM_RTC,
R.string.use_custom_rtc,
R.string.use_custom_rtc_description
)
)
put(DateTimeSetting(LongSetting.CUSTOM_RTC, R.string.set_custom_rtc, 0))
put(
SingleChoiceSetting(
IntSetting.RENDERER_ACCURACY,
R.string.renderer_accuracy,
0,
R.array.rendererAccuracyNames,
R.array.rendererAccuracyValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_RESOLUTION,
R.string.renderer_resolution,
0,
R.array.rendererResolutionNames,
R.array.rendererResolutionValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_VSYNC,
R.string.renderer_vsync,
0,
R.array.rendererVSyncNames,
R.array.rendererVSyncValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_SCALING_FILTER,
R.string.renderer_scaling_filter,
0,
R.array.rendererScalingFilterNames,
R.array.rendererScalingFilterValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_ANTI_ALIASING,
R.string.renderer_anti_aliasing,
0,
R.array.rendererAntiAliasingNames,
R.array.rendererAntiAliasingValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_SCREEN_LAYOUT,
R.string.renderer_screen_layout,
0,
R.array.rendererScreenLayoutNames,
R.array.rendererScreenLayoutValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_ASPECT_RATIO,
R.string.renderer_aspect_ratio,
0,
R.array.rendererAspectRatioNames,
R.array.rendererAspectRatioValues
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE,
R.string.use_disk_shader_cache,
R.string.use_disk_shader_cache_description
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_FORCE_MAX_CLOCK,
R.string.renderer_force_max_clock,
R.string.renderer_force_max_clock_description
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS,
R.string.renderer_asynchronous_shaders,
R.string.renderer_asynchronous_shaders_description
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_REACTIVE_FLUSHING,
R.string.renderer_reactive_flushing,
R.string.renderer_reactive_flushing_description
)
)
put(
SingleChoiceSetting(
IntSetting.AUDIO_OUTPUT_ENGINE,
R.string.audio_output_engine,
0,
R.array.outputEngineEntries,
R.array.outputEngineValues
)
)
put(
SliderSetting(
ByteSetting.AUDIO_VOLUME,
R.string.audio_volume,
R.string.audio_volume_description,
0,
100,
"%"
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_BACKEND,
R.string.renderer_api,
0,
R.array.rendererApiNames,
R.array.rendererApiValues
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_DEBUG,
R.string.renderer_debug,
R.string.renderer_debug_description
)
)
put(
SwitchSetting(
BooleanSetting.CPU_DEBUG_MODE,
R.string.cpu_debug_mode,
R.string.cpu_debug_mode_description
)
)
val fastmem = object : AbstractBooleanSetting {
override val boolean: Boolean
get() =
BooleanSetting.FASTMEM.boolean && BooleanSetting.FASTMEM_EXCLUSIVES.boolean
override fun setBoolean(value: Boolean) {
BooleanSetting.FASTMEM.setBoolean(value)
BooleanSetting.FASTMEM_EXCLUSIVES.setBoolean(value)
}
override val key: String = FASTMEM_COMBINED
override val category = Settings.Category.Cpu
override val isRuntimeModifiable: Boolean = false
override val defaultValue: Boolean = true
override fun reset() = setBoolean(defaultValue)
}
put(SwitchSetting(fastmem, R.string.fastmem, 0))
}
} }
} }

View file

@ -14,7 +14,9 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import com.google.android.material.datepicker.MaterialDatePicker import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.slider.Slider import com.google.android.material.slider.Slider
@ -37,8 +39,8 @@ import org.yuzu.yuzu_emu.model.SettingsViewModel
class SettingsAdapter( class SettingsAdapter(
private val fragment: SettingsFragment, private val fragment: SettingsFragment,
private val context: Context private val context: Context
) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener { ) : ListAdapter<SettingsItem, SettingViewHolder>(AsyncDifferConfig.Builder(DiffCallback()).build()),
private var settings = ArrayList<SettingsItem>() DialogInterface.OnClickListener {
private var clickedItem: SettingsItem? = null private var clickedItem: SettingsItem? = null
private var clickedPosition: Int private var clickedPosition: Int
private var dialog: AlertDialog? = null private var dialog: AlertDialog? = null
@ -94,24 +96,18 @@ class SettingsAdapter(
} }
override fun onBindViewHolder(holder: SettingViewHolder, position: Int) { override fun onBindViewHolder(holder: SettingViewHolder, position: Int) {
holder.bind(getItem(position)) holder.bind(currentList[position])
} }
private fun getItem(position: Int): SettingsItem = settings[position] override fun getItemCount(): Int = currentList.size
override fun getItemCount(): Int = settings.size
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return getItem(position).type return currentList[position].type
} }
fun setSettingsList(settings: ArrayList<SettingsItem>) { fun onBooleanClick(item: SwitchSetting, checked: Boolean) {
this.settings = settings
notifyDataSetChanged()
}
fun onBooleanClick(item: SwitchSetting, position: Int, checked: Boolean) {
item.checked = checked item.checked = checked
settingsViewModel.setShouldReloadSettingsList(true)
settingsViewModel.shouldSave = true settingsViewModel.shouldSave = true
} }
@ -338,4 +334,14 @@ class SettingsAdapter(
} }
return -1 return -1
} }
private class DiffCallback : DiffUtil.ItemCallback<SettingsItem>() {
override fun areItemsTheSame(oldItem: SettingsItem, newItem: SettingsItem): Boolean {
return oldItem.setting.key == newItem.setting.key
}
override fun areContentsTheSame(oldItem: SettingsItem, newItem: SettingsItem): Boolean {
return oldItem.setting.key == newItem.setting.key
}
}
} }

View file

@ -77,6 +77,13 @@ class SettingsFragment : Fragment() {
if (it.isNotEmpty()) binding.toolbarSettingsLayout.title = it if (it.isNotEmpty()) binding.toolbarSettingsLayout.title = it
} }
settingsViewModel.shouldReloadSettingsList.observe(viewLifecycleOwner) {
if (it) {
settingsViewModel.setShouldReloadSettingsList(false)
presenter.loadSettingsList()
}
}
presenter.onViewCreated() presenter.onViewCreated()
setInsets() setInsets()

View file

@ -22,6 +22,7 @@ import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.model.view.* import org.yuzu.yuzu_emu.features.settings.model.view.*
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
import org.yuzu.yuzu_emu.model.SettingsViewModel import org.yuzu.yuzu_emu.model.SettingsViewModel
import org.yuzu.yuzu_emu.utils.NativeConfig
class SettingsFragmentPresenter( class SettingsFragmentPresenter(
private val settingsViewModel: SettingsViewModel, private val settingsViewModel: SettingsViewModel,
@ -36,11 +37,22 @@ class SettingsFragmentPresenter(
private val context: Context get() = YuzuApplication.appContext private val context: Context get() = YuzuApplication.appContext
// Extension for populating settings list based on paired settings
fun ArrayList<SettingsItem>.add(key: String) {
val item = SettingsItem.settingsItems[key]!!
val pairedSettingKey = item.setting.pairedSettingKey
if (pairedSettingKey.isNotEmpty()) {
val pairedSettingValue = NativeConfig.getBoolean(pairedSettingKey, false)
if (!pairedSettingValue) return
}
add(item)
}
fun onViewCreated() { fun onViewCreated() {
loadSettingsList() loadSettingsList()
} }
private fun loadSettingsList() { fun loadSettingsList() {
if (!TextUtils.isEmpty(gameId)) { if (!TextUtils.isEmpty(gameId)) {
settingsViewModel.setToolbarTitle( settingsViewModel.setToolbarTitle(
context.getString( context.getString(
@ -70,7 +82,7 @@ class SettingsFragmentPresenter(
} }
} }
settingsList = sl settingsList = sl
adapter.setSettingsList(settingsList) adapter.submitList(settingsList)
} }
private fun addConfigSettings(sl: ArrayList<SettingsItem>) { private fun addConfigSettings(sl: ArrayList<SettingsItem>) {
@ -92,200 +104,46 @@ class SettingsFragmentPresenter(
private fun addGeneralSettings(sl: ArrayList<SettingsItem>) { private fun addGeneralSettings(sl: ArrayList<SettingsItem>) {
settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_general)) settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_general))
sl.apply { sl.apply {
add( add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key)
SwitchSetting( add(ShortSetting.RENDERER_SPEED_LIMIT.key)
BooleanSetting.RENDERER_USE_SPEED_LIMIT, add(IntSetting.CPU_ACCURACY.key)
R.string.frame_limit_enable, add(BooleanSetting.PICTURE_IN_PICTURE.key)
R.string.frame_limit_enable_description
)
)
add(
SliderSetting(
ShortSetting.RENDERER_SPEED_LIMIT,
R.string.frame_limit_slider,
R.string.frame_limit_slider_description,
1,
200,
"%"
)
)
add(
SingleChoiceSetting(
IntSetting.CPU_ACCURACY,
R.string.cpu_accuracy,
0,
R.array.cpuAccuracyNames,
R.array.cpuAccuracyValues
)
)
add(
SwitchSetting(
BooleanSetting.PICTURE_IN_PICTURE,
R.string.picture_in_picture,
R.string.picture_in_picture_description
)
)
} }
} }
private fun addSystemSettings(sl: ArrayList<SettingsItem>) { private fun addSystemSettings(sl: ArrayList<SettingsItem>) {
settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_system)) settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_system))
sl.apply { sl.apply {
add( add(BooleanSetting.USE_DOCKED_MODE.key)
SwitchSetting( add(IntSetting.REGION_INDEX.key)
BooleanSetting.USE_DOCKED_MODE, add(IntSetting.LANGUAGE_INDEX.key)
R.string.use_docked_mode, add(BooleanSetting.USE_CUSTOM_RTC.key)
R.string.use_docked_mode_description add(LongSetting.CUSTOM_RTC.key)
)
)
add(
SingleChoiceSetting(
IntSetting.REGION_INDEX,
R.string.emulated_region,
0,
R.array.regionNames,
R.array.regionValues
)
)
add(
SingleChoiceSetting(
IntSetting.LANGUAGE_INDEX,
R.string.emulated_language,
0,
R.array.languageNames,
R.array.languageValues
)
)
add(
SwitchSetting(
BooleanSetting.USE_CUSTOM_RTC,
R.string.use_custom_rtc,
R.string.use_custom_rtc_description
)
)
add(DateTimeSetting(LongSetting.CUSTOM_RTC, R.string.set_custom_rtc, 0))
} }
} }
private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) { private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_graphics)) settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_graphics))
sl.apply { sl.apply {
add( add(IntSetting.RENDERER_ACCURACY.key)
SingleChoiceSetting( add(IntSetting.RENDERER_RESOLUTION.key)
IntSetting.RENDERER_ACCURACY, add(IntSetting.RENDERER_VSYNC.key)
R.string.renderer_accuracy, add(IntSetting.RENDERER_SCALING_FILTER.key)
0, add(IntSetting.RENDERER_ANTI_ALIASING.key)
R.array.rendererAccuracyNames, add(IntSetting.RENDERER_SCREEN_LAYOUT.key)
R.array.rendererAccuracyValues add(IntSetting.RENDERER_ASPECT_RATIO.key)
) add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
) add(BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key)
add( add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
SingleChoiceSetting( add(BooleanSetting.RENDERER_REACTIVE_FLUSHING.key)
IntSetting.RENDERER_RESOLUTION,
R.string.renderer_resolution,
0,
R.array.rendererResolutionNames,
R.array.rendererResolutionValues
)
)
add(
SingleChoiceSetting(
IntSetting.RENDERER_VSYNC,
R.string.renderer_vsync,
0,
R.array.rendererVSyncNames,
R.array.rendererVSyncValues
)
)
add(
SingleChoiceSetting(
IntSetting.RENDERER_SCALING_FILTER,
R.string.renderer_scaling_filter,
0,
R.array.rendererScalingFilterNames,
R.array.rendererScalingFilterValues
)
)
add(
SingleChoiceSetting(
IntSetting.RENDERER_ANTI_ALIASING,
R.string.renderer_anti_aliasing,
0,
R.array.rendererAntiAliasingNames,
R.array.rendererAntiAliasingValues
)
)
add(
SingleChoiceSetting(
IntSetting.RENDERER_SCREEN_LAYOUT,
R.string.renderer_screen_layout,
0,
R.array.rendererScreenLayoutNames,
R.array.rendererScreenLayoutValues
)
)
add(
SingleChoiceSetting(
IntSetting.RENDERER_ASPECT_RATIO,
R.string.renderer_aspect_ratio,
0,
R.array.rendererAspectRatioNames,
R.array.rendererAspectRatioValues
)
)
add(
SwitchSetting(
BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE,
R.string.use_disk_shader_cache,
R.string.use_disk_shader_cache_description
)
)
add(
SwitchSetting(
BooleanSetting.RENDERER_FORCE_MAX_CLOCK,
R.string.renderer_force_max_clock,
R.string.renderer_force_max_clock_description
)
)
add(
SwitchSetting(
BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS,
R.string.renderer_asynchronous_shaders,
R.string.renderer_asynchronous_shaders_description
)
)
add(
SwitchSetting(
BooleanSetting.RENDERER_REACTIVE_FLUSHING,
R.string.renderer_reactive_flushing,
R.string.renderer_reactive_flushing_description
)
)
} }
} }
private fun addAudioSettings(sl: ArrayList<SettingsItem>) { private fun addAudioSettings(sl: ArrayList<SettingsItem>) {
settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_audio)) settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_audio))
sl.apply { sl.apply {
add( add(IntSetting.AUDIO_OUTPUT_ENGINE.key)
SingleChoiceSetting( add(ByteSetting.AUDIO_VOLUME.key)
IntSetting.AUDIO_OUTPUT_ENGINE,
R.string.audio_output_engine,
0,
R.array.outputEngineEntries,
R.array.outputEngineValues
)
)
add(
SliderSetting(
ByteSetting.AUDIO_VOLUME,
R.string.audio_volume,
R.string.audio_volume_description,
0,
100,
"%"
)
)
} }
} }
@ -303,7 +161,7 @@ class SettingsFragmentPresenter(
settingsViewModel.setShouldRecreate(true) settingsViewModel.setShouldRecreate(true)
} }
override val key: String? = null override val key: String = Settings.PREF_THEME
override val category = Settings.Category.UiGeneral override val category = Settings.Category.UiGeneral
override val isRuntimeModifiable: Boolean = false override val isRuntimeModifiable: Boolean = false
override val defaultValue: Int = 0 override val defaultValue: Int = 0
@ -347,7 +205,7 @@ class SettingsFragmentPresenter(
settingsViewModel.setShouldRecreate(true) settingsViewModel.setShouldRecreate(true)
} }
override val key: String? = null override val key: String = Settings.PREF_THEME_MODE
override val category = Settings.Category.UiGeneral override val category = Settings.Category.UiGeneral
override val isRuntimeModifiable: Boolean = false override val isRuntimeModifiable: Boolean = false
override val defaultValue: Int = -1 override val defaultValue: Int = -1
@ -380,7 +238,7 @@ class SettingsFragmentPresenter(
settingsViewModel.setShouldRecreate(true) settingsViewModel.setShouldRecreate(true)
} }
override val key: String? = null override val key: String = Settings.PREF_BLACK_BACKGROUNDS
override val category = Settings.Category.UiGeneral override val category = Settings.Category.UiGeneral
override val isRuntimeModifiable: Boolean = false override val isRuntimeModifiable: Boolean = false
override val defaultValue: Boolean = false override val defaultValue: Boolean = false
@ -406,49 +264,12 @@ class SettingsFragmentPresenter(
settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_debug)) settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_debug))
sl.apply { sl.apply {
add(HeaderSetting(R.string.gpu)) add(HeaderSetting(R.string.gpu))
add( add(IntSetting.RENDERER_BACKEND.key)
SingleChoiceSetting( add(BooleanSetting.RENDERER_DEBUG.key)
IntSetting.RENDERER_BACKEND,
R.string.renderer_api,
0,
R.array.rendererApiNames,
R.array.rendererApiValues
)
)
add(
SwitchSetting(
BooleanSetting.RENDERER_DEBUG,
R.string.renderer_debug,
R.string.renderer_debug_description
)
)
add(HeaderSetting(R.string.cpu)) add(HeaderSetting(R.string.cpu))
add( add(BooleanSetting.CPU_DEBUG_MODE.key)
SwitchSetting( add(SettingsItem.FASTMEM_COMBINED)
BooleanSetting.CPU_DEBUG_MODE,
R.string.cpu_debug_mode,
R.string.cpu_debug_mode_description
)
)
val fastmem = object : AbstractBooleanSetting {
override val boolean: Boolean
get() =
BooleanSetting.FASTMEM.boolean && BooleanSetting.FASTMEM_EXCLUSIVES.boolean
override fun setBoolean(value: Boolean) {
BooleanSetting.FASTMEM.setBoolean(value)
BooleanSetting.FASTMEM_EXCLUSIVES.setBoolean(value)
}
override val key: String? = null
override val category = Settings.Category.Cpu
override val isRuntimeModifiable: Boolean = false
override val defaultValue: Boolean = true
override fun reset() = setBoolean(defaultValue)
}
add(SwitchSetting(fastmem, R.string.fastmem, 0))
} }
} }
} }

View file

@ -29,7 +29,7 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
binding.switchWidget.setOnCheckedChangeListener(null) binding.switchWidget.setOnCheckedChangeListener(null)
binding.switchWidget.isChecked = setting.checked binding.switchWidget.isChecked = setting.checked
binding.switchWidget.setOnCheckedChangeListener { _: CompoundButton, _: Boolean -> binding.switchWidget.setOnCheckedChangeListener { _: CompoundButton, _: Boolean ->
adapter.onBooleanClick(item, bindingAdapterPosition, binding.switchWidget.isChecked) adapter.onBooleanClick(item, binding.switchWidget.isChecked)
} }
setStyle(setting.isEditable, binding) setStyle(setting.isEditable, binding)
@ -43,7 +43,7 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
override fun onLongClick(clicked: View): Boolean { override fun onLongClick(clicked: View): Boolean {
if (setting.isEditable) { if (setting.isEditable) {
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition) return adapter.onLongClick(setting.setting, bindingAdapterPosition)
} }
return false return false
} }

View file

@ -24,6 +24,9 @@ class SettingsViewModel : ViewModel() {
private val _shouldShowResetSettingsDialog = MutableLiveData(false) private val _shouldShowResetSettingsDialog = MutableLiveData(false)
val shouldShowResetSettingsDialog: LiveData<Boolean> get() = _shouldShowResetSettingsDialog val shouldShowResetSettingsDialog: LiveData<Boolean> get() = _shouldShowResetSettingsDialog
private val _shouldReloadSettingsList = MutableLiveData(false)
val shouldReloadSettingsList: LiveData<Boolean> get() = _shouldReloadSettingsList
fun setToolbarTitle(value: String) { fun setToolbarTitle(value: String) {
_toolbarTitle.value = value _toolbarTitle.value = value
} }
@ -40,6 +43,10 @@ class SettingsViewModel : ViewModel() {
_shouldShowResetSettingsDialog.value = value _shouldShowResetSettingsDialog.value = value
} }
fun setShouldReloadSettingsList(value: Boolean) {
_shouldReloadSettingsList.value = value
}
fun clear() { fun clear() {
game = null game = null
shouldSave = false shouldSave = false

View file

@ -28,4 +28,6 @@ object NativeConfig {
external fun getIsRuntimeModifiable(key: String): Boolean external fun getIsRuntimeModifiable(key: String): Boolean
external fun getConfigHeader(category: Int): String external fun getConfigHeader(category: Int): String
external fun getPairedSettingKey(key: String): String
} }

View file

@ -216,9 +216,22 @@ jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getIsRuntimeModifiable(JNIEn
} }
jstring Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getConfigHeader(JNIEnv* env, jobject obj, jstring Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getConfigHeader(JNIEnv* env, jobject obj,
jint jcategory) { jint jcategory) {
auto category = static_cast<Settings::Category>(jcategory); auto category = static_cast<Settings::Category>(jcategory);
return ToJString(env, Settings::TranslateCategory(category)); return ToJString(env, Settings::TranslateCategory(category));
} }
jstring Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getPairedSettingKey(JNIEnv* env, jobject obj,
jstring jkey) {
auto setting = getSetting<std::string>(env, jkey);
if (setting == nullptr) {
return ToJString(env, "");
}
if (setting->PairedSetting() == nullptr) {
return ToJString(env, "");
}
return ToJString(env, setting->PairedSetting()->GetLabel());
}
} // extern "C" } // extern "C"