tor-browser

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

commit 4eee14a8bba5e2a058882ea55c35c0680fa4e13c
parent 577185e60ee2ab7af834102130c2459de80a586d
Author: Moyin <madeyemi@mozilla.com>
Date:   Tue, 16 Dec 2025 17:32:26 +0000

Bug 2002551 - Retain options order when selecting Toolbar shortcut r=android-reviewers,RJ

- Updated the Shortcut options to use a `RadioButtonPreference`
- Reduced code duplication by using dynamic layouts

Differential Revision: https://phabricator.services.mozilla.com/D275795

Diffstat:
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/CustomizationFragment.kt | 43++++++++++++++++++++++++++-----------------
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarShortcutPreference.kt | 130++++++++++++++++++++++---------------------------------------------------------
Mmobile/android/fenix/app/src/main/res/layout/preference_toolbar_shortcut.xml | 21---------------------
Dmobile/android/fenix/app/src/main/res/layout/toolbar_shortcut_row.xml | 39---------------------------------------
Mmobile/android/fenix/app/src/main/res/values/preference_keys.xml | 3+--
Mmobile/android/fenix/app/src/main/res/xml/customization_preferences.xml | 26++++----------------------
6 files changed, 67 insertions(+), 195 deletions(-)

diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/CustomizationFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/CustomizationFragment.kt @@ -93,26 +93,35 @@ class CustomizationFragment : PreferenceFragmentCompat() { } private fun updateToolbarShortcut() { - val simpleCategory = requirePreference<PreferenceCategory>( - R.string.pref_key_customization_category_toolbar_simple_shortcut, - ) - val expandedCategory = requirePreference<PreferenceCategory>( - R.string.pref_key_customization_category_toolbar_expanded_shortcut, + val category = requirePreference<PreferenceCategory>( + R.string.pref_key_customization_category_toolbar_shortcut, ) val settings = requireContext().settings() val isExpandedToolbarEnabled = settings.shouldUseExpandedToolbar && isTallWindow() && !isWideWindow() - - simpleCategory.isVisible = - settings.shouldShowToolbarCustomization && - settings.shouldUseComposableToolbar && - settings.toolbarRedesignEnabled && - !isExpandedToolbarEnabled - - expandedCategory.isVisible = - settings.shouldShowToolbarCustomization && - settings.shouldUseComposableToolbar && - settings.toolbarRedesignEnabled && - isExpandedToolbarEnabled + val shouldShowShortcutCategory = settings.shouldShowToolbarCustomization && + settings.shouldUseComposableToolbar && + settings.toolbarRedesignEnabled + + category.isVisible = shouldShowShortcutCategory + if (shouldShowShortcutCategory) { + val shortcutPreference = if (isExpandedToolbarEnabled) { + ToolbarExpandedShortcutPreference(requireContext()).apply { + key = getString(R.string.pref_key_toolbar_expanded_shortcut) + layoutResource = R.layout.preference_toolbar_shortcut + } + } else { + ToolbarSimpleShortcutPreference(requireContext()).apply { + key = getString(R.string.pref_key_toolbar_simple_shortcut) + layoutResource = R.layout.preference_toolbar_shortcut + } + } + category.apply { + removeAll() + addPreference(shortcutPreference) + val shortcutOptions = shortcutPreference.getShortcutOptions() + shortcutOptions.forEach(::addPreference) + } + } } private fun setupRadioGroups() { 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 @@ -5,23 +5,17 @@ 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.GleanMetrics.CustomizationSettings import org.mozilla.fenix.R +import org.mozilla.fenix.utils.view.addToRadioGroup import com.google.android.material.R as materialR /** @@ -57,105 +51,53 @@ internal abstract class ToolbarShortcutPreference @JvmOverloads constructor( super.onBindViewHolder(holder) val selectedIcon = getSelectedIconImageView(holder) - 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) + selectedIcon.setImageResource(getSelectedOption().icon) + } + + private fun getSelectedOption(): ShortcutOption { val selectedKey = readSelectedKey() - val selected = options.firstOrNull { + return options.firstOrNull { it.key == ShortcutType.fromValue(selectedKey) } ?: options.first() - selectedIcon.setImageResource(selected.icon) - 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 -> - CustomizationSettings.toolbarShortcutSelection.record( - CustomizationSettings.ToolbarShortcutSelectionExtra( - toolbarType = getToolbarType(), - item = newlySelected.key.value, - ), - ) - writeSelectedKey(newlySelected.key.value) - selectedIcon.setImageResource(newlySelected.icon) - notifyChanged() - }, - ) - } + } - separator.visibility = if (remaining.isEmpty()) View.GONE else View.VISIBLE + @Suppress("SpreadOperator") + fun getShortcutOptions(): List<RadioButtonPreference> { + val shortcutOptions = options + .distinctBy { it.key } + .map { newOption -> + createShortcutRadioButton( + newOption = newOption, + selectedOption = getSelectedOption(), + ) + } + + addToRadioGroup(*shortcutOptions.toTypedArray()) + return shortcutOptions } - 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), - ) - - row.isEnabled = isEnabled - row.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES - - if (isEnabled) { - val clicker = View.OnClickListener { onClick(option) } - row.setOnClickListener(clicker) + private fun createShortcutRadioButton( + newOption: ShortcutOption, + selectedOption: ShortcutOption, + ): RadioButtonPreference = RadioButtonPreference(context).apply { + key = newOption.key.value + title = context.getString(newOption.label) + setCheckedWithoutClickListener(newOption == selectedOption) + onClickListener { + CustomizationSettings.toolbarShortcutSelection.record( + CustomizationSettings.ToolbarShortcutSelectionExtra( + toolbarType = getToolbarType(), + item = newOption.key.value, + ), + ) + writeSelectedKey(newOption.key.value) + notifyChanged() } - - return row } private fun View.getMaterialColor( diff --git a/mobile/android/fenix/app/src/main/res/layout/preference_toolbar_shortcut.xml b/mobile/android/fenix/app/src/main/res/layout/preference_toolbar_shortcut.xml @@ -29,25 +29,4 @@ android:id="@+id/toolbar_expanded_shortcut_preview" layout="@layout/toolbar_expanded_shortcut_preview" android:visibility="gone" /> - - <LinearLayout - android:id="@+id/selected_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:paddingTop="8dp" /> - - <View - android:id="@+id/separator" - android:layout_width="match_parent" - android:layout_height="1dp" - android:alpha="0.12" - android:background="?attr/colorOnSurface" - android:visibility="gone" /> - - <LinearLayout - android:id="@+id/options_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" /> </LinearLayout> diff --git a/mobile/android/fenix/app/src/main/res/layout/toolbar_shortcut_row.xml b/mobile/android/fenix/app/src/main/res/layout/toolbar_shortcut_row.xml @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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/. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:layout_width="match_parent" - android:layout_height="48dp" - android:gravity="center_vertical" - android:orientation="horizontal" - android:paddingStart="@dimen/top_bar_no_icon_alignment_margin_start" - android:paddingEnd="16dp" - android:foreground="?android:attr/selectableItemBackground"> - - <RadioButton - android:id="@+id/row_radio" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:minWidth="0dp" - android:padding="0dp" - android:focusable="false" - android:clickable="false" - android:button="@null"/> - - <ImageView - android:id="@+id/row_icon" - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_marginStart="@dimen/top_bar_no_icon_alignment_margin_start" - android:layout_marginEnd="8dp" - android:contentDescription="@null" /> - - <TextView - android:id="@+id/row_label" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textAppearance="?android:attr/textAppearanceListItem" /> -</LinearLayout> diff --git a/mobile/android/fenix/app/src/main/res/values/preference_keys.xml b/mobile/android/fenix/app/src/main/res/values/preference_keys.xml @@ -207,8 +207,7 @@ <string name="pref_key_customization_category_toolbar" translatable="false">pref_key_customization_category_toolbar</string> <string name="pref_key_customization_category_toolbar_layout" translatable="false">pref_key_customization_category_toolbar_layout</string> <string name="pref_key_customization_category_app_icon" translatable="false">pref_key_customization_category_app_icon</string> - <string name="pref_key_customization_category_toolbar_simple_shortcut" translatable="false">pref_key_customization_category_toolbar_simple_shortcut</string> - <string name="pref_key_customization_category_toolbar_expanded_shortcut" translatable="false">pref_key_customization_category_toolbar_expanded_shortcut</string> + <string name="pref_key_customization_category_toolbar_shortcut" translatable="false">pref_key_customization_category_toolbar_shortcut</string> <string name="pref_key_toolbar_simple_shortcut" translatable="false">pref_key_toolbar_simple_shortcut</string> <string name="pref_key_toolbar_expanded_shortcut" translatable="false">pref_key_toolbar_expanded_shortcut</string> diff --git a/mobile/android/fenix/app/src/main/res/xml/customization_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/customization_preferences.xml @@ -82,31 +82,13 @@ app:trueOptionTitle="@string/preference_expanded_toolbar" /> </androidx.preference.PreferenceCategory> - <!-- Simple toolbar shortcut picker --> + <!-- Toolbar shortcut picker --> <androidx.preference.PreferenceCategory + android:key="@string/pref_key_customization_category_toolbar_shortcut" android:layout="@layout/preference_cat_style" android:title="@string/preferences_toolbar_shortcut" - android:key="@string/pref_key_customization_category_toolbar_simple_shortcut" - app:iconSpaceReserved="false"> - - <!-- Custom preference shows the selected option on top --> - <org.mozilla.fenix.settings.ToolbarSimpleShortcutPreference - android:key="@string/pref_key_toolbar_simple_shortcut" - android:layout="@layout/preference_toolbar_shortcut"/> - </androidx.preference.PreferenceCategory> - - <!-- Expanded toolbar shortcut picker --> - <androidx.preference.PreferenceCategory - android:layout="@layout/preference_cat_style" - android:title="@string/preferences_toolbar_shortcut" - android:key="@string/pref_key_customization_category_toolbar_expanded_shortcut" - app:iconSpaceReserved="false"> - - <!-- Custom preference shows the selected option on top --> - <org.mozilla.fenix.settings.ToolbarExpandedShortcutPreference - android:key="@string/pref_key_toolbar_expanded_shortcut" - android:layout="@layout/preference_toolbar_shortcut"/> - </androidx.preference.PreferenceCategory> + android:visible="false" + app:iconSpaceReserved="false" /> <androidx.preference.PreferenceCategory android:layout="@layout/preference_cat_style"