* For #2899 - Scroll to Collections on change, animate new collections * For #2899 - Scroll to tabs when tabs opened from collectionmaster
parent
975975e789
commit
e57e7b50ee
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
package org.mozilla.fenix.home
|
package org.mozilla.fenix.home
|
||||||
|
|
||||||
|
import android.animation.Animator
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
|
@ -28,6 +29,7 @@ import kotlinx.android.synthetic.main.fragment_home.view.*
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import mozilla.components.browser.menu.BrowserMenu
|
import mozilla.components.browser.menu.BrowserMenu
|
||||||
|
@ -68,6 +70,7 @@ import org.mozilla.fenix.home.sessioncontrol.SessionControlViewModel
|
||||||
import org.mozilla.fenix.home.sessioncontrol.Tab
|
import org.mozilla.fenix.home.sessioncontrol.Tab
|
||||||
import org.mozilla.fenix.home.sessioncontrol.TabAction
|
import org.mozilla.fenix.home.sessioncontrol.TabAction
|
||||||
import org.mozilla.fenix.home.sessioncontrol.TabCollection
|
import org.mozilla.fenix.home.sessioncontrol.TabCollection
|
||||||
|
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionViewHolder
|
||||||
import org.mozilla.fenix.lib.Do
|
import org.mozilla.fenix.lib.Do
|
||||||
import org.mozilla.fenix.mvi.ActionBusFactory
|
import org.mozilla.fenix.mvi.ActionBusFactory
|
||||||
import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
||||||
|
@ -458,6 +461,10 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
|
||||||
action.collection.tabs.forEach {
|
action.collection.tabs.forEach {
|
||||||
requireComponents.useCases.tabsUseCases.addTab.invoke(it.url)
|
requireComponents.useCases.tabsUseCases.addTab.invoke(it.url)
|
||||||
}
|
}
|
||||||
|
launch {
|
||||||
|
delay(ANIM_SCROLL_DELAY)
|
||||||
|
sessionControlComponent.view.smoothScrollToPosition(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is CollectionAction.ShareTabs -> {
|
is CollectionAction.ShareTabs -> {
|
||||||
val shareTabs = action.collection.tabs.map { ShareTab(it.url, it.title) }
|
val shareTabs = action.collection.tabs.map { ShareTab(it.url, it.title) }
|
||||||
|
@ -709,10 +716,48 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
|
||||||
emitAccountChanges()
|
emitAccountChanges()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun scrollToCollections(addedTabsSize: Int) {
|
||||||
|
launch {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun animateTopCollection() {
|
||||||
|
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 border = (viewHolder as? CollectionViewHolder)?.view?.findViewById<View>(R.id.selected_border)
|
||||||
|
val listener = object : Animator.AnimatorListener {
|
||||||
|
override fun onAnimationCancel(animation: Animator?) {}
|
||||||
|
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)
|
||||||
|
?.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delay(ANIM_ON_SCREEN_DELAY)
|
||||||
|
border?.animate()?.alpha(1.0F)?.setDuration(FADE_ANIM_DURATION)?.setListener(listener)?.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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>) {
|
||||||
super.onCollectionCreated(title, sessions)
|
super.onCollectionCreated(title, sessions)
|
||||||
showSavedSnackbar(sessions.size)
|
scrollToCollections(sessions.size)
|
||||||
|
animateTopCollection()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabsAdded(
|
override fun onTabsAdded(
|
||||||
|
@ -720,7 +765,7 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
|
||||||
sessions: List<Session>
|
sessions: List<Session>
|
||||||
) {
|
) {
|
||||||
super.onTabsAdded(tabCollection, sessions)
|
super.onTabsAdded(tabCollection, sessions)
|
||||||
showSavedSnackbar(sessions.size)
|
scrollToCollections(sessions.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCollectionRenamed(
|
override fun onCollectionRenamed(
|
||||||
|
@ -755,6 +800,11 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val NON_TAB_ITEM_NUM = 3
|
||||||
|
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 SHARED_TRANSITION_MS = 200L
|
private const val SHARED_TRANSITION_MS = 200L
|
||||||
private const val TAB_ITEM_TRANSITION_NAME = "tab_item"
|
private const val TAB_ITEM_TRANSITION_NAME = "tab_item"
|
||||||
private const val toolbarPaddingDp = 12f
|
private const val toolbarPaddingDp = 12f
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:layout_marginTop="16dp">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/collection_icon"
|
android:id="@+id/collection_icon"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
android:importantForAccessibility="no"
|
android:importantForAccessibility="no"
|
||||||
android:src="@drawable/ic_tab_collection"
|
android:src="@drawable/ic_tab_collection"
|
||||||
android:tint="@null"
|
android:tint="@null"
|
||||||
|
@ -37,6 +37,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="12dp"
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
|
@ -55,7 +56,7 @@
|
||||||
android:id="@+id/chevron"
|
android:id="@+id/chevron"
|
||||||
android:layout_width="10dp"
|
android:layout_width="10dp"
|
||||||
android:layout_height="6dp"
|
android:layout_height="6dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="24dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:background="@drawable/ic_chevron_down"
|
android:background="@drawable/ic_chevron_down"
|
||||||
android:contentDescription="@string/tab_menu"
|
android:contentDescription="@string/tab_menu"
|
||||||
|
@ -95,11 +96,23 @@
|
||||||
android:id="@+id/collection_overflow_button"
|
android:id="@+id/collection_overflow_button"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="4.5dp"
|
android:layout_marginEnd="4.5dp"
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:contentDescription="@string/tab_menu"
|
android:contentDescription="@string/tab_menu"
|
||||||
android:src="@drawable/ic_menu"
|
android:src="@drawable/ic_menu"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/selected_border"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:alpha="0"
|
||||||
|
android:background="@drawable/session_border"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
Loading…
Reference in New Issue