diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index c6a097b35..3f04575c6 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -22,6 +22,9 @@ import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.navigation.fragment.FragmentNavigator import androidx.navigation.fragment.NavHostFragment.findNavController +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE import androidx.transition.TransitionInflater import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.fragment_home.* @@ -692,48 +695,71 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { emitAccountChanges() } - private fun scrollToCollections(addedTabsSize: Int) { + private fun scrollAndAnimateCollection(addedTabsSize: Int, changedCollection: TabCollection? = null) { launch { + val recyclerView = sessionControlComponent.view delay(ANIM_SCROLL_DELAY) val tabsSize = requireComponents.core.sessionManager.sessions.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private }.size - sessionControlComponent.view.smoothScrollToPosition(tabsSize + NON_TAB_ITEM_NUM) - delay(ANIM_SNACKBAR_DELAY) - showSavedSnackbar(addedTabsSize) + 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 lastVisiblePosition = + (recyclerView.layoutManager as? LinearLayoutManager)?.findLastCompletelyVisibleItemPosition() ?: 0 + if (lastVisiblePosition < indexOfCollection) { + val onScrollListener = object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + super.onScrollStateChanged(recyclerView, newState) + if (newState == SCROLL_STATE_IDLE) { + animateCollection(addedTabsSize = addedTabsSize, indexOfCollection = indexOfCollection) + recyclerView.removeOnScrollListener(this) + } + } + } + recyclerView.addOnScrollListener(onScrollListener) + recyclerView.smoothScrollToPosition(indexOfCollection) + } else { + animateCollection(addedTabsSize = addedTabsSize, indexOfCollection = indexOfCollection) + } } } - private fun animateTopCollection() { + private fun animateCollection(addedTabsSize: Int, indexOfCollection: Int) { launch { - delay(ANIM_SCROLL_DELAY) - val tabsSize = requireComponents.core.sessionManager.sessions.filter { - (activity as HomeActivity).browsingModeManager.isPrivate == it.private - }.size - val topCollectionPosition = tabsSize + NON_TAB_ITEM_NUM - sessionControlComponent.view.smoothScrollToPosition(topCollectionPosition) - val viewHolder = sessionControlComponent.view.findViewHolderForAdapterPosition(topCollectionPosition) + val viewHolder = sessionControlComponent.view.findViewHolderForAdapterPosition(indexOfCollection) val border = (viewHolder as? CollectionViewHolder)?.view?.findViewById(R.id.selected_border) val listener = object : Animator.AnimatorListener { - override fun onAnimationCancel(animation: Animator?) {} + override fun onAnimationCancel(animation: Animator?) { + border?.visibility = View.GONE + } + override fun onAnimationStart(animation: Animator?) {} override fun onAnimationRepeat(animation: Animator?) {} override fun onAnimationEnd(animation: Animator?) { - border?.animate()?.alpha(0.0F)?.setDuration(FADE_ANIM_DURATION) - ?.setStartDelay(ANIM_ON_SCREEN_DELAY) + border?.animate()?.alpha(0.0F)?.setStartDelay(ANIM_ON_SCREEN_DELAY) + ?.setDuration(FADE_ANIM_DURATION) ?.start() } } - delay(ANIM_ON_SCREEN_DELAY) - border?.animate()?.alpha(1.0F)?.setDuration(FADE_ANIM_DURATION)?.setListener(listener)?.start() + border?.animate()?.alpha(1.0F)?.setStartDelay(ANIM_ON_SCREEN_DELAY)?.setDuration(FADE_ANIM_DURATION) + ?.setListener(listener)?.start() + }.invokeOnCompletion { + showSavedSnackbar(addedTabsSize) } } private val collectionStorageObserver = object : TabCollectionStorage.Observer { override fun onCollectionCreated(title: String, sessions: List) { super.onCollectionCreated(title, sessions) - scrollToCollections(sessions.size) - animateTopCollection() + scrollAndAnimateCollection(sessions.size) } override fun onTabsAdded( @@ -741,7 +767,7 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { sessions: List ) { super.onTabsAdded(tabCollection, sessions) - scrollToCollections(sessions.size) + scrollAndAnimateCollection(sessions.size, tabCollection) } override fun onCollectionRenamed( @@ -754,13 +780,16 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { } private fun showSavedSnackbar(tabSize: Int) { - context?.let { context: Context -> - view?.let { view: View -> - val string = - if (tabSize > 1) context.getString(R.string.create_collection_tabs_saved) else - context.getString(R.string.create_collection_tab_saved) - val snackbar = FenixSnackbar.make(view, Snackbar.LENGTH_LONG).setText(string) - snackbar.show() + launch { + delay(ANIM_SNACKBAR_DELAY) + context?.let { context: Context -> + view?.let { view: View -> + val string = + if (tabSize > 1) context.getString(R.string.create_collection_tabs_saved) else + context.getString(R.string.create_collection_tab_saved) + val snackbar = FenixSnackbar.make(view, Snackbar.LENGTH_LONG).setText(string) + snackbar.show() + } } } } @@ -780,7 +809,7 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { 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 = 500L + private const val ANIM_SNACKBAR_DELAY = 100L private const val SHARED_TRANSITION_MS = 200L private const val TAB_ITEM_TRANSITION_NAME = "tab_item" private const val toolbarPaddingDp = 12f