Merge remote-tracking branch 'abhijitvalluri/improved_tabs_tray' into fork

pull/50/head
Adam Novak 4 years ago
commit db86e42e53

@ -50,7 +50,7 @@ class SyncedTabsController(
.collect { mode -> .collect { mode ->
when (mode) { when (mode) {
is TabTrayDialogFragmentState.Mode.Normal -> { is TabTrayDialogFragmentState.Mode.Normal -> {
concatAdapter.addAdapter(0, adapter) concatAdapter.addAdapter(adapter)
} }
is TabTrayDialogFragmentState.Mode.MultiSelect -> { is TabTrayDialogFragmentState.Mode.MultiSelect -> {
concatAdapter.removeAdapter(adapter) concatAdapter.removeAdapter(adapter)
@ -63,8 +63,7 @@ class SyncedTabsController(
override fun displaySyncedTabs(syncedTabs: List<SyncedDeviceTabs>) { override fun displaySyncedTabs(syncedTabs: List<SyncedDeviceTabs>) {
scope.launch { scope.launch {
val tabsList = listOf(SyncedTabsAdapter.AdapterItem.Title) + syncedTabs.toAdapterList() val tabsList = listOf(SyncedTabsAdapter.AdapterItem.Title) + syncedTabs.toAdapterList()
// Reverse layout for TabTrayView which does things backwards. adapter.submitList(tabsList)
adapter.submitList(tabsList.reversed())
} }
} }

@ -22,7 +22,6 @@ import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.component_tabstray.view.* import kotlinx.android.synthetic.main.component_tabstray.view.*
import kotlinx.android.synthetic.main.component_tabstray_fab.view.*
import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.* import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.*
import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.view.* import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.view.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -67,8 +66,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
private lateinit var tabTrayDialogStore: TabTrayDialogFragmentStore private lateinit var tabTrayDialogStore: TabTrayDialogFragmentStore
private val snackbarAnchor: View? private val snackbarAnchor: View?
get() = if (tabTrayView.fabView.new_tab_button.isVisible) tabTrayView.fabView.new_tab_button get() = null
else null
private val collectionStorageObserver = object : TabCollectionStorage.Observer { private val collectionStorageObserver = object : TabCollectionStorage.Observer {
override fun onCollectionCreated(title: String, sessions: List<Session>) { override fun onCollectionCreated(title: String, sessions: List<Session>) {
@ -158,6 +156,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
if (newConfig.orientation != currentOrientation) { if (newConfig.orientation != currentOrientation) {
tabTrayView.dismissMenu() tabTrayView.dismissMenu()
tabTrayView.expand() tabTrayView.expand()
tabTrayView.updateTabsTrayLayout()
currentOrientation = newConfig.orientation currentOrientation = newConfig.orientation
} }
} }

@ -20,12 +20,11 @@ import androidx.core.view.updatePadding
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import kotlinx.android.extensions.LayoutContainer import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.component_tabstray.view.* import kotlinx.android.synthetic.main.component_tabstray.view.*
import kotlinx.android.synthetic.main.component_tabstray_fab.view.*
import kotlinx.android.synthetic.main.tabs_tray_tab_counter.* import kotlinx.android.synthetic.main.tabs_tray_tab_counter.*
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -68,10 +67,6 @@ class TabTrayView(
private val filterTabs: (Boolean) -> Unit private val filterTabs: (Boolean) -> Unit
) : LayoutContainer, TabLayout.OnTabSelectedListener { ) : LayoutContainer, TabLayout.OnTabSelectedListener {
val lifecycleScope = lifecycleOwner.lifecycleScope val lifecycleScope = lifecycleOwner.lifecycleScope
val fabView = LayoutInflater.from(container.context)
.inflate(R.layout.component_tabstray_fab, container, true)
private val hasAccessibilityEnabled = container.context.settings().accessibilityServicesEnabled
val view = LayoutInflater.from(container.context) val view = LayoutInflater.from(container.context)
.inflate(R.layout.component_tabstray, container, true) .inflate(R.layout.component_tabstray, container, true)
@ -100,17 +95,8 @@ class TabTrayView(
init { init {
components.analytics.metrics.track(Event.TabsTrayOpened) components.analytics.metrics.track(Event.TabsTrayOpened)
toggleFabText(isPrivate)
behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) { override fun onSlide(bottomSheet: View, slideOffset: Float) {
if (interactor.onModeRequested() is Mode.Normal && !hasAccessibilityEnabled) {
if (slideOffset >= SLIDE_OFFSET) {
fabView.new_tab_button.show()
} else {
fabView.new_tab_button.hide()
}
}
} }
override fun onStateChanged(bottomSheet: View, newState: Int) { override fun onStateChanged(bottomSheet: View, newState: Int) {
@ -163,11 +149,8 @@ class TabTrayView(
) )
} }
updateTabsTrayLayout()
view.tabsTray.apply { view.tabsTray.apply {
layoutManager = LinearLayoutManager(container.context).apply {
reverseLayout = true
stackFromEnd = true
}
adapter = concatAdapter adapter = concatAdapter
tabsTouchHelper = TabsTouchHelper( tabsTouchHelper = TabsTouchHelper(
@ -180,14 +163,11 @@ class TabTrayView(
tabsAdapter.tabTrayInteractor = interactor tabsAdapter.tabTrayInteractor = interactor
tabsAdapter.onTabsUpdated = { tabsAdapter.onTabsUpdated = {
// Put the 'Add to collections' button after the tabs have loaded. // Put the 'Add to collections' button after the tabs have loaded.
concatAdapter.addAdapter(0, collectionsButtonAdapter) concatAdapter.addAdapter(collectionsButtonAdapter)
// Put the Synced Tabs adapter at the end. // Put the Synced Tabs adapter at the end.
concatAdapter.addAdapter(0, syncedTabsController.adapter) concatAdapter.addAdapter(syncedTabsController.adapter)
if (hasAccessibilityEnabled) {
tabsAdapter.notifyDataSetChanged()
}
if (!hasLoaded) { if (!hasLoaded) {
hasLoaded = true hasLoaded = true
scrollToTab(view.context.components.core.store.state.selectedTabId) scrollToTab(view.context.components.core.store.state.selectedTabId)
@ -235,24 +215,24 @@ class TabTrayView(
} }
} }
adjustNewTabButtonsForNormalMode() adjustNewTabButtonForNormalMode()
}
private fun gridViewNumberOfCols(context: Context): Int {
val displayMetrics = context.resources.displayMetrics
val dpWidth = displayMetrics.widthPixels / displayMetrics.density
val columnWidthDp = 190
val columnCount = (dpWidth / columnWidthDp).toInt()
return if (columnCount >= 2) columnCount else 2
} }
private fun handleTabClicked(tab: SyncTab) { private fun handleTabClicked(tab: SyncTab) {
interactor.onSyncedTabClicked(tab) interactor.onSyncedTabClicked(tab)
} }
private fun adjustNewTabButtonsForNormalMode() { private fun adjustNewTabButtonForNormalMode() {
view.tab_tray_new_tab.apply { view.tab_tray_new_tab.apply {
isVisible = hasAccessibilityEnabled visibility = View.VISIBLE
setOnClickListener {
sendNewTabEvent(isPrivateModeSelected)
interactor.onNewTabTapped(isPrivateModeSelected)
}
}
fabView.new_tab_button.apply {
isVisible = !hasAccessibilityEnabled
setOnClickListener { setOnClickListener {
sendNewTabEvent(isPrivateModeSelected) sendNewTabEvent(isPrivateModeSelected)
interactor.onNewTabTapped(isPrivateModeSelected) interactor.onNewTabTapped(isPrivateModeSelected)
@ -270,6 +250,24 @@ class TabTrayView(
components.analytics.metrics.track(eventToSend) components.analytics.metrics.track(eventToSend)
} }
fun updateTabsTrayLayout() {
view.tabsTray.apply {
val gridLayoutManager = GridLayoutManager(container.context, gridViewNumberOfCols(container.context))
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
val numTabs = tabsAdapter.itemCount
return if (position < numTabs) {
1
} else {
gridViewNumberOfCols(container.context)
}
}
}
layoutManager = gridLayoutManager
}
}
fun expand() { fun expand() {
behavior.state = BottomSheetBehavior.STATE_EXPANDED behavior.state = BottomSheetBehavior.STATE_EXPANDED
} }
@ -286,7 +284,6 @@ class TabTrayView(
} }
override fun onTabSelected(tab: TabLayout.Tab?) { override fun onTabSelected(tab: TabLayout.Tab?) {
toggleFabText(isPrivateModeSelected)
filterTabs.invoke(isPrivateModeSelected) filterTabs.invoke(isPrivateModeSelected)
toggleSaveToCollectionButton(isPrivateModeSelected) toggleSaveToCollectionButton(isPrivateModeSelected)
@ -337,7 +334,6 @@ class TabTrayView(
toggleUIMultiselect(multiselect = true) toggleUIMultiselect(multiselect = true)
fabView.new_tab_button.isVisible = false
view.tab_tray_new_tab.isVisible = false view.tab_tray_new_tab.isVisible = false
view.collect_multi_select.isVisible = state.mode.selectedItems.isNotEmpty() view.collect_multi_select.isVisible = state.mode.selectedItems.isNotEmpty()
@ -410,7 +406,7 @@ class TabTrayView(
counter_text.text = updateTabCounter(browserState.normalTabs.size) counter_text.text = updateTabCounter(browserState.normalTabs.size)
updateTabCounterContentDescription(browserState.normalTabs.size) updateTabCounterContentDescription(browserState.normalTabs.size)
adjustNewTabButtonsForNormalMode() adjustNewTabButtonForNormalMode()
} }
private fun toggleUIMultiselect(multiselect: Boolean) { private fun toggleUIMultiselect(multiselect: Boolean) {
@ -514,18 +510,6 @@ class TabTrayView(
menu?.dismiss() menu?.dismiss()
} }
private fun toggleFabText(private: Boolean) {
if (private) {
fabView.new_tab_button.extend()
fabView.new_tab_button.contentDescription =
view.context.resources.getString(R.string.add_private_tab)
} else {
fabView.new_tab_button.shrink()
fabView.new_tab_button.contentDescription =
view.context.resources.getString(R.string.add_tab)
}
}
fun onBackPressed(): Boolean { fun onBackPressed(): Boolean {
return interactor.onBackPressed() return interactor.onBackPressed()
} }
@ -541,13 +525,7 @@ class TabTrayView(
val selectedBrowserTabIndex = tabs val selectedBrowserTabIndex = tabs
.indexOfFirst { it.id == sessionId } .indexOfFirst { it.id == sessionId }
// We offset the tab index by the number of items in the other adapters. layoutManager?.scrollToPosition(selectedBrowserTabIndex)
// We add the offset, because the layoutManager is initialized with `reverseLayout`.
val recyclerViewIndex = selectedBrowserTabIndex +
collectionsButtonAdapter.itemCount +
syncedTabsController.adapter.itemCount
layoutManager?.scrollToPosition(recyclerViewIndex)
} }
} }

@ -57,7 +57,6 @@ class TabTrayViewHolder(
itemView.findViewById(R.id.mozac_browser_tabstray_thumbnail) itemView.findViewById(R.id.mozac_browser_tabstray_thumbnail)
@VisibleForTesting @VisibleForTesting
internal val urlView: TextView? = itemView.findViewById(R.id.mozac_browser_tabstray_url)
private val playPauseButtonView: ImageButton = itemView.findViewById(R.id.play_pause_button) private val playPauseButtonView: ImageButton = itemView.findViewById(R.id.play_pause_button)
override var tab: Tab? = null override var tab: Tab? = null
@ -75,7 +74,6 @@ class TabTrayViewHolder(
// Basic text // Basic text
updateTitle(tab) updateTitle(tab)
updateUrl(tab)
updateCloseButtonDescription(tab.title) updateCloseButtonDescription(tab.title)
// Drawables and theme // Drawables and theme
@ -155,24 +153,6 @@ class TabTrayViewHolder(
titleView.text = title titleView.text = title
} }
private fun updateUrl(tab: Tab) {
// Truncate to MAX_URI_LENGTH to prevent the UI from locking up for
// extremely large URLs such as data URIs or bookmarklets. The same
// is done in the toolbar and awesomebar:
// https://github.com/mozilla-mobile/fenix/issues/1824
// https://github.com/mozilla-mobile/android-components/issues/6985
urlView?.apply {
text =
if (context.settings().shouldStripUrl) {
tab.url
.toShortUrl(itemView.context.components.publicSuffixList)
.take(MAX_URI_LENGTH)
} else {
tab.url.take(MAX_URI_LENGTH)
}
}
}
@VisibleForTesting @VisibleForTesting
internal fun updateBackgroundColor(isSelected: Boolean) { internal fun updateBackgroundColor(isSelected: Boolean) {
val color = if (isSelected) { val color = if (isSelected) {

@ -135,7 +135,7 @@
android:layout_height="48dp" android:layout_height="48dp"
android:background="?android:attr/selectableItemBackgroundBorderless" android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/add_tab" android:contentDescription="@string/add_tab"
android:visibility="gone" android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@id/tab_layout" app:layout_constraintBottom_toBottomOf="@id/tab_layout"
app:layout_constraintEnd_toStartOf="@id/tab_tray_overflow" app:layout_constraintEnd_toStartOf="@id/tab_tray_overflow"
app:layout_constraintTop_toTopOf="@id/tab_layout" app:layout_constraintTop_toTopOf="@id/tab_layout"

@ -1,22 +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/. -->
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/new_tab_button"
style="@style/TabTrayFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:scrollbars="none"
android:layout_margin="16dp"
android:backgroundTint="@color/accent_normal_theme"
android:contentDescription="@string/add_tab"
android:elevation="99dp"
android:text="@string/tab_drawer_fab_content"
android:textColor="@color/photonWhite"
app:elevation="99dp"
app:borderWidth="0dp"
app:icon="@drawable/ic_new"
app:iconTint="@color/photonWhite" />

@ -4,9 +4,10 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tab_item" android:id="@+id/tab_item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="88dp" android:layout_height="175dp"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:foreground="?android:selectableItemBackground"> android:foreground="?android:selectableItemBackground">
@ -15,22 +16,22 @@
android:id="@+id/play_pause_button" android:id="@+id/play_pause_button"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_marginStart="80dp" android:layout_marginTop="30dp"
android:layout_marginTop="4dp" android:layout_marginEnd="5dp"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/mozac_feature_media_notification_action_pause" android:contentDescription="@string/mozac_feature_media_notification_action_pause"
android:elevation="10dp" android:elevation="10dp"
android:visibility="gone" android:visibility="gone"
app:layout_constraintStart_toStartOf="@id/mozac_browser_tabstray_card" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/play_with_background" /> app:srcCompat="@drawable/play_with_background" />
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:id="@+id/mozac_browser_tabstray_card" android:id="@+id/mozac_browser_tabstray_card"
android:layout_width="@dimen/tab_tray_thumbnail_width" android:layout_width="match_parent"
android:layout_height="@dimen/tab_tray_thumbnail_height" android:layout_height="@dimen/tab_tray_thumbnail_height"
android:layout_marginStart="16dp" android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="40dp"
android:backgroundTint="?tabTrayThumbnailItemBackground" android:backgroundTint="?tabTrayThumbnailItemBackground"
app:cardBackgroundColor="@color/photonWhite" app:cardBackgroundColor="@color/photonWhite"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -78,39 +79,29 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:ellipsize="end" android:requiresFadingEdge="horizontal"
android:lines="1" android:fadingEdgeLength="30dp"
android:paddingStart="16dp" android:ellipsize="none"
android:paddingTop="22dp" android:singleLine="true"
android:paddingHorizontal="16dp"
android:paddingVertical="10dp"
android:textColor="@color/tab_tray_item_text_normal_theme" android:textColor="@color/tab_tray_item_text_normal_theme"
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="@id/mozac_browser_tabstray_close"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@id/mozac_browser_tabstray_card"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/mozac_browser_tabstray_url"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:ellipsize="end"
android:lines="1"
android:paddingStart="16dp"
android:textColor="@color/tab_tray_item_url_normal_theme"
android:textSize="14sp" android:textSize="14sp"
android:visibility="visible"
tools:text="Webpage tile that is long"
app:layout_constraintEnd_toStartOf="@id/mozac_browser_tabstray_close" app:layout_constraintEnd_toStartOf="@id/mozac_browser_tabstray_close"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@id/mozac_browser_tabstray_card" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/mozac_browser_tabstray_title" /> app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageButton <androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/mozac_browser_tabstray_close" android:id="@+id/mozac_browser_tabstray_close"
android:layout_width="48dp" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackgroundBorderless" android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/close_tab" android:contentDescription="@string/close_tab"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="@id/mozac_browser_tabstray_card"
app:layout_constraintBottom_toTopOf="@id/mozac_browser_tabstray_card"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/mozac_ic_close" app:srcCompat="@drawable/mozac_ic_close"

@ -157,8 +157,8 @@
<!-- Tabs Tray --> <!-- Tabs Tray -->
<dimen name="tab_tray_top_offset">40dp</dimen> <dimen name="tab_tray_top_offset">40dp</dimen>
<dimen name="tab_tray_thumbnail_width">92dp</dimen> <dimen name="tab_tray_thumbnail_width">125dp</dimen>
<dimen name="tab_tray_thumbnail_height">69dp</dimen> <dimen name="tab_tray_thumbnail_height">130dp</dimen>
<!-- Saved Logins Fragment --> <!-- Saved Logins Fragment -->
<dimen name="saved_logins_sort_menu_dropdown_chevron_icon_margin_start">10dp</dimen> <dimen name="saved_logins_sort_menu_dropdown_chevron_icon_margin_start">10dp</dimen>

Loading…
Cancel
Save