Merge 8ccedb9bc2cfaef5d1aca8b05c59248feca376ec into 42d77cd720eb42845c2afb77c6d7157e02c8c325

This commit is contained in:
Kleidis 2025-03-13 02:34:57 -03:00 committed by GitHub
commit 51a0d5ce37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 132 additions and 43 deletions

View File

@ -12,7 +12,8 @@ class DateTimeSetting(
titleId: Int,
descriptionId: Int,
val key: String? = null,
private val defaultValue: String? = null
private val defaultValue: String? = null,
override var isEnabled: Boolean = true
) : SettingsItem(setting, titleId, descriptionId) {
override val type = TYPE_DATETIME_SETTING

View File

@ -28,6 +28,8 @@ abstract class SettingsItem(
return setting?.isRuntimeEditable ?: false
}
open var isEnabled: Boolean = true
companion object {
const val TYPE_HEADER = 0
const val TYPE_SWITCH = 1

View File

@ -15,7 +15,8 @@ class SingleChoiceSetting(
val choicesId: Int,
val valuesId: Int,
val key: String? = null,
val defaultValue: Int? = null
val defaultValue: Int? = null,
override var isEnabled: Boolean = true
) : SettingsItem(setting, titleId, descriptionId) {
override val type = TYPE_SINGLE_CHOICE

View File

@ -20,7 +20,8 @@ class SliderSetting(
val max: Int,
val units: String,
val key: String? = null,
val defaultValue: Float? = null
val defaultValue: Float? = null,
override var isEnabled: Boolean = true
) : SettingsItem(setting, titleId, descriptionId) {
override val type = TYPE_SLIDER
val selectedFloat: Float

View File

@ -12,7 +12,8 @@ class StringInputSetting(
titleId: Int,
descriptionId: Int,
val defaultValue: String,
val characterLimit: Int = 0
val characterLimit: Int = 0,
override var isEnabled: Boolean = true
) : SettingsItem(setting, titleId, descriptionId) {
override val type = TYPE_STRING_INPUT

View File

@ -15,7 +15,8 @@ class StringSingleChoiceSetting(
val choices: Array<String>,
val values: Array<String>?,
val key: String? = null,
private val defaultValue: String? = null
private val defaultValue: String? = null,
override var isEnabled: Boolean = true
) : SettingsItem(setting, titleId, descriptionId) {
override val type = TYPE_STRING_SINGLE_CHOICE

View File

@ -13,7 +13,8 @@ class SwitchSetting(
titleId: Int,
descriptionId: Int,
val key: String? = null,
val defaultValue: Any? = null
val defaultValue: Any? = null,
override var isEnabled: Boolean = true
) : SettingsItem(setting, titleId, descriptionId) {
override val type = TYPE_SWITCH

View File

@ -7,7 +7,6 @@ package org.citra.citra_emu.features.settings.ui
import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.graphics.Color
import android.icu.util.Calendar
import android.icu.util.TimeZone
import android.text.Editable
@ -17,11 +16,11 @@ import android.text.TextWatcher
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@ -66,7 +65,6 @@ import org.citra.citra_emu.features.settings.ui.viewholder.SwitchSettingViewHold
import org.citra.citra_emu.fragments.MessageDialogFragment
import org.citra.citra_emu.fragments.MotionBottomSheetDialogFragment
import org.citra.citra_emu.utils.SystemSaveGame
import java.lang.IllegalStateException
import java.lang.NumberFormatException
import java.text.SimpleDateFormat
import kotlin.math.roundToInt
@ -153,15 +151,71 @@ class SettingsAdapter(
return getItem(position)?.type ?: -1
}
fun setSettingsList(settings: ArrayList<SettingsItem>?) {
this.settings = settings ?: arrayListOf()
fun setSettingsList(newSettings: ArrayList<SettingsItem>?) {
if (settings == null) {
settings = newSettings ?: arrayListOf()
notifyDataSetChanged()
return
}
val oldSettings = settings
val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
override fun getOldListSize() = oldSettings?.size ?: 0
override fun getNewListSize() = newSettings?.size ?: 0
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldSettings?.get(oldItemPosition)?.setting
val newItem = newSettings?.get(newItemPosition)?.setting
return oldItem?.key == newItem?.key
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldSettings?.get(oldItemPosition)
val newItem = newSettings?.get(newItemPosition)
if (oldItem == null || newItem == null || oldItem.type != newItem.type) {
return false
}
return when (oldItem.type) {
SettingsItem.TYPE_SLIDER -> {
(oldItem as SliderSetting).isEnabled == (newItem as SliderSetting).isEnabled
}
SettingsItem.TYPE_SWITCH -> {
(oldItem as SwitchSetting).isEnabled == (newItem as SwitchSetting).isEnabled
}
SettingsItem.TYPE_SINGLE_CHOICE -> {
(oldItem as SingleChoiceSetting).isEnabled == (newItem as SingleChoiceSetting).isEnabled
}
SettingsItem.TYPE_DATETIME_SETTING -> {
(oldItem as DateTimeSetting).isEnabled == (newItem as DateTimeSetting).isEnabled
}
SettingsItem.TYPE_STRING_SINGLE_CHOICE -> {
(oldItem as StringSingleChoiceSetting).isEnabled == (newItem as StringSingleChoiceSetting).isEnabled
}
SettingsItem.TYPE_STRING_INPUT -> {
(oldItem as StringInputSetting).isEnabled == (newItem as StringInputSetting).isEnabled
}
else -> {
oldItem == newItem
}
}
}
})
settings = newSettings ?: arrayListOf()
diffResult.dispatchUpdatesTo(this)
}
fun onBooleanClick(item: SwitchSetting, position: Int, checked: Boolean) {
val setting = item.setChecked(checked)
fragmentView.putSetting(setting)
fragmentView.onSettingChanged()
// If statement is required otherwise the app will crash on activity recreate ex. theme settings
if (fragmentView.activityView != null)
// Reload the settings list to update the UI
fragmentView.loadSettingsList()
}
private fun onSingleChoiceClick(item: SingleChoiceSetting) {
@ -247,6 +301,7 @@ class SettingsAdapter(
notifyItemChanged(clickedPosition)
val setting = item.setSelectedValue(rtcString)
fragmentView.putSetting(setting)
fragmentView.loadSettingsList()
clickedItem = null
}
datePicker.show(
@ -402,6 +457,7 @@ class SettingsAdapter(
else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!")
}
fragmentView?.putSetting(setting)
fragmentView.loadSettingsList()
closeDialog()
}
}
@ -425,6 +481,7 @@ class SettingsAdapter(
}
fragmentView?.putSetting(setting)
fragmentView.loadSettingsList()
closeDialog()
}
}
@ -447,6 +504,7 @@ class SettingsAdapter(
fragmentView?.putSetting(setting)
}
}
fragmentView.loadSettingsList()
closeDialog()
}
}
@ -459,6 +517,7 @@ class SettingsAdapter(
}
val setting = it.setSelectedValue(textInputValue ?: "")
fragmentView?.putSetting(setting)
fragmentView.loadSettingsList()
closeDialog()
}
}
@ -488,6 +547,7 @@ class SettingsAdapter(
}
notifyItemChanged(position)
fragmentView.onSettingChanged()
fragmentView.loadSettingsList()
}
.setNegativeButton(android.R.string.cancel, null)
.show()
@ -495,10 +555,19 @@ class SettingsAdapter(
return true
}
fun onClickDisabledSetting() {
MessageDialogFragment.newInstance(
R.string.setting_not_editable,
fun onClickDisabledSetting(isRuntimeDisabled: Boolean) {
val titleId = if (isRuntimeDisabled)
R.string.setting_not_editable
else
R.string.setting_disabled
val messageId = if (isRuntimeDisabled)
R.string.setting_not_editable_description
else
R.string.setting_disabled_description
MessageDialogFragment.newInstance(
titleId,
messageId
).show((fragmentView as SettingsFragment).childFragmentManager, MessageDialogFragment.TAG)
}

View File

@ -47,7 +47,7 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
binding.textSettingValue.text = dateFormatter.format(zonedTime)
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
binding.textSettingName.alpha = 1f
binding.textSettingDescription.alpha = 1f
binding.textSettingValue.alpha = 1f
@ -59,18 +59,18 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
}
override fun onClick(clicked: View) {
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
adapter.onDateTimeClick(setting, bindingAdapterPosition)
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
}
override fun onLongClick(clicked: View): Boolean {
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
return false
}

View File

@ -45,7 +45,7 @@ class InputBindingSettingViewHolder(val binding: ListItemSettingBinding, adapter
if (setting.isEditable) {
adapter.onInputBindingClick(setting, bindingAdapterPosition)
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
}
@ -53,7 +53,7 @@ class InputBindingSettingViewHolder(val binding: ListItemSettingBinding, adapter
if (setting.isEditable) {
adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
return false
}

View File

@ -60,7 +60,7 @@ class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
override fun onClick(clicked: View) {
if (!setting.isRuntimeRunnable && EmulationActivity.isRunning()) {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(true)
} else {
setting.runnable.invoke()
}

View File

@ -27,7 +27,7 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
binding.textSettingValue.visibility = View.VISIBLE
binding.textSettingValue.text = getTextSetting()
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
binding.textSettingName.alpha = 1f
binding.textSettingDescription.alpha = 1f
binding.textSettingValue.alpha = 1f
@ -65,8 +65,8 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
}
override fun onClick(clicked: View) {
if (!setting.isEditable) {
adapter.onClickDisabledSetting()
if (!setting.isEditable || !setting.isEnabled) {
adapter.onClickDisabledSetting(!setting.isEditable)
return
}
@ -84,10 +84,10 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
}
override fun onLongClick(clicked: View): Boolean {
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
return false
}

View File

@ -35,7 +35,7 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
else -> "${(setting.setting as AbstractIntSetting).int}${setting.units}"
}
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
binding.textSettingName.alpha = 1f
binding.textSettingDescription.alpha = 1f
binding.textSettingValue.alpha = 1f
@ -47,18 +47,18 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
}
override fun onClick(clicked: View) {
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
adapter.onSliderClick(setting, bindingAdapterPosition)
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
}
override fun onLongClick(clicked: View): Boolean {
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
return false
}

View File

@ -25,21 +25,31 @@ class StringInputViewHolder(val binding: ListItemSettingBinding, adapter: Settin
}
binding.textSettingValue.visibility = View.VISIBLE
binding.textSettingValue.text = setting.setting?.valueAsString
if (setting.isEditable && setting.isEnabled) {
binding.textSettingName.alpha = 1f
binding.textSettingDescription.alpha = 1f
binding.textSettingValue.alpha = 1f
} else {
binding.textSettingName.alpha = 0.5f
binding.textSettingDescription.alpha = 0.5f
binding.textSettingValue.alpha = 0.5f
}
}
override fun onClick(clicked: View) {
if (!setting.isEditable) {
adapter.onClickDisabledSetting()
if (!setting.isEditable || !setting.isEnabled) {
adapter.onClickDisabledSetting(!setting.isEditable)
return
}
adapter.onStringInputClick((setting as StringInputSetting), bindingAdapterPosition)
}
override fun onLongClick(clicked: View): Boolean {
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
return false
}

View File

@ -33,26 +33,26 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
adapter.onBooleanClick(item, bindingAdapterPosition, binding.switchWidget.isChecked)
}
binding.switchWidget.isEnabled = setting.isEditable
binding.switchWidget.isEnabled = setting.isEditable && setting.isEnabled
val textAlpha = if (setting.isEditable) 1f else 0.5f
val textAlpha = if (setting.isEditable && setting.isEnabled) 1f else 0.5f
binding.textSettingName.alpha = textAlpha
binding.textSettingDescription.alpha = textAlpha
}
override fun onClick(clicked: View) {
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
binding.switchWidget.toggle()
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
}
override fun onLongClick(clicked: View): Boolean {
if (setting.isEditable) {
if (setting.isEditable && setting.isEnabled) {
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
} else {
adapter.onClickDisabledSetting()
adapter.onClickDisabledSetting(!setting.isEditable)
}
return false
}

View File

@ -315,6 +315,8 @@
<string name="select_rtc_time">Select RTC time</string>
<string name="reset_setting_confirmation">Do you want to reset this setting back to its default value?</string>
<string name="setting_not_editable">You can\'t edit this now</string>
<string name="setting_disabled">Setting disabled</string>
<string name="setting_disabled_description">This setting is currently disabled due to another setting not being the appropriate value.</string>
<string name="setting_not_editable_description">This option can\'t be changed while a game is running.</string>
<string name="auto_select">Auto-Select</string>