tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarExpandedShortcutPreference.kt | 151++++---------------------------------------------------------------------------
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarShortcut.kt | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Amobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarShortcutPreference.kt | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarSimpleShortcutPreference.kt | 176+++----------------------------------------------------------------------------
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 } }