diff --git a/app/src/main/java/emu/skyline/preference/IntegerListPreference.kt b/app/src/main/java/emu/skyline/preference/IntegerListPreference.kt index 2dbfd549..bbe2ad54 100644 --- a/app/src/main/java/emu/skyline/preference/IntegerListPreference.kt +++ b/app/src/main/java/emu/skyline/preference/IntegerListPreference.kt @@ -199,7 +199,7 @@ open class IntegerListPreference @JvmOverloads constructor( } } - class IntegerListPreferenceDialogFragmentCompat : PreferenceDialogFragmentCompat() { + open class IntegerListPreferenceDialogFragmentCompat : PreferenceDialogFragmentCompat() { var clickedDialogEntryIndex = 0 private var entries : Array? = null private var entryValues : IntArray? = null @@ -259,9 +259,9 @@ open class IntegerListPreference @JvmOverloads constructor( } companion object { - private const val SAVE_STATE_INDEX = "ListPreferenceDialogFragment.index" - private const val SAVE_STATE_ENTRIES = "ListPreferenceDialogFragment.entries" - private const val SAVE_STATE_ENTRY_VALUES = "ListPreferenceDialogFragment.entryValues" + private const val SAVE_STATE_INDEX = "IntegerListPreferenceDialogFragment.index" + private const val SAVE_STATE_ENTRIES = "IntegerListPreferenceDialogFragment.entries" + private const val SAVE_STATE_ENTRY_VALUES = "IntegerListPreferenceDialogFragment.entryValues" fun newInstance(key : String?) : IntegerListPreferenceDialogFragmentCompat { val fragment = IntegerListPreferenceDialogFragmentCompat() diff --git a/app/src/main/java/emu/skyline/preference/dialog/EditTextPreferenceMaterialDialogFragmentCompat.kt b/app/src/main/java/emu/skyline/preference/dialog/EditTextPreferenceMaterialDialogFragmentCompat.kt new file mode 100644 index 00000000..821e6af0 --- /dev/null +++ b/app/src/main/java/emu/skyline/preference/dialog/EditTextPreferenceMaterialDialogFragmentCompat.kt @@ -0,0 +1,64 @@ +/* + * SPDX-License-Identifier: MPL-2.0 + * Copyright © 2023 Skyline Team and Contributors (https://github.com/skyline-emu/) + */ + +@file:SuppressLint("RestrictedApi") + +package emu.skyline.preference.dialog + +import android.annotation.SuppressLint +import android.app.Dialog +import android.os.Build +import android.os.Bundle +import android.view.WindowInsets +import androidx.preference.EditTextPreferenceDialogFragmentCompat +import com.google.android.material.dialog.MaterialAlertDialogBuilder + +/** + * An [EditTextPreferenceDialogFragmentCompat] that uses [MaterialAlertDialogBuilder] + */ +class EditTextPreferenceMaterialDialogFragmentCompat : EditTextPreferenceDialogFragmentCompat() { + override fun onCreateDialog(savedInstanceState : Bundle?) : Dialog { + val builder = MaterialAlertDialogBuilder(requireContext()) + .setTitle(preference.dialogTitle) + .setIcon(preference.dialogIcon) + .setPositiveButton(preference.positiveButtonText, this) + .setNegativeButton(preference.negativeButtonText, this) + + val contentView = onCreateDialogView(requireContext()) + if (contentView != null) { + onBindDialogView(contentView) + builder.setView(contentView) + } else { + builder.setMessage(preference.dialogMessage) + } + + onPrepareDialogBuilder(builder) + + // Create the dialog + val dialog : Dialog = builder.create() + if (needInputMethod()) { + requestInputMethod(dialog) + } + + return dialog + } + + private fun requestInputMethod(dialog : Dialog) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) + dialog.window?.decorView?.windowInsetsController?.show(WindowInsets.Type.ime()) + else + scheduleShowSoftInput() + } + + companion object { + fun newInstance(key : String?) : EditTextPreferenceMaterialDialogFragmentCompat { + val fragment = EditTextPreferenceMaterialDialogFragmentCompat() + val bundle = Bundle(1) + bundle.putString(ARG_KEY, key) + fragment.arguments = bundle + return fragment + } + } +} diff --git a/app/src/main/java/emu/skyline/preference/dialog/IntegerListPreferenceMaterialDialogFragmentCompat.kt b/app/src/main/java/emu/skyline/preference/dialog/IntegerListPreferenceMaterialDialogFragmentCompat.kt new file mode 100644 index 00000000..52df3227 --- /dev/null +++ b/app/src/main/java/emu/skyline/preference/dialog/IntegerListPreferenceMaterialDialogFragmentCompat.kt @@ -0,0 +1,64 @@ +/* + * SPDX-License-Identifier: MPL-2.0 + * Copyright © 2023 Skyline Team and Contributors (https://github.com/skyline-emu/) + */ + +@file:SuppressLint("RestrictedApi") + +package emu.skyline.preference.dialog + +import android.annotation.SuppressLint +import android.app.Dialog +import android.os.Build +import android.os.Bundle +import android.view.WindowInsets +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import emu.skyline.preference.IntegerListPreference + +/** + * An [IntegerListPreference.IntegerListPreferenceDialogFragmentCompat] that uses [MaterialAlertDialogBuilder] + */ +class IntegerListPreferenceMaterialDialogFragmentCompat : IntegerListPreference.IntegerListPreferenceDialogFragmentCompat() { + override fun onCreateDialog(savedInstanceState : Bundle?) : Dialog { + val builder = MaterialAlertDialogBuilder(requireContext()) + .setTitle(preference.dialogTitle) + .setIcon(preference.dialogIcon) + .setPositiveButton(preference.positiveButtonText, this) + .setNegativeButton(preference.negativeButtonText, this) + + val contentView = onCreateDialogView(requireContext()) + if (contentView != null) { + onBindDialogView(contentView) + builder.setView(contentView) + } else { + builder.setMessage(preference.dialogMessage) + } + + onPrepareDialogBuilder(builder) + + // Create the dialog + val dialog : Dialog = builder.create() + if (needInputMethod()) { + requestInputMethod(dialog) + } + + return dialog + } + + private fun requestInputMethod(dialog : Dialog) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) + dialog.window?.decorView?.windowInsetsController?.show(WindowInsets.Type.ime()) + else + scheduleShowSoftInput() + } + + companion object { + fun newInstance(key : String?) : IntegerListPreferenceMaterialDialogFragmentCompat { + val fragment = IntegerListPreferenceMaterialDialogFragmentCompat() + val bundle = Bundle(1) + bundle.putString(ARG_KEY, key) + fragment.arguments = bundle + return fragment + } + } +} diff --git a/app/src/main/java/emu/skyline/preference/dialog/ListPreferenceMaterialDialogFragmentCompat.kt b/app/src/main/java/emu/skyline/preference/dialog/ListPreferenceMaterialDialogFragmentCompat.kt new file mode 100644 index 00000000..b22eb688 --- /dev/null +++ b/app/src/main/java/emu/skyline/preference/dialog/ListPreferenceMaterialDialogFragmentCompat.kt @@ -0,0 +1,64 @@ +/* + * SPDX-License-Identifier: MPL-2.0 + * Copyright © 2023 Skyline Team and Contributors (https://github.com/skyline-emu/) + */ + +@file:SuppressLint("RestrictedApi") + +package emu.skyline.preference.dialog + +import android.annotation.SuppressLint +import android.app.Dialog +import android.os.Build +import android.os.Bundle +import android.view.WindowInsets +import androidx.preference.ListPreferenceDialogFragmentCompat +import com.google.android.material.dialog.MaterialAlertDialogBuilder + +/** + * A [ListPreferenceDialogFragmentCompat] that uses [MaterialAlertDialogBuilder] + */ +class ListPreferenceMaterialDialogFragmentCompat : ListPreferenceDialogFragmentCompat() { + override fun onCreateDialog(savedInstanceState : Bundle?) : Dialog { + val builder = MaterialAlertDialogBuilder(requireContext()) + .setTitle(preference.dialogTitle) + .setIcon(preference.dialogIcon) + .setPositiveButton(preference.positiveButtonText, this) + .setNegativeButton(preference.negativeButtonText, this) + + val contentView = onCreateDialogView(requireContext()) + if (contentView != null) { + onBindDialogView(contentView) + builder.setView(contentView) + } else { + builder.setMessage(preference.dialogMessage) + } + + onPrepareDialogBuilder(builder) + + // Create the dialog + val dialog : Dialog = builder.create() + if (needInputMethod()) { + requestInputMethod(dialog) + } + + return dialog + } + + private fun requestInputMethod(dialog : Dialog) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) + dialog.window?.decorView?.windowInsetsController?.show(WindowInsets.Type.ime()) + else + scheduleShowSoftInput() + } + + companion object { + fun newInstance(key : String?) : ListPreferenceMaterialDialogFragmentCompat { + val fragment = ListPreferenceMaterialDialogFragmentCompat() + val bundle = Bundle(1) + bundle.putString(ARG_KEY, key) + fragment.arguments = bundle + return fragment + } + } +} diff --git a/app/src/main/java/emu/skyline/settings/GameSettingsFragment.kt b/app/src/main/java/emu/skyline/settings/GameSettingsFragment.kt index c10237d7..21fd5063 100644 --- a/app/src/main/java/emu/skyline/settings/GameSettingsFragment.kt +++ b/app/src/main/java/emu/skyline/settings/GameSettingsFragment.kt @@ -14,7 +14,6 @@ import emu.skyline.R import emu.skyline.data.AppItem import emu.skyline.data.AppItemTag import emu.skyline.preference.GpuDriverPreference -import emu.skyline.preference.IntegerListPreference import emu.skyline.utils.GpuDriverHelper import emu.skyline.utils.WindowInsetsHelper import emu.skyline.utils.serializable @@ -23,10 +22,6 @@ import emu.skyline.utils.serializable * This fragment is used to display custom game preferences */ class GameSettingsFragment : PreferenceFragmentCompat() { - companion object { - private const val DIALOG_FRAGMENT_TAG = "androidx.preference.PreferenceFragment.DIALOG" - } - private val item by lazy { requireArguments().serializable(AppItemTag)!! } override fun onViewCreated(view : View, savedInstanceState : Bundle?) { @@ -87,19 +82,4 @@ class GameSettingsFragment : PreferenceFragmentCompat() { if (BuildConfig.BUILD_TYPE == "release") findPreference("category_debug")?.isVisible = false } - - override fun onDisplayPreferenceDialog(preference : Preference) { - if (preference is IntegerListPreference) { - // Check if dialog is already showing - if (parentFragmentManager.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) - return - - val dialogFragment = IntegerListPreference.IntegerListPreferenceDialogFragmentCompat.newInstance(preference.getKey()) - @Suppress("DEPRECATION") - dialogFragment.setTargetFragment(this, 0) // androidx.preference.PreferenceDialogFragmentCompat depends on the target fragment being set correctly even though it's deprecated - dialogFragment.show(parentFragmentManager, DIALOG_FRAGMENT_TAG) - } else { - super.onDisplayPreferenceDialog(preference) - } - } } diff --git a/app/src/main/java/emu/skyline/settings/GlobalSettingsFragment.kt b/app/src/main/java/emu/skyline/settings/GlobalSettingsFragment.kt index f865d229..20f1bf45 100644 --- a/app/src/main/java/emu/skyline/settings/GlobalSettingsFragment.kt +++ b/app/src/main/java/emu/skyline/settings/GlobalSettingsFragment.kt @@ -13,7 +13,6 @@ import androidx.preference.PreferenceFragmentCompat import androidx.preference.TwoStatePreference import emu.skyline.BuildConfig import emu.skyline.R -import emu.skyline.preference.IntegerListPreference import emu.skyline.utils.GpuDriverHelper import emu.skyline.utils.WindowInsetsHelper @@ -21,10 +20,6 @@ import emu.skyline.utils.WindowInsetsHelper * This fragment is used to display the global preferences */ class GlobalSettingsFragment : PreferenceFragmentCompat() { - companion object { - private const val DIALOG_FRAGMENT_TAG = "androidx.preference.PreferenceFragment.DIALOG" - } - override fun onViewCreated(view : View, savedInstanceState : Bundle?) { super.onViewCreated(view, savedInstanceState) val recyclerView = view.findViewById(R.id.recycler_view) @@ -66,19 +61,4 @@ class GlobalSettingsFragment : PreferenceFragmentCompat() { }) } } - - override fun onDisplayPreferenceDialog(preference : Preference) { - if (preference is IntegerListPreference) { - // Check if dialog is already showing - if (parentFragmentManager.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) - return - - val dialogFragment = IntegerListPreference.IntegerListPreferenceDialogFragmentCompat.newInstance(preference.getKey()) - @Suppress("DEPRECATION") - dialogFragment.setTargetFragment(this, 0) // androidx.preference.PreferenceDialogFragmentCompat depends on the target fragment being set correctly even though it's deprecated - dialogFragment.show(parentFragmentManager, DIALOG_FRAGMENT_TAG) - } else { - super.onDisplayPreferenceDialog(preference) - } - } } diff --git a/app/src/main/java/emu/skyline/settings/SettingsActivity.kt b/app/src/main/java/emu/skyline/settings/SettingsActivity.kt index e3f70be0..d27db32c 100644 --- a/app/src/main/java/emu/skyline/settings/SettingsActivity.kt +++ b/app/src/main/java/emu/skyline/settings/SettingsActivity.kt @@ -14,14 +14,23 @@ import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.view.WindowCompat +import androidx.preference.EditTextPreference +import androidx.preference.ListPreference +import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import com.google.android.material.internal.ToolbarUtils import emu.skyline.R import emu.skyline.data.AppItemTag import emu.skyline.databinding.SettingsActivityBinding +import emu.skyline.preference.IntegerListPreference +import emu.skyline.preference.dialog.EditTextPreferenceMaterialDialogFragmentCompat +import emu.skyline.preference.dialog.IntegerListPreferenceMaterialDialogFragmentCompat +import emu.skyline.preference.dialog.ListPreferenceMaterialDialogFragmentCompat import emu.skyline.utils.WindowInsetsHelper -class SettingsActivity : AppCompatActivity() { +private const val PREFERENCE_DIALOG_FRAGMENT_TAG = "androidx.preference.PreferenceFragment.DIALOG" + +class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback { val binding by lazy { SettingsActivityBinding.inflate(layoutInflater) } /** @@ -118,4 +127,41 @@ class SettingsActivity : AppCompatActivity() { setResult(RESULT_OK) super.finish() } + + override fun onPreferenceDisplayDialog(caller : PreferenceFragmentCompat, pref : Preference) : Boolean { + when (pref) { + is IntegerListPreference -> { + // Check if dialog is already showing + if (supportFragmentManager.findFragmentByTag(PREFERENCE_DIALOG_FRAGMENT_TAG) != null) + return true + + val dialogFragment = IntegerListPreferenceMaterialDialogFragmentCompat.newInstance(pref.getKey()) + @Suppress("DEPRECATION") + dialogFragment.setTargetFragment(caller, 0) // androidx.preference.PreferenceDialogFragmentCompat depends on the target fragment being set correctly even though it's deprecated + dialogFragment.show(supportFragmentManager, PREFERENCE_DIALOG_FRAGMENT_TAG) + return true + } + is EditTextPreference -> { + if (supportFragmentManager.findFragmentByTag(PREFERENCE_DIALOG_FRAGMENT_TAG) != null) + return true + + val dialogFragment = EditTextPreferenceMaterialDialogFragmentCompat.newInstance(pref.getKey()) + @Suppress("DEPRECATION") + dialogFragment.setTargetFragment(caller, 0) + dialogFragment.show(supportFragmentManager, PREFERENCE_DIALOG_FRAGMENT_TAG) + return true + } + is ListPreference -> { + if (supportFragmentManager.findFragmentByTag(PREFERENCE_DIALOG_FRAGMENT_TAG) != null) + return true + + val dialogFragment = ListPreferenceMaterialDialogFragmentCompat.newInstance(pref.getKey()) + @Suppress("DEPRECATION") + dialogFragment.setTargetFragment(caller, 0) + dialogFragment.show(supportFragmentManager, PREFERENCE_DIALOG_FRAGMENT_TAG) + return true + } + else -> return false + } + } }