For #16629 - Fix for collection snackbar View button (#16679)

upstream-sync
Codrut Topliceanu 4 years ago committed by GitHub
parent 8a579ee62b
commit 79d1c08402
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -247,7 +247,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
}
private val collectionStorageObserver = object : TabCollectionStorage.Observer {
override fun onCollectionCreated(title: String, sessions: List<Session>) {
override fun onCollectionCreated(title: String, sessions: List<Session>, id: Long?) {
showTabSavedToCollectionSnackbar(sessions.size, true)
}

@ -40,7 +40,7 @@ class TabCollectionStorage(
/**
* A collection has been created
*/
fun onCollectionCreated(title: String, sessions: List<Session>) = Unit
fun onCollectionCreated(title: String, sessions: List<Session>, id: Long?) = Unit
/**
* Tab(s) have been added to collection
@ -63,8 +63,8 @@ class TabCollectionStorage(
}
suspend fun createCollection(title: String, sessions: List<Session>) = ioScope.launch {
collectionStorage.createCollection(title, sessions)
notifyObservers { onCollectionCreated(title, sessions) }
val id = collectionStorage.createCollection(title, sessions)
notifyObservers { onCollectionCreated(title, sessions, id) }
}.join()
suspend fun addTabsToCollection(tabCollection: TabCollection, sessions: List<Session>) = ioScope.launch {

@ -39,6 +39,7 @@ import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_home.privateBrowsingButton
import kotlinx.android.synthetic.main.fragment_home.search_engine_icon
@ -62,10 +63,8 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import mozilla.appservices.places.BookmarkRoot
import mozilla.components.browser.menu.view.MenuButton
import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager
import mozilla.components.browser.state.selector.findTab
import mozilla.components.browser.state.selector.getNormalOrPrivateTabs
import mozilla.components.browser.state.selector.normalTabs
import mozilla.components.browser.state.selector.privateTabs
import mozilla.components.browser.state.state.BrowserState
@ -137,14 +136,6 @@ class HomeFragment : Fragment() {
private val browsingModeManager get() = (activity as HomeActivity).browsingModeManager
private val collectionStorageObserver = object : TabCollectionStorage.Observer {
override fun onCollectionCreated(title: String, sessions: List<Session>) {
scrollAndAnimateCollection()
}
override fun onTabsAdded(tabCollection: TabCollection, sessions: List<Session>) {
scrollAndAnimateCollection(tabCollection)
}
override fun onCollectionRenamed(tabCollection: TabCollection, title: String) {
lifecycleScope.launch(Main) {
view?.sessionControlRecyclerView?.adapter?.notifyDataSetChanged()
@ -170,6 +161,7 @@ class HomeFragment : Fragment() {
get() = _sessionControlInteractor!!
private var sessionControlView: SessionControlView? = null
private var appBarLayout: AppBarLayout? = null
private lateinit var currentMode: CurrentMode
private val topSitesFeature = ViewBoundFeatureWrapper<TopSitesFeature>()
@ -267,6 +259,8 @@ class HomeFragment : Fragment() {
updateSessionControlView(view)
appBarLayout = view.homeAppBar
activity.themeManager.applyStatusBarTheme(activity)
return view
}
@ -442,6 +436,12 @@ class HomeFragment : Fragment() {
if (bundleArgs.getBoolean(FOCUS_ON_ADDRESS_BAR)) {
navigateToSearch()
} else if (bundleArgs.getLong(FOCUS_ON_COLLECTION, -1) >= 0) {
// No need to scroll to async'd loaded TopSites if we want to scroll to collections.
homeViewModel.shouldScrollToTopSites = false
/* Triggered when the user has added a tab to a collection and has tapped
* the View action on the [TabsTrayDialogFragment] snackbar.*/
scrollAndAnimateCollection(bundleArgs.getLong(FOCUS_ON_COLLECTION, -1))
}
}
@ -848,31 +848,23 @@ class HomeFragment : Fragment() {
requireComponents.core.tabCollectionStorage.register(collectionStorageObserver, this)
}
/**
* This method will find and scroll to the row of the specified collection Id.
* */
private fun scrollAndAnimateCollection(
changedCollection: TabCollection? = null
collectionIdToSelect: Long = -1
) {
if (view != null) {
if (view != null && collectionIdToSelect >= 0) {
viewLifecycleOwner.lifecycleScope.launch {
val recyclerView = sessionControlView!!.view
delay(ANIM_SCROLL_DELAY)
val tabsSize = store.state
.getNormalOrPrivateTabs(browsingModeManager.mode.isPrivate)
.size
var indexOfCollection = tabsSize + NON_TAB_ITEM_NUM
changedCollection?.let { changedCollection ->
requireComponents.core.tabCollectionStorage.cachedTabCollections
.filterIndexed { index, tabCollection ->
if (tabCollection.id == changedCollection.id) {
indexOfCollection = tabsSize + NON_TAB_ITEM_NUM + index
return@filterIndexed true
}
false
}
}
val indexOfCollection =
NON_COLLECTION_ITEM_NUM + findIndexOfSpecificCollection(collectionIdToSelect)
val lastVisiblePosition =
(recyclerView.layoutManager as? LinearLayoutManager)?.findLastCompletelyVisibleItemPosition()
?: 0
if (lastVisiblePosition < indexOfCollection) {
val onScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(
@ -881,6 +873,7 @@ class HomeFragment : Fragment() {
) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == SCROLL_STATE_IDLE) {
appBarLayout?.setExpanded(false)
animateCollection(indexOfCollection)
recyclerView.removeOnScrollListener(this)
}
@ -889,12 +882,34 @@ class HomeFragment : Fragment() {
recyclerView.addOnScrollListener(onScrollListener)
recyclerView.smoothScrollToPosition(indexOfCollection)
} else {
appBarLayout?.setExpanded(false)
animateCollection(indexOfCollection)
}
}
}
}
/**
* Returns index of the collection with the specified id.
* */
private fun findIndexOfSpecificCollection(
changedCollectionId: Long
): Int {
var result = 0
requireComponents.core.tabCollectionStorage.cachedTabCollections
.filterIndexed { index, tabCollection ->
if (tabCollection.id == changedCollectionId) {
result = index
return@filterIndexed true
}
false
}
return result
}
/**
* Will highlight the border of the collection with the specified index.
* */
private fun animateCollection(indexOfCollection: Int) {
viewLifecycleOwner.lifecycleScope.launch {
val viewHolder =
@ -921,24 +936,6 @@ class HomeFragment : Fragment() {
border?.animate()?.alpha(1.0F)?.setStartDelay(ANIM_ON_SCREEN_DELAY)
?.setDuration(FADE_ANIM_DURATION)
?.setListener(listener)?.start()
}.invokeOnCompletion {
showSavedSnackbar()
}
}
private fun showSavedSnackbar() {
viewLifecycleOwner.lifecycleScope.launch {
delay(ANIM_SNACKBAR_DELAY)
view?.let { view ->
FenixSnackbar.make(
view = view,
duration = Snackbar.LENGTH_LONG,
isDisplayedWithBrowserToolbar = false
)
.setText(view.context.getString(R.string.create_collection_tabs_saved_new_collection))
.setAnchorView(snackbarAnchorView)
.show()
}
}
}
@ -983,13 +980,18 @@ class HomeFragment : Fragment() {
const val ALL_PRIVATE_TABS = "all_private"
private const val FOCUS_ON_ADDRESS_BAR = "focusOnAddressBar"
private const val FOCUS_ON_COLLECTION = "focusOnCollection"
private const val ANIMATION_DELAY = 100L
private const val NON_TAB_ITEM_NUM = 3
/**
* Represents the number of items in [sessionControlView] that are NOT part of
* the list of collections. At the moment these are topSites pager, collections header.
* */
private const val NON_COLLECTION_ITEM_NUM = 2
private const val ANIM_SCROLL_DELAY = 100L
private const val ANIM_ON_SCREEN_DELAY = 200L
private const val FADE_ANIM_DURATION = 150L
private const val ANIM_SNACKBAR_DELAY = 100L
private const val CFR_WIDTH_DIVIDER = 1.7
private const val CFR_Y_OFFSET = -20
}

@ -86,12 +86,15 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
else null
private val collectionStorageObserver = object : TabCollectionStorage.Observer {
override fun onCollectionCreated(title: String, sessions: List<Session>) {
showCollectionSnackbar(sessions.size, true)
override fun onCollectionCreated(title: String, sessions: List<Session>, id: Long?) {
showCollectionSnackbar(sessions.size, true, collectionToSelect = id)
}
override fun onTabsAdded(tabCollection: TabCollection, sessions: List<Session>) {
showCollectionSnackbar(sessions.size)
showCollectionSnackbar(
sessions.size,
collectionToSelect = tabCollection.id
)
}
}
@ -354,7 +357,11 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
requireComponents.core.tabCollectionStorage.register(collectionStorageObserver, this)
}
private fun showCollectionSnackbar(tabSize: Int, isNewCollection: Boolean = false) {
private fun showCollectionSnackbar(
tabSize: Int,
isNewCollection: Boolean = false,
collectionToSelect: Long?
) {
view.let {
val messageStringRes = when {
isNewCollection -> {
@ -378,7 +385,10 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
.setAction(requireContext().getString(R.string.create_collection_view)) {
dismissAllowingStateLoss()
findNavController().navigate(
TabTrayDialogFragmentDirections.actionGlobalHome(focusOnAddressBar = false)
TabTrayDialogFragmentDirections.actionGlobalHome(
focusOnAddressBar = false,
focusOnCollection = collectionToSelect ?: -1L
)
)
}

@ -138,6 +138,10 @@
android:name="focusOnAddressBar"
android:defaultValue="false"
app:argType="boolean" />
<argument
android:name="focusOnCollection"
android:defaultValue="-1L"
app:argType="long" />
</fragment>
<dialog

Loading…
Cancel
Save