Skip to content

Commit

Permalink
For mozilla-mobile#21236: Separate tabs with the same search term int…
Browse files Browse the repository at this point in the history
…o a different section (mozilla-mobile#21177)

* For mozilla-mobile#21236: Separate tabs with the same search term into a different section in tabs tray

* Issue mozilla-mobile#21236: Scroll to selected tab + various tab fixes for groupings

* Issue mozilla-mobile#21236: Fix failing test

Co-authored-by: Jonathan Almeida <jalmeida@mozilla.com>
  • Loading branch information
2 people authored and pkirakosyan committed Sep 17, 2021
1 parent 2696a5e commit 7b321a0
Show file tree
Hide file tree
Showing 31 changed files with 1,159 additions and 221 deletions.
5 changes: 5 additions & 0 deletions app/src/main/java/org/mozilla/fenix/FeatureFlags.kt
Expand Up @@ -63,4 +63,9 @@ object FeatureFlags {
* Enables customizing the home screen
*/
val customizeHome = Config.channel.isNightlyOrDebug

/**
* Identifies and separates the tabs list with a group containing search term tabs.
*/
val tabGroupFeature = Config.channel.isNightlyOrDebug
}
50 changes: 31 additions & 19 deletions app/src/main/java/org/mozilla/fenix/tabstray/TrayPagerAdapter.kt
Expand Up @@ -10,16 +10,13 @@ import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.RecyclerView
import mozilla.components.browser.state.selector.normalTabs
import mozilla.components.browser.state.selector.privateTabs
import mozilla.components.browser.state.selector.selectedTab
import mozilla.components.browser.state.store.BrowserStore
import org.mozilla.fenix.sync.SyncedTabsAdapter
import org.mozilla.fenix.tabstray.browser.BrowserTabsAdapter
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
import org.mozilla.fenix.tabstray.browser.TitleHeaderAdapter
import org.mozilla.fenix.tabstray.browser.InactiveTabsAdapter
import org.mozilla.fenix.tabstray.browser.maxActiveTime
import org.mozilla.fenix.tabstray.ext.isNormalTabActive
import org.mozilla.fenix.tabstray.browser.TabGroupAdapter
import org.mozilla.fenix.tabstray.syncedtabs.TabClickDelegate
import org.mozilla.fenix.tabstray.viewholders.AbstractPageViewHolder
import org.mozilla.fenix.tabstray.viewholders.NormalBrowserPageViewHolder
Expand All @@ -28,48 +25,62 @@ import org.mozilla.fenix.tabstray.viewholders.SyncedTabsPageViewHolder

class TrayPagerAdapter(
@VisibleForTesting internal val context: Context,
@VisibleForTesting internal val store: TabsTrayStore,
@VisibleForTesting internal val tabsTrayStore: TabsTrayStore,
@VisibleForTesting internal val browserInteractor: BrowserTrayInteractor,
@VisibleForTesting internal val navInteractor: NavigationInteractor,
@VisibleForTesting internal val interactor: TabsTrayInteractor,
@VisibleForTesting internal val browserStore: BrowserStore
) : RecyclerView.Adapter<AbstractPageViewHolder>() {

/**
* ⚠️ N.B: Scrolling to the selected tab depends on the order of these adapters. If you change
* the ordering or add/remove an adapter, please update [NormalBrowserPageViewHolder.scrollToTab] and
* the layout manager.
*/
private val normalAdapter by lazy {
ConcatAdapter(
BrowserTabsAdapter(context, browserInteractor, store, TABS_TRAY_FEATURE_NAME),
InactiveTabsAdapter(context, browserInteractor, INACTIVE_TABS_FEATURE_NAME)
InactiveTabsAdapter(context, browserInteractor, INACTIVE_TABS_FEATURE_NAME),
TabGroupAdapter(context, browserInteractor, tabsTrayStore, TAB_GROUP_FEATURE_NAME),
TitleHeaderAdapter(browserStore),
BrowserTabsAdapter(context, browserInteractor, tabsTrayStore, TABS_TRAY_FEATURE_NAME)
)
}
private val privateAdapter by lazy { BrowserTabsAdapter(context, browserInteractor, store, TABS_TRAY_FEATURE_NAME) }
private val syncedTabsAdapter by lazy { SyncedTabsAdapter(TabClickDelegate(navInteractor)) }
private val privateAdapter by lazy {
BrowserTabsAdapter(
context,
browserInteractor,
tabsTrayStore,
TABS_TRAY_FEATURE_NAME
)
}
private val syncedTabsAdapter by lazy {
SyncedTabsAdapter(TabClickDelegate(navInteractor))
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractPageViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(viewType, parent, false)

val selectedTab = browserStore.state.selectedTab

return when (viewType) {
NormalBrowserPageViewHolder.LAYOUT_ID -> {
NormalBrowserPageViewHolder(
itemView,
store,
interactor,
browserStore.state.normalTabs.filter { it.isNormalTabActive(maxActiveTime) }.indexOf(selectedTab)
tabsTrayStore,
browserStore,
interactor
)
}
PrivateBrowserPageViewHolder.LAYOUT_ID -> {
PrivateBrowserPageViewHolder(
itemView,
store,
interactor,
browserStore.state.privateTabs.indexOf(selectedTab)
tabsTrayStore,
browserStore,
interactor
)
}
SyncedTabsPageViewHolder.LAYOUT_ID -> {
SyncedTabsPageViewHolder(
itemView,
store
tabsTrayStore
)
}
else -> throw IllegalStateException("Unknown viewType.")
Expand Down Expand Up @@ -106,6 +117,7 @@ class TrayPagerAdapter(

// Telemetry keys for identifying from which app features the a was opened / closed.
const val TABS_TRAY_FEATURE_NAME = "Tabs tray"
const val TAB_GROUP_FEATURE_NAME = "Tab group"
const val INACTIVE_TABS_FEATURE_NAME = "Inactive tabs"

val POSITION_NORMAL_TABS = Page.NormalTabs.ordinal
Expand Down

This file was deleted.

This file was deleted.

@@ -0,0 +1,120 @@
/* 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.tabstray.browser

import android.view.View
import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.AppCompatImageButton
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import mozilla.components.browser.tabstray.TabsTrayStyling
import mozilla.components.concept.base.images.ImageLoader
import mozilla.components.concept.tabstray.Tab
import mozilla.components.concept.tabstray.TabsTray
import mozilla.components.support.base.observer.Observable
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.TabTrayGridItemBinding
import org.mozilla.fenix.ext.increaseTapArea
import kotlin.math.max
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.TabsTrayStore

sealed class BrowserTabViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
/**
* A RecyclerView ViewHolder implementation for "tab" items with grid layout.
*
* @param imageLoader [ImageLoader] used to load tab thumbnails.
* @param browserTrayInteractor [BrowserTrayInteractor] handling tabs interactions in a tab tray.
* @param store [TabsTrayStore] containing the complete state of tabs tray and methods to update that.
* @param selectionHolder [SelectionHolder]<[Tab]> for helping with selecting any number of displayed [Tab]s.
* @param itemView [View] that displays a "tab".
* @param featureName [String] representing the name of the feature displaying tabs. Used in telemetry reporting.
*/
class GridViewHolder(
imageLoader: ImageLoader,
override val browserTrayInteractor: BrowserTrayInteractor,
store: TabsTrayStore,
selectionHolder: SelectionHolder<Tab>? = null,
itemView: View,
featureName: String
) : AbstractBrowserTabViewHolder(itemView, imageLoader, store, selectionHolder, featureName) {

private val closeButton: AppCompatImageButton = itemView.findViewById(R.id.mozac_browser_tabstray_close)

override val thumbnailSize: Int
get() = max(
itemView.resources.getDimensionPixelSize(R.dimen.tab_tray_grid_item_thumbnail_height),
itemView.resources.getDimensionPixelSize(R.dimen.tab_tray_grid_item_thumbnail_width)
)

override fun updateSelectedTabIndicator(showAsSelected: Boolean) {
val binding = TabTrayGridItemBinding.bind(itemView)
binding.tabTrayGridItem.background = if (showAsSelected) {
AppCompatResources.getDrawable(itemView.context, R.drawable.tab_tray_grid_item_selected_border)
} else {
null
}
return
}

override fun bind(
tab: Tab,
isSelected: Boolean,
styling: TabsTrayStyling,
observable: Observable<TabsTray.Observer>
) {
super.bind(tab, isSelected, styling, observable)

closeButton.increaseTapArea(GRID_ITEM_CLOSE_BUTTON_EXTRA_DPS)
}

companion object {
const val LAYOUT_ID = R.layout.tab_tray_grid_item
}
}

/**
* A RecyclerView ViewHolder implementation for "tab" items with list layout.
*
* @param imageLoader [ImageLoader] used to load tab thumbnails.
* @param browserTrayInteractor [BrowserTrayInteractor] handling tabs interactions in a tab tray.
* @param store [TabsTrayStore] containing the complete state of tabs tray and methods to update that.
* @param selectionHolder [SelectionHolder]<[Tab]> for helping with selecting any number of displayed [Tab]s.
* @param itemView [View] that displays a "tab".
* @param featureName [String] representing the name of the feature displaying tabs. Used in telemetry reporting.
*/
class ListViewHolder(
imageLoader: ImageLoader,
override val browserTrayInteractor: BrowserTrayInteractor,
store: TabsTrayStore,
selectionHolder: SelectionHolder<Tab>? = null,
itemView: View,
featureName: String
) : AbstractBrowserTabViewHolder(itemView, imageLoader, store, selectionHolder, featureName) {
override val thumbnailSize: Int
get() = max(
itemView.resources.getDimensionPixelSize(R.dimen.tab_tray_list_item_thumbnail_height),
itemView.resources.getDimensionPixelSize(R.dimen.tab_tray_list_item_thumbnail_width)
)

override fun updateSelectedTabIndicator(showAsSelected: Boolean) {
val color = if (showAsSelected) {
R.color.tab_tray_item_selected_background_normal_theme
} else {
R.color.tab_tray_item_background_normal_theme
}
itemView.setBackgroundColor(
ContextCompat.getColor(
itemView.context,
color
)
)
}

companion object {
const val LAYOUT_ID = R.layout.tab_tray_item
}
}
}

0 comments on commit 7b321a0

Please sign in to comment.