feat(ui): implement theme selection dialog with TV support

This commit is contained in:
2026-03-28 21:55:38 +01:00
parent 2ccb4225d4
commit a5b11ba99a
4 changed files with 231 additions and 22 deletions

View File

@@ -5,6 +5,7 @@ import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -16,8 +17,10 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.net.toUri
import androidx.navigation.fragment.findNavController
import androidx.preference.*
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.michatec.radio.dialogs.ErrorDialog
import com.michatec.radio.dialogs.ThemeSelectionDialog
import com.michatec.radio.dialogs.YesNoDialog
import com.michatec.radio.helpers.*
import com.michatec.radio.helpers.AppThemeHelper.getColor
@@ -31,7 +34,7 @@ import java.util.*
/*
* SettingsFragment class
*/
class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogListener {
class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogListener, ThemeSelectionDialog.ThemeSelectionDialogListener {
/* Define log tag */
@@ -55,35 +58,24 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
val screen = preferenceManager.createPreferenceScreen(context)
// set up "App Theme" preference
val preferenceThemeSelection = ListPreference(activity as Context)
val preferenceThemeSelection = Preference(activity as Context)
preferenceThemeSelection.title = getString(R.string.pref_theme_selection_title)
preferenceThemeSelection.setIcon(R.drawable.ic_brush_24dp)
preferenceThemeSelection.key = Keys.PREF_THEME_SELECTION
preferenceThemeSelection.summary = "${getString(R.string.pref_theme_selection_summary)} ${
AppThemeHelper.getCurrentTheme(activity as Context)
}"
preferenceThemeSelection.entries = arrayOf(
getString(R.string.pref_theme_selection_mode_device_default),
getString(R.string.pref_theme_selection_mode_light),
getString(R.string.pref_theme_selection_mode_dark)
)
preferenceThemeSelection.entryValues = arrayOf(
Keys.STATE_THEME_FOLLOW_SYSTEM,
Keys.STATE_THEME_LIGHT_MODE,
Keys.STATE_THEME_DARK_MODE
)
preferenceThemeSelection.setDefaultValue(Keys.STATE_THEME_FOLLOW_SYSTEM)
preferenceThemeSelection.setOnPreferenceChangeListener { preference, newValue ->
if (preference is ListPreference) {
val index: Int = preference.entryValues.indexOf(newValue)
preferenceThemeSelection.summary =
"${getString(R.string.pref_theme_selection_summary)} ${preference.entries[index]}"
AppThemeHelper.setTheme(newValue as String)
return@setOnPreferenceChangeListener true
preferenceThemeSelection.setOnPreferenceClickListener {
// check if device is a TV
val isTv = requireContext().packageManager.hasSystemFeature(android.content.pm.PackageManager.FEATURE_LEANBACK)
if (isTv) {
// show TV-specific theme selection dialog
ThemeSelectionDialog(this).show(activity as Context)
} else {
return@setOnPreferenceChangeListener false
// show standard theme selection dialog for non-TV devices
showThemeSelectionDialog()
}
return@setOnPreferenceClickListener true
}
// set up "Update Station Images" preference
@@ -306,6 +298,57 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
}
/* Shows theme selection dialog for non-TV devices */
private fun showThemeSelectionDialog() {
val themes = arrayOf(
getString(R.string.pref_theme_selection_mode_device_default),
getString(R.string.pref_theme_selection_mode_light),
getString(R.string.pref_theme_selection_mode_dark)
)
val themeValues = arrayOf(
Keys.STATE_THEME_FOLLOW_SYSTEM,
Keys.STATE_THEME_LIGHT_MODE,
Keys.STATE_THEME_DARK_MODE
)
val currentTheme = AppThemeHelper.getCurrentTheme(activity as Context)
val currentIndex = themes.indexOf(currentTheme)
val builder = MaterialAlertDialogBuilder(activity as Context)
builder.setTitle(getString(R.string.pref_theme_selection_title))
builder.setSingleChoiceItems(themes, currentIndex) { dialog, which ->
val selectedTheme = themeValues[which]
AppThemeHelper.setTheme(selectedTheme)
// update summary
val preferenceThemeSelection = findPreference<Preference>(Keys.PREF_THEME_SELECTION)
preferenceThemeSelection?.summary = "${getString(R.string.pref_theme_selection_summary)} ${themes[which]}"
dialog.dismiss()
}
builder.setNegativeButton(R.string.dialog_generic_button_cancel, null)
builder.show()
}
/* Overrides onThemeSelectionDialog from ThemeSelectionDialogListener */
override fun onThemeSelectionDialog(dialogResult: Boolean, selectedTheme: String) {
if (dialogResult) {
// update summary
val themes = arrayOf(
getString(R.string.pref_theme_selection_mode_device_default),
getString(R.string.pref_theme_selection_mode_light),
getString(R.string.pref_theme_selection_mode_dark)
)
val themeValues = arrayOf(
Keys.STATE_THEME_FOLLOW_SYSTEM,
Keys.STATE_THEME_LIGHT_MODE,
Keys.STATE_THEME_DARK_MODE
)
val index = themeValues.indexOf(selectedTheme)
val preferenceThemeSelection = findPreference<Preference>(Keys.PREF_THEME_SELECTION)
preferenceThemeSelection?.summary = "${getString(R.string.pref_theme_selection_summary)} ${themes[index]}"
}
}
/* Overrides onYesNoDialog from YesNoDialogListener */
override fun onYesNoDialog(
type: Int,