commit 0890d8f6b71be93cfaf876beaa32e1772cf322ef
parent aabaae1041c48cda93045cff4c0b5dbfe2cfd793
Author: rmalicdem <rmalicdem@mozilla.com>
Date: Tue, 11 Nov 2025 21:29:21 +0000
Bug 1969124 - Part 2: Cleanup toolbar shortcut preferences r=android-reviewers,Roger
Differential Revision: https://phabricator.services.mozilla.com/D271496
Diffstat:
4 files changed, 215 insertions(+), 315 deletions(-)
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarExpandedShortcutPreference.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarExpandedShortcutPreference.kt
@@ -5,158 +5,19 @@
package org.mozilla.fenix.settings
import android.content.Context
-import android.content.res.ColorStateList
import android.util.AttributeSet
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.RadioButton
-import android.widget.TextView
-import androidx.annotation.AttrRes
-import androidx.annotation.ColorInt
-import androidx.core.widget.ImageViewCompat
-import androidx.preference.Preference
-import androidx.preference.PreferenceViewHolder
-import com.google.android.material.color.MaterialColors
-import org.mozilla.fenix.R
import org.mozilla.fenix.ext.settings
-import com.google.android.material.R as materialR
-import mozilla.components.ui.icons.R as iconsR
-/**
- * Custom Preference that renders the expanded shortcut options list.
- * Selecting an option moves it to the top and persists to SharedPreferences.
- */
-class ToolbarExpandedShortcutPreference @JvmOverloads constructor(
+internal class ToolbarExpandedShortcutPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
-) : Preference(context, attrs) {
+) : ToolbarShortcutPreference(context, attrs) {
- private val options: List<ShortcutOption> by lazy {
- listOf(
- ShortcutOption(
- ShortcutType.BOOKMARK,
- iconsR.drawable.mozac_ic_bookmark_24,
- R.string.toolbar_customize_shortcut_add_bookmark,
- ),
- )
- }
-
- @ColorInt
- private var colorTertiary: Int = 0
-
- @ColorInt
- private var colorOnSurface: Int = 0
-
- @ColorInt
- private var colorOnSurfaceVariant: Int = 0
-
- init {
- layoutResource = R.layout.preference_toolbar_shortcut
- isSelectable = false
- }
-
- override fun onBindViewHolder(holder: PreferenceViewHolder) {
- super.onBindViewHolder(holder)
-
- val settings = context.settings()
- val selectedKey = settings.toolbarExpandedShortcutKey
-
- val selectedContainer = holder.findViewById(R.id.selected_container) as LinearLayout
- val optionsContainer = holder.findViewById(R.id.options_container) as LinearLayout
- val separator = holder.findViewById(R.id.separator) as View
-
- colorTertiary = holder.itemView.getMaterialColor(materialR.attr.colorTertiary)
- colorOnSurface = holder.itemView.getMaterialColor(materialR.attr.colorOnSurface)
- colorOnSurfaceVariant = holder.itemView.getMaterialColor(materialR.attr.colorOnSurfaceVariant)
-
- val selected = options.firstOrNull { it.key == selectedKey } ?: options.first()
-
- selectedContainer.removeAllViews()
- selectedContainer.addView(
- makeRow(
- parent = selectedContainer,
- option = selected,
- isChecked = true,
- isEnabled = false,
- onClick = {},
- ),
- )
-
- val remaining = options.filter { it.key != selected.key }.distinctBy { it.key }
- optionsContainer.removeAllViews()
- remaining.forEach { opt ->
- optionsContainer.addView(
- makeRow(
- parent = optionsContainer,
- option = opt,
- isChecked = false,
- isEnabled = true,
- ) { newlySelected ->
- settings.toolbarExpandedShortcutKey = newlySelected.key
- notifyChanged()
- },
- )
- }
+ override val options: List<ShortcutOption> = expandedShortcutOptions
- separator.visibility = if (remaining.isEmpty()) View.GONE else View.VISIBLE
- }
-
- private fun makeRow(
- parent: ViewGroup,
- option: ShortcutOption,
- isChecked: Boolean,
- isEnabled: Boolean,
- onClick: (ShortcutOption) -> Unit,
- ): View {
- val row = LayoutInflater.from(context)
- .inflate(R.layout.toolbar_shortcut_row, parent, false) as LinearLayout
-
- val radio = row.findViewById<RadioButton>(R.id.row_radio)
- val icon = row.findViewById<ImageView>(R.id.row_icon)
- val label = row.findViewById<TextView>(R.id.row_label)
-
- icon.setImageResource(option.icon)
- label.setText(option.label)
-
- radio?.setStartCheckedIndicator()
- radio.isChecked = isChecked
- radio.isEnabled = true
-
- label.setTextColor(
- if (isChecked) colorTertiary else colorOnSurface,
- )
-
- ImageViewCompat.setImageTintList(
- icon,
- ColorStateList.valueOf(
- if (isChecked) colorTertiary else colorOnSurface,
- ),
- )
-
- radio.buttonTintList = ColorStateList(
- arrayOf(
- intArrayOf(android.R.attr.state_checked),
- intArrayOf(-android.R.attr.state_checked),
- ),
- intArrayOf(colorTertiary, colorOnSurfaceVariant),
- )
-
- if (isEnabled) {
- val clicker = View.OnClickListener {
- onClick(option)
- }
- row.setOnClickListener(clicker)
- }
-
- row.isEnabled = isEnabled
-
- return row
- }
+ override fun readSelectedKey(): String? = context.settings().toolbarExpandedShortcutKey
- private fun View.getMaterialColor(@AttrRes attr: Int): Int {
- return MaterialColors.getColor(this, attr)
+ override fun writeSelectedKey(key: String) {
+ context.settings().toolbarExpandedShortcutKey = key
}
}
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarShortcut.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarShortcut.kt
@@ -6,6 +6,8 @@ package org.mozilla.fenix.settings
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
+import org.mozilla.fenix.R
+import mozilla.components.ui.icons.R as iconsR
/**
* String keys used to persist and map the selected toolbar shortcut option.
@@ -20,8 +22,59 @@ object ShortcutType {
const val BACK = "back"
}
+internal enum class ShortcutAvailability {
+ SIMPLE,
+ EXPANDED,
+}
+
internal data class ShortcutOption(
val key: String,
@param:DrawableRes val icon: Int,
@param:StringRes val label: Int,
+ val availability: Set<ShortcutAvailability>,
+)
+
+internal val allShortcutOptions: List<ShortcutOption> = listOf(
+ ShortcutOption(
+ ShortcutType.NEW_TAB,
+ iconsR.drawable.mozac_ic_plus_24,
+ R.string.toolbar_customize_shortcut_new_tab,
+ setOf(ShortcutAvailability.SIMPLE),
+ ),
+ ShortcutOption(
+ ShortcutType.SHARE,
+ iconsR.drawable.mozac_ic_share_android_24,
+ R.string.toolbar_customize_shortcut_share,
+ setOf(ShortcutAvailability.SIMPLE),
+ ),
+ ShortcutOption(
+ ShortcutType.BOOKMARK,
+ iconsR.drawable.mozac_ic_bookmark_24,
+ R.string.toolbar_customize_shortcut_add_bookmark,
+ setOf(ShortcutAvailability.SIMPLE, ShortcutAvailability.EXPANDED),
+ ),
+ ShortcutOption(
+ ShortcutType.TRANSLATE,
+ iconsR.drawable.mozac_ic_translate_24,
+ R.string.toolbar_customize_shortcut_translate,
+ setOf(ShortcutAvailability.SIMPLE),
+ ),
+ ShortcutOption(
+ ShortcutType.HOMEPAGE,
+ iconsR.drawable.mozac_ic_home_24,
+ R.string.toolbar_customize_shortcut_homepage,
+ setOf(ShortcutAvailability.SIMPLE),
+ ),
+ ShortcutOption(
+ ShortcutType.BACK,
+ iconsR.drawable.mozac_ic_back_24,
+ R.string.toolbar_customize_shortcut_back,
+ setOf(ShortcutAvailability.SIMPLE),
+ ),
)
+
+internal val expandedShortcutOptions: List<ShortcutOption> =
+ allShortcutOptions.filter { ShortcutAvailability.EXPANDED in it.availability }
+
+internal val simpleShortcutOptions: List<ShortcutOption> =
+ allShortcutOptions.filter { ShortcutAvailability.SIMPLE in it.availability }
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarShortcutPreference.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarShortcutPreference.kt
@@ -0,0 +1,150 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.fenix.settings
+
+import android.content.Context
+import android.content.res.ColorStateList
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.RadioButton
+import android.widget.TextView
+import androidx.annotation.AttrRes
+import androidx.annotation.ColorInt
+import androidx.core.widget.ImageViewCompat
+import androidx.preference.Preference
+import androidx.preference.PreferenceViewHolder
+import com.google.android.material.color.MaterialColors
+import org.mozilla.fenix.R
+import com.google.android.material.R as materialR
+
+/**
+ * Custom Preference that renders the options list.
+ * Selecting an option moves it to the top and persists to SharedPreferences.
+ */
+internal abstract class ToolbarShortcutPreference @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+) : Preference(context, attrs) {
+
+ @ColorInt
+ private var colorTertiary: Int = 0
+
+ @ColorInt
+ private var colorOnSurface: Int = 0
+
+ @ColorInt
+ private var colorOnSurfaceVariant: Int = 0
+
+ init {
+ layoutResource = R.layout.preference_toolbar_shortcut
+ isSelectable = false
+ }
+
+ protected abstract val options: List<ShortcutOption>
+ protected abstract fun readSelectedKey(): String?
+ protected abstract fun writeSelectedKey(key: String)
+
+ override fun onBindViewHolder(holder: PreferenceViewHolder) {
+ super.onBindViewHolder(holder)
+
+ val selectedKey = readSelectedKey()
+
+ val selectedContainer = holder.findViewById(R.id.selected_container) as LinearLayout
+ val optionsContainer = holder.findViewById(R.id.options_container) as LinearLayout
+ val separator = holder.findViewById(R.id.separator) as View
+
+ colorTertiary = holder.itemView.getMaterialColor(materialR.attr.colorTertiary)
+ colorOnSurface = holder.itemView.getMaterialColor(materialR.attr.colorOnSurface)
+ colorOnSurfaceVariant = holder.itemView.getMaterialColor(materialR.attr.colorOnSurfaceVariant)
+
+ val selected = options.firstOrNull { it.key == selectedKey } ?: options.first()
+
+ selectedContainer.removeAllViews()
+ selectedContainer.addView(
+ makeRow(
+ parent = selectedContainer,
+ option = selected,
+ isChecked = true,
+ isEnabled = false,
+ onClick = {},
+ ),
+ )
+
+ val remaining = options.filter { it.key != selected.key }.distinctBy { it.key }
+ optionsContainer.removeAllViews()
+ remaining.forEach { opt ->
+ optionsContainer.addView(
+ makeRow(
+ parent = optionsContainer,
+ option = opt,
+ isChecked = false,
+ isEnabled = true,
+ ) { newlySelected ->
+ writeSelectedKey(newlySelected.key)
+ notifyChanged()
+ },
+ )
+ }
+
+ separator.visibility = if (remaining.isEmpty()) View.GONE else View.VISIBLE
+ }
+
+ private fun makeRow(
+ parent: ViewGroup,
+ option: ShortcutOption,
+ isChecked: Boolean,
+ isEnabled: Boolean,
+ onClick: (ShortcutOption) -> Unit,
+ ): View {
+ val row = LayoutInflater.from(context)
+ .inflate(R.layout.toolbar_shortcut_row, parent, false) as LinearLayout
+
+ val radio = row.findViewById<RadioButton>(R.id.row_radio)
+ val icon = row.findViewById<ImageView>(R.id.row_icon)
+ val label = row.findViewById<TextView>(R.id.row_label)
+
+ icon.setImageResource(option.icon)
+ label.setText(option.label)
+
+ radio?.setStartCheckedIndicator()
+ radio.isChecked = isChecked
+ radio.isEnabled = true
+
+ label.setTextColor(
+ if (isChecked) colorTertiary else colorOnSurface,
+ )
+
+ ImageViewCompat.setImageTintList(
+ icon,
+ ColorStateList.valueOf(
+ if (isChecked) colorTertiary else colorOnSurface,
+ ),
+ )
+
+ radio.buttonTintList = ColorStateList(
+ arrayOf(
+ intArrayOf(android.R.attr.state_checked),
+ intArrayOf(-android.R.attr.state_checked),
+ ),
+ intArrayOf(colorTertiary, colorOnSurfaceVariant),
+ )
+
+ if (isEnabled) {
+ val clicker = View.OnClickListener { onClick(option) }
+ row.setOnClickListener(clicker)
+ }
+
+ row.isEnabled = isEnabled
+ return row
+ }
+
+ private fun View.getMaterialColor(@AttrRes attr: Int): Int {
+ return MaterialColors.getColor(this, attr)
+ }
+}
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarSimpleShortcutPreference.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarSimpleShortcutPreference.kt
@@ -5,183 +5,19 @@
package org.mozilla.fenix.settings
import android.content.Context
-import android.content.res.ColorStateList
import android.util.AttributeSet
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.RadioButton
-import android.widget.TextView
-import androidx.annotation.AttrRes
-import androidx.annotation.ColorInt
-import androidx.core.widget.ImageViewCompat
-import androidx.preference.Preference
-import androidx.preference.PreferenceViewHolder
-import com.google.android.material.color.MaterialColors
-import org.mozilla.fenix.R
import org.mozilla.fenix.ext.settings
-import com.google.android.material.R as materialR
-import mozilla.components.ui.icons.R as iconsR
-/**
- * Custom Preference that renders the simple shortcut options list.
- * Selecting an option moves it to the top and persists to SharedPreferences.
- */
-class ToolbarSimpleShortcutPreference @JvmOverloads constructor(
+internal class ToolbarSimpleShortcutPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
-) : Preference(context, attrs) {
+) : ToolbarShortcutPreference(context, attrs) {
- private val options: List<ShortcutOption> by lazy {
- listOf(
- ShortcutOption(
- ShortcutType.NEW_TAB,
- iconsR.drawable.mozac_ic_plus_24,
- R.string.toolbar_customize_shortcut_new_tab,
- ),
- ShortcutOption(
- ShortcutType.SHARE,
- iconsR.drawable.mozac_ic_share_android_24,
- R.string.toolbar_customize_shortcut_share,
- ),
- ShortcutOption(
- ShortcutType.BOOKMARK,
- iconsR.drawable.mozac_ic_bookmark_24,
- R.string.toolbar_customize_shortcut_add_bookmark,
- ),
- ShortcutOption(
- ShortcutType.TRANSLATE,
- iconsR.drawable.mozac_ic_translate_24,
- R.string.toolbar_customize_shortcut_translate,
- ),
- ShortcutOption(
- ShortcutType.HOMEPAGE,
- iconsR.drawable.mozac_ic_home_24,
- R.string.toolbar_customize_shortcut_homepage,
- ),
- ShortcutOption(
- ShortcutType.BACK,
- iconsR.drawable.mozac_ic_back_24,
- R.string.toolbar_customize_shortcut_back,
- ),
- )
- }
-
- @ColorInt
- private var colorTertiary: Int = 0
-
- @ColorInt
- private var colorOnSurface: Int = 0
-
- @ColorInt
- private var colorOnSurfaceVariant: Int = 0
-
- init {
- layoutResource = R.layout.preference_toolbar_shortcut
- isSelectable = false
- }
-
- override fun onBindViewHolder(holder: PreferenceViewHolder) {
- super.onBindViewHolder(holder)
-
- val settings = context.settings()
- val selectedKey = settings.toolbarSimpleShortcutKey
-
- val selectedContainer = holder.findViewById(R.id.selected_container) as LinearLayout
- val optionsContainer = holder.findViewById(R.id.options_container) as LinearLayout
- val separator = holder.findViewById(R.id.separator) as View
-
- colorTertiary = holder.itemView.getMaterialColor(materialR.attr.colorTertiary)
- colorOnSurface = holder.itemView.getMaterialColor(materialR.attr.colorOnSurface)
- colorOnSurfaceVariant = holder.itemView.getMaterialColor(materialR.attr.colorOnSurfaceVariant)
-
- val selected = options.firstOrNull { it.key == selectedKey } ?: options.first()
-
- selectedContainer.removeAllViews()
- selectedContainer.addView(
- makeRow(
- parent = selectedContainer,
- option = selected,
- isChecked = true,
- isEnabled = false,
- onClick = {},
- ),
- )
-
- val remaining = options.filter { it.key != selected.key }.distinctBy { it.key }
- optionsContainer.removeAllViews()
- remaining.forEach { opt ->
- optionsContainer.addView(
- makeRow(
- parent = optionsContainer,
- option = opt,
- isChecked = false,
- isEnabled = true,
- ) { newlySelected ->
- settings.toolbarSimpleShortcutKey = newlySelected.key
- notifyChanged()
- },
- )
- }
+ override val options: List<ShortcutOption> = simpleShortcutOptions
- separator.visibility = if (remaining.isEmpty()) View.GONE else View.VISIBLE
- }
-
- private fun makeRow(
- parent: ViewGroup,
- option: ShortcutOption,
- isChecked: Boolean,
- isEnabled: Boolean,
- onClick: (ShortcutOption) -> Unit,
- ): View {
- val row = LayoutInflater.from(context)
- .inflate(R.layout.toolbar_shortcut_row, parent, false) as LinearLayout
-
- val radio = row.findViewById<RadioButton>(R.id.row_radio)
- val icon = row.findViewById<ImageView>(R.id.row_icon)
- val label = row.findViewById<TextView>(R.id.row_label)
-
- icon.setImageResource(option.icon)
- label.setText(option.label)
-
- radio?.setStartCheckedIndicator()
- radio.isChecked = isChecked
- radio.isEnabled = true
-
- label.setTextColor(
- if (isChecked) colorTertiary else colorOnSurface,
- )
-
- ImageViewCompat.setImageTintList(
- icon,
- ColorStateList.valueOf(
- if (isChecked) colorTertiary else colorOnSurface,
- ),
- )
-
- radio.buttonTintList = ColorStateList(
- arrayOf(
- intArrayOf(android.R.attr.state_checked),
- intArrayOf(-android.R.attr.state_checked),
- ),
- intArrayOf(colorTertiary, colorOnSurfaceVariant),
- )
-
- if (isEnabled) {
- val clicker = View.OnClickListener {
- onClick(option)
- }
- row.setOnClickListener(clicker)
- }
-
- row.isEnabled = isEnabled
-
- return row
- }
+ override fun readSelectedKey(): String? = context.settings().toolbarSimpleShortcutKey
- private fun View.getMaterialColor(@AttrRes attr: Int): Int {
- return MaterialColors.getColor(this, attr)
+ override fun writeSelectedKey(key: String) {
+ context.settings().toolbarSimpleShortcutKey = key
}
}