Closes #4602 - Add back transitions

nightly-build-test
Emily Kager 5 years ago committed by Jeff Boek
parent 4566bd6fba
commit 0b98d43c23

@ -16,6 +16,7 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.NavHostFragment.findNavController import androidx.navigation.fragment.NavHostFragment.findNavController
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.transition.TransitionInflater
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.component_search.* import kotlinx.android.synthetic.main.component_search.*
import kotlinx.android.synthetic.main.fragment_browser.view.* import kotlinx.android.synthetic.main.fragment_browser.view.*
@ -66,19 +67,21 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
private val customTabsIntegration = ViewBoundFeatureWrapper<CustomTabsIntegration>() private val customTabsIntegration = ViewBoundFeatureWrapper<CustomTabsIntegration>()
private var findBookmarkJob: Job? = null private var findBookmarkJob: Job? = null
/*
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// Disabled while awaiting a better solution to #3209
postponeEnterTransition() postponeEnterTransition()
sharedElementEnterTransition = sharedElementEnterTransition =
TransitionInflater.from(context).inflateTransition(android.R.transition.move).setDuration( TransitionInflater.from(context).inflateTransition(android.R.transition.move)
SHARED_TRANSITION_MS .setDuration(
) SHARED_TRANSITION_MS
)
} }
*/
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val view = super.onCreateView(inflater, container, savedInstanceState) val view = super.onCreateView(inflater, container, savedInstanceState)
view.browserLayout.transitionName = "$TAB_ITEM_TRANSITION_NAME${getSessionById()?.id}" view.browserLayout.transitionName = "$TAB_ITEM_TRANSITION_NAME${getSessionById()?.id}"
@ -96,7 +99,8 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
val sessionManager = requireComponents.core.sessionManager val sessionManager = requireComponents.core.sessionManager
getSessionById()?.let { getSessionById()?.let {
quickActionSheetView = QuickActionSheetView(view.nestedScrollQuickAction, browserInteractor) quickActionSheetView =
QuickActionSheetView(view.nestedScrollQuickAction, browserInteractor)
customTabSessionId?.let { customTabSessionId -> customTabSessionId?.let { customTabSessionId ->
customTabsIntegration.set( customTabsIntegration.set(
@ -137,13 +141,17 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
requireComponents.core.sessionManager, requireComponents.core.sessionManager,
view.readerViewControlsBar view.readerViewControlsBar
) { available -> ) { available ->
if (available) { requireComponents.analytics.metrics.track(Event.ReaderModeAvailable) } if (available) {
requireComponents.analytics.metrics.track(Event.ReaderModeAvailable)
}
browserStore.apply { browserStore.apply {
dispatch(QuickActionSheetAction.ReadableStateChange(available)) dispatch(QuickActionSheetAction.ReadableStateChange(available))
dispatch(QuickActionSheetAction.ReaderActiveStateChange( dispatch(
sessionManager.selectedSession?.readerMode ?: false QuickActionSheetAction.ReaderActiveStateChange(
)) sessionManager.selectedSession?.readerMode ?: false
)
)
} }
}, },
owner = this, owner = this,
@ -183,7 +191,9 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
if (customTabsIntegration.onBackPressed()) return true if (customTabsIntegration.onBackPressed()) return true
getSessionById()?.let { session -> getSessionById()?.let { session ->
if (session.source == Session.Source.ACTION_VIEW) requireComponents.core.sessionManager.remove(session) if (session.source == Session.Source.ACTION_VIEW) requireComponents.core.sessionManager.remove(
session
)
} }
return false return false
} }
@ -198,7 +208,8 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
quickActionSheetController = DefaultQuickActionSheetController( quickActionSheetController = DefaultQuickActionSheetController(
context = context!!, context = context!!,
navController = findNavController(), navController = findNavController(),
currentSession = getSessionById() ?: requireComponents.core.sessionManager.selectedSessionOrThrow, currentSession = getSessionById()
?: requireComponents.core.sessionManager.selectedSessionOrThrow,
appLinksUseCases = requireComponents.useCases.appLinksUseCases, appLinksUseCases = requireComponents.useCases.appLinksUseCases,
bookmarkTapped = { bookmarkTapped = {
lifecycleScope.launch { bookmarkTapped(it) } lifecycleScope.launch { bookmarkTapped(it) }
@ -214,7 +225,8 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
return if (customTabSessionId != null) Pair(toolbarSize, 0) else Pair(0, toolbarAndQASSize) return if (customTabSessionId != null) Pair(toolbarSize, 0) else Pair(0, toolbarAndQASSize)
} }
override fun getAppropriateLayoutGravity() = if (customTabSessionId != null) Gravity.TOP else Gravity.BOTTOM override fun getAppropriateLayoutGravity() =
if (customTabSessionId != null) Gravity.TOP else Gravity.BOTTOM
private fun themeReaderViewControlsForPrivateMode(view: View) = with(view) { private fun themeReaderViewControlsForPrivateMode(view: View) = with(view) {
listOf( listOf(
@ -223,7 +235,12 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
).map { ).map {
findViewById<Button>(it) findViewById<Button>(it)
}.forEach { }.forEach {
it.setTextColor(ContextCompat.getColorStateList(context, R.color.readerview_private_button_color)) it.setTextColor(
ContextCompat.getColorStateList(
context,
R.color.readerview_private_button_color
)
)
} }
listOf( listOf(
@ -232,13 +249,19 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
).map { ).map {
findViewById<RadioButton>(it) findViewById<RadioButton>(it)
}.forEach { }.forEach {
it.setTextColor(ContextCompat.getColorStateList(context, R.color.readerview_private_radio_color)) it.setTextColor(
ContextCompat.getColorStateList(
context,
R.color.readerview_private_radio_color
)
)
} }
} }
private suspend fun bookmarkTapped(session: Session) = withContext(IO) { private suspend fun bookmarkTapped(session: Session) = withContext(IO) {
val bookmarksStorage = requireComponents.core.bookmarksStorage val bookmarksStorage = requireComponents.core.bookmarksStorage
val existing = bookmarksStorage.getBookmarksWithUrl(session.url).firstOrNull { it.url == session.url } val existing =
bookmarksStorage.getBookmarksWithUrl(session.url).firstOrNull { it.url == session.url }
if (existing != null) { if (existing != null) {
// Bookmark exists, go to edit fragment // Bookmark exists, go to edit fragment
withContext(Main) { withContext(Main) {
@ -268,7 +291,9 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
.setAction(getString(R.string.edit_bookmark_snackbar_action)) { .setAction(getString(R.string.edit_bookmark_snackbar_action)) {
nav( nav(
R.id.browserFragment, R.id.browserFragment,
BrowserFragmentDirections.actionBrowserFragmentToBookmarkEditFragment(guid) BrowserFragmentDirections.actionBrowserFragmentToBookmarkEditFragment(
guid
)
) )
} }
.setText(getString(R.string.bookmark_saved_snackbar)) .setText(getString(R.string.bookmark_saved_snackbar))
@ -281,7 +306,11 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
private fun subscribeToTabCollections() { private fun subscribeToTabCollections() {
requireComponents.core.tabCollectionStorage.getCollections().observe(this, Observer { requireComponents.core.tabCollectionStorage.getCollections().observe(this, Observer {
requireComponents.core.tabCollectionStorage.cachedTabCollections = it requireComponents.core.tabCollectionStorage.cachedTabCollections = it
getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.CollectionsChange(it)) getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.CollectionsChange(
it
)
)
}) })
} }

@ -97,6 +97,7 @@ class BrowserToolbarView(
toolbarIntegration = ToolbarIntegration( toolbarIntegration = ToolbarIntegration(
this, this,
view, view,
container,
menuToolbar, menuToolbar,
ShippedDomainsProvider().also { it.initialize(this) }, ShippedDomainsProvider().also { it.initialize(this) },
components.core.historyStorage, components.core.historyStorage,

@ -5,8 +5,10 @@
package org.mozilla.fenix.components.toolbar package org.mozilla.fenix.components.toolbar
import android.content.Context import android.content.Context
import android.view.ViewGroup
import androidx.navigation.NavOptions import androidx.navigation.NavOptions
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.navigation.fragment.FragmentNavigator
import mozilla.components.browser.domains.autocomplete.DomainAutocompleteProvider import mozilla.components.browser.domains.autocomplete.DomainAutocompleteProvider
import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.SessionManager
import mozilla.components.browser.session.runWithSession import mozilla.components.browser.session.runWithSession
@ -27,6 +29,7 @@ import org.mozilla.fenix.utils.Settings
class ToolbarIntegration( class ToolbarIntegration(
context: Context, context: Context,
toolbar: BrowserToolbar, toolbar: BrowserToolbar,
browserLayout: ViewGroup,
toolbarMenu: ToolbarMenu, toolbarMenu: ToolbarMenu,
domainAutocompleteProvider: DomainAutocompleteProvider, domainAutocompleteProvider: DomainAutocompleteProvider,
historyStorage: HistoryStorage, historyStorage: HistoryStorage,
@ -57,15 +60,13 @@ class ToolbarIntegration(
// We need to dynamically add the options here because if you do it in XML it overwrites // We need to dynamically add the options here because if you do it in XML it overwrites
val options = NavOptions.Builder().setPopUpTo(R.id.nav_graph, false) val options = NavOptions.Builder().setPopUpTo(R.id.nav_graph, false)
.setEnterAnim(R.anim.fade_in).build() .setEnterAnim(R.anim.fade_in).build()
val extras = null val extras =
// Disabled while awaiting a better solution to #3209 FragmentNavigator.Extras.Builder()
// val extras = .addSharedElement(
// FragmentNavigator.Extras.Builder() browserLayout,
// .addSharedElement( "$TAB_ITEM_TRANSITION_NAME${sessionManager.selectedSession?.id}"
// browserLayout, )
// "$TAB_ITEM_TRANSITION_NAME${sessionManager.selectedSession?.id}" .build()
// )
// .build()
val navController = Navigation.findNavController(toolbar) val navController = Navigation.findNavController(toolbar)
if (!navController.popBackStack( if (!navController.popBackStack(
R.id.homeFragment, R.id.homeFragment,
@ -104,7 +105,8 @@ class ToolbarIntegration(
ThemeManager.resolveAttribute(R.attr.primaryText, context), renderStyle = renderStyle ThemeManager.resolveAttribute(R.attr.primaryText, context), renderStyle = renderStyle
) )
) )
private var menuPresenter = MenuPresenter(toolbar, context.components.core.sessionManager, sessionId) private var menuPresenter =
MenuPresenter(toolbar, context.components.core.sessionManager, sessionId)
override fun start() { override fun start() {
menuPresenter.start() menuPresenter.start()

@ -25,10 +25,12 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.FragmentNavigator
import androidx.navigation.fragment.NavHostFragment.findNavController import androidx.navigation.fragment.NavHostFragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE
import androidx.transition.TransitionInflater
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_home.* import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.android.synthetic.main.fragment_home.view.* import kotlinx.android.synthetic.main.fragment_home.view.*
@ -114,8 +116,10 @@ class HomeFragment : Fragment(), AccountObserver {
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
delay(ANIM_SCROLL_DELAY) delay(ANIM_SCROLL_DELAY)
restoreLayoutState() restoreLayoutState()
// startPostponedEnterTransition() startPostponedEnterTransition()
}.invokeOnCompletion { sessionControlComponent.view.viewTreeObserver.removeOnPreDrawListener(this) } }.invokeOnCompletion {
sessionControlComponent.view.viewTreeObserver.removeOnPreDrawListener(this)
}
} }
return true return true
} }
@ -136,10 +140,10 @@ class HomeFragment : Fragment(), AccountObserver {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// Disabled while awaiting a better solution to #3209 postponeEnterTransition()
// postponeEnterTransition() sharedElementEnterTransition =
// sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move) TransitionInflater.from(context).inflateTransition(android.R.transition.move)
// .setDuration(SHARED_TRANSITION_MS) .setDuration(SHARED_TRANSITION_MS)
val sessionObserver = BrowserSessionsObserver(sessionManager, singleSessionObserver) { val sessionObserver = BrowserSessionsObserver(sessionManager, singleSessionObserver) {
emitSessionChanges() emitSessionChanges()
@ -189,12 +193,11 @@ class HomeFragment : Fragment(), AccountObserver {
} }
} }
// postponeEnterTransition()
ActionBusFactory.get(this).logMergedObservables() ActionBusFactory.get(this).logMergedObservables()
val activity = activity as HomeActivity val activity = activity as HomeActivity
ThemeManager.applyStatusBarTheme(activity.window, activity.themeManager, activity) ThemeManager.applyStatusBarTheme(activity.window, activity.themeManager, activity)
postponeEnterTransition()
sessionControlComponent.view.viewTreeObserver.addOnPreDrawListener(preDrawListener) sessionControlComponent.view.viewTreeObserver.addOnPreDrawListener(preDrawListener)
return view return view
@ -208,9 +211,7 @@ class HomeFragment : Fragment(), AccountObserver {
homeViewModel?.layoutManagerState?.also { parcelable -> homeViewModel?.layoutManagerState?.also { parcelable ->
sessionControlComponent.view.layoutManager?.onRestoreInstanceState(parcelable) sessionControlComponent.view.layoutManager?.onRestoreInstanceState(parcelable)
} }
val progress = homeViewModel?.motionLayoutProgress homeLayout?.progress = homeViewModel?.motionLayoutProgress ?: 0F
homeLayout?.progress =
if (progress ?: 0F > MOTION_LAYOUT_PROGRESS_ROUND_POINT) 1.0f else 0f
homeViewModel?.layoutManagerState = null homeViewModel?.layoutManagerState = null
} }
@ -223,7 +224,8 @@ class HomeFragment : Fragment(), AccountObserver {
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
val iconSize = resources.getDimension(R.dimen.preference_icon_drawable_size).toInt() val iconSize = resources.getDimension(R.dimen.preference_icon_drawable_size).toInt()
val searchEngine = requireComponents.search.searchEngineManager.getDefaultSearchEngine(requireContext()) val searchEngine =
requireComponents.search.searchEngineManager.getDefaultSearchEngine(requireContext())
val searchIcon = BitmapDrawable(resources, searchEngine.icon) val searchIcon = BitmapDrawable(resources, searchEngine.icon)
searchIcon.setBounds(0, 0, iconSize, iconSize) searchIcon.setBounds(0, 0, iconSize, iconSize)
@ -244,13 +246,11 @@ class HomeFragment : Fragment(), AccountObserver {
invokePendingDeleteJobs() invokePendingDeleteJobs()
onboarding.finish() onboarding.finish()
val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment(null) val directions = HomeFragmentDirections.actionHomeFragmentToSearchFragment(null)
// Disabled while awaiting a better solution to #3209 val extras =
// val extras = FragmentNavigator.Extras.Builder()
// FragmentNavigator.Extras.Builder() .addSharedElement(toolbar_wrapper, "toolbar_wrapper_transition")
// .addSharedElement(toolbar_wrapper, "toolbar_wrapper_transition") .build()
// .build() nav(R.id.homeFragment, directions, extras)
// nav(R.id.homeFragment, directions, extras)
nav(R.id.homeFragment, directions)
requireComponents.analytics.metrics.track(Event.SearchBarTapped(Event.SearchBarTapped.Source.HOME)) requireComponents.analytics.metrics.track(Event.SearchBarTapped(Event.SearchBarTapped.Source.HOME))
} }
@ -268,8 +268,13 @@ class HomeFragment : Fragment(), AccountObserver {
} }
if (onboarding.userHasBeenOnboarded()) { if (onboarding.userHasBeenOnboarded()) {
val mode = if (newMode == BrowsingModeManager.Mode.Private) Mode.Private else Mode.Normal val mode =
getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.ModeChange(mode)) if (newMode == BrowsingModeManager.Mode.Private) Mode.Private else Mode.Normal
getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.ModeChange(
mode
)
)
} }
browsingModeManager.mode = newMode browsingModeManager.mode = newMode
@ -324,7 +329,11 @@ class HomeFragment : Fragment(), AccountObserver {
onboarding.finish() onboarding.finish()
val mode = currentMode(context!!) val mode = currentMode(context!!)
getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.ModeChange(mode)) getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.ModeChange(
mode
)
)
} }
} }
} }
@ -344,13 +353,14 @@ class HomeFragment : Fragment(), AccountObserver {
val session = sessionManager.findSessionById(action.sessionId) val session = sessionManager.findSessionById(action.sessionId)
sessionManager.select(session!!) sessionManager.select(session!!)
val directions = HomeFragmentDirections.actionHomeFragmentToBrowserFragment(null) val directions = HomeFragmentDirections.actionHomeFragmentToBrowserFragment(null)
// Disabled while awaiting a better solution to #3209 val extras =
// val extras = FragmentNavigator.Extras.Builder()
// FragmentNavigator.Extras.Builder() .addSharedElement(
// .addSharedElement(action.tabView, "$TAB_ITEM_TRANSITION_NAME${action.sessionId}") action.tabView,
// .build() "$TAB_ITEM_TRANSITION_NAME${action.sessionId}"
// nav(R.id.homeFragment, directions, extras) )
nav(R.id.homeFragment, directions) .build()
nav(R.id.homeFragment, directions, extras)
} }
is TabAction.Close -> { is TabAction.Close -> {
if (pendingSessionDeletion?.deletionJob == null) { if (pendingSessionDeletion?.deletionJob == null) {
@ -430,7 +440,8 @@ class HomeFragment : Fragment(), AccountObserver {
private fun createDeleteCollectionPrompt(tabCollection: TabCollection) { private fun createDeleteCollectionPrompt(tabCollection: TabCollection) {
context?.let { context?.let {
AlertDialog.Builder(it).apply { AlertDialog.Builder(it).apply {
val message = context.getString(R.string.tab_collection_dialog_message, tabCollection.title) val message =
context.getString(R.string.tab_collection_dialog_message, tabCollection.title)
setMessage(message) setMessage(message)
setNegativeButton(R.string.tab_collection_dialog_negative) { dialog: DialogInterface, _ -> setNegativeButton(R.string.tab_collection_dialog_negative) { dialog: DialogInterface, _ ->
dialog.cancel() dialog.cancel()
@ -531,7 +542,10 @@ class HomeFragment : Fragment(), AccountObserver {
} }
is CollectionAction.RemoveTab -> { is CollectionAction.RemoveTab -> {
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
requireComponents.core.tabCollectionStorage.removeTabFromCollection(action.collection, action.tab) requireComponents.core.tabCollectionStorage.removeTabFromCollection(
action.collection,
action.tab
)
} }
requireComponents.analytics.metrics.track(Event.CollectionTabRemoved) requireComponents.analytics.metrics.track(Event.CollectionTabRemoved)
} }
@ -594,7 +608,11 @@ class HomeFragment : Fragment(), AccountObserver {
private fun subscribeToTabCollections(): Observer<List<TabCollection>> { private fun subscribeToTabCollections(): Observer<List<TabCollection>> {
return Observer<List<TabCollection>> { return Observer<List<TabCollection>> {
requireComponents.core.tabCollectionStorage.cachedTabCollections = it requireComponents.core.tabCollectionStorage.cachedTabCollections = it
getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.CollectionsChange(it)) getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.CollectionsChange(
it
)
)
}.also { observer -> }.also { observer ->
requireComponents.core.tabCollectionStorage.getCollections().observe(this, observer) requireComponents.core.tabCollectionStorage.getCollections().observe(this, observer)
} }
@ -659,7 +677,8 @@ class HomeFragment : Fragment(), AccountObserver {
private fun getListOfSessions(): List<Session> { private fun getListOfSessions(): List<Session> {
val isPrivate = (activity as HomeActivity).browsingModeManager.isPrivate val isPrivate = (activity as HomeActivity).browsingModeManager.isPrivate
val notPendingDeletion: (Session) -> Boolean = { it.id != pendingSessionDeletion?.sessionId } val notPendingDeletion: (Session) -> Boolean =
{ it.id != pendingSessionDeletion?.sessionId }
return sessionManager.filteredSessions(isPrivate, notPendingDeletion) return sessionManager.filteredSessions(isPrivate, notPendingDeletion)
} }
@ -677,10 +696,12 @@ class HomeFragment : Fragment(), AccountObserver {
} }
viewModel?.tabs = tabs viewModel?.tabs = tabs
val selectedTabs = val selectedTabs =
tabs.find { tab -> tab.sessionId == selectedTabId } ?: if (tabs.size == 1) tabs[0] else null tabs.find { tab -> tab.sessionId == selectedTabId }
?: if (tabs.size == 1) tabs[0] else null
val selectedSet = if (selectedTabs == null) mutableSetOf() else mutableSetOf(selectedTabs) val selectedSet = if (selectedTabs == null) mutableSetOf() else mutableSetOf(selectedTabs)
viewModel?.selectedTabs = selectedSet viewModel?.selectedTabs = selectedSet
viewModel?.tabCollections = requireComponents.core.tabCollectionStorage.cachedTabCollections.reversed() viewModel?.tabCollections =
requireComponents.core.tabCollectionStorage.cachedTabCollections.reversed()
viewModel?.selectedTabCollection = selectedTabCollection viewModel?.selectedTabCollection = selectedTabCollection
viewModel?.saveCollectionStep = viewModel?.saveCollectionStep =
step ?: viewModel?.getStepForTabsAndCollectionSize() ?: SaveCollectionStep.SelectTabs step ?: viewModel?.getStepForTabsAndCollectionSize() ?: SaveCollectionStep.SelectTabs
@ -743,7 +764,10 @@ class HomeFragment : Fragment(), AccountObserver {
override fun onLoggedOut() = emitAccountChanges() override fun onLoggedOut() = emitAccountChanges()
override fun onProfileUpdated(profile: Profile) = emitAccountChanges() override fun onProfileUpdated(profile: Profile) = emitAccountChanges()
private fun scrollAndAnimateCollection(tabsAddedToCollectionSize: Int, changedCollection: TabCollection? = null) { private fun scrollAndAnimateCollection(
tabsAddedToCollectionSize: Int,
changedCollection: TabCollection? = null
) {
if (view != null) { if (view != null) {
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
val recyclerView = sessionControlComponent.view val recyclerView = sessionControlComponent.view
@ -762,10 +786,14 @@ class HomeFragment : Fragment(), AccountObserver {
} }
} }
val lastVisiblePosition = val lastVisiblePosition =
(recyclerView.layoutManager as? LinearLayoutManager)?.findLastCompletelyVisibleItemPosition() ?: 0 (recyclerView.layoutManager as? LinearLayoutManager)?.findLastCompletelyVisibleItemPosition()
?: 0
if (lastVisiblePosition < indexOfCollection) { if (lastVisiblePosition < indexOfCollection) {
val onScrollListener = object : RecyclerView.OnScrollListener() { val onScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { override fun onScrollStateChanged(
recyclerView: RecyclerView,
newState: Int
) {
super.onScrollStateChanged(recyclerView, newState) super.onScrollStateChanged(recyclerView, newState)
if (newState == SCROLL_STATE_IDLE) { if (newState == SCROLL_STATE_IDLE) {
animateCollection(tabsAddedToCollectionSize, indexOfCollection) animateCollection(tabsAddedToCollectionSize, indexOfCollection)
@ -784,8 +812,10 @@ class HomeFragment : Fragment(), AccountObserver {
private fun animateCollection(addedTabsSize: Int, indexOfCollection: Int) { private fun animateCollection(addedTabsSize: Int, indexOfCollection: Int) {
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
val viewHolder = sessionControlComponent.view.findViewHolderForAdapterPosition(indexOfCollection) val viewHolder =
val border = (viewHolder as? CollectionViewHolder)?.view?.findViewById<View>(R.id.selected_border) sessionControlComponent.view.findViewHolderForAdapterPosition(indexOfCollection)
val border =
(viewHolder as? CollectionViewHolder)?.view?.findViewById<View>(R.id.selected_border)
val listener = object : Animator.AnimatorListener { val listener = object : Animator.AnimatorListener {
override fun onAnimationCancel(animation: Animator?) { override fun onAnimationCancel(animation: Animator?) {
border?.visibility = View.GONE border?.visibility = View.GONE
@ -799,7 +829,8 @@ class HomeFragment : Fragment(), AccountObserver {
?.start() ?.start()
} }
} }
border?.animate()?.alpha(1.0F)?.setStartDelay(ANIM_ON_SCREEN_DELAY)?.setDuration(FADE_ANIM_DURATION) border?.animate()?.alpha(1.0F)?.setStartDelay(ANIM_ON_SCREEN_DELAY)
?.setDuration(FADE_ANIM_DURATION)
?.setListener(listener)?.start() ?.setListener(listener)?.start()
}.invokeOnCompletion { }.invokeOnCompletion {
showSavedSnackbar(addedTabsSize) showSavedSnackbar(addedTabsSize)
@ -816,7 +847,8 @@ class HomeFragment : Fragment(), AccountObserver {
} else { } else {
R.string.create_collection_tab_saved R.string.create_collection_tab_saved
} }
FenixSnackbar.make(view, Snackbar.LENGTH_LONG).setText(view.context.getString(stringRes)).show() FenixSnackbar.make(view, Snackbar.LENGTH_LONG)
.setText(view.context.getString(stringRes)).show()
} }
} }
} }
@ -853,7 +885,6 @@ class HomeFragment : Fragment(), AccountObserver {
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
private const val MOTION_LAYOUT_PROGRESS_ROUND_POINT = 0.25f
} }
} }

@ -19,6 +19,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.transition.TransitionInflater
import kotlinx.android.synthetic.main.fragment_search.* import kotlinx.android.synthetic.main.fragment_search.*
import kotlinx.android.synthetic.main.fragment_search.view.* import kotlinx.android.synthetic.main.fragment_search.view.*
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -54,6 +55,12 @@ class SearchFragment : Fragment(), BackHandler {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
postponeEnterTransition()
sharedElementEnterTransition =
TransitionInflater.from(context).inflateTransition(android.R.transition.move)
.setDuration(
SHARED_TRANSITION_MS
)
requireComponents.analytics.metrics.track(Event.InteractWithSearchURLArea) requireComponents.analytics.metrics.track(Event.InteractWithSearchURLArea)
} }
@ -101,6 +108,7 @@ class SearchFragment : Fragment(), BackHandler {
(activity as HomeActivity).browsingModeManager.isPrivate (activity as HomeActivity).browsingModeManager.isPrivate
) )
startPostponedEnterTransition()
return view return view
} }
@ -191,7 +199,8 @@ class SearchFragment : Fragment(), BackHandler {
// The user has the option to go to 'Shortcuts' -> 'Search engine settings' to modify the default search engine. // The user has the option to go to 'Shortcuts' -> 'Search engine settings' to modify the default search engine.
// When returning from that settings screen we need to update it to account for any changes. // When returning from that settings screen we need to update it to account for any changes.
val currentDefaultEngine = requireComponents.search.searchEngineManager.getDefaultSearchEngine(requireContext()) val currentDefaultEngine =
requireComponents.search.searchEngineManager.getDefaultSearchEngine(requireContext())
if (searchStore.state.defaultEngineSource.searchEngine != currentDefaultEngine) { if (searchStore.state.defaultEngineSource.searchEngine != currentDefaultEngine) {
searchStore.dispatch( searchStore.dispatch(
SearchAction.SelectNewDefaultSearchEngine SearchAction.SelectNewDefaultSearchEngine
@ -232,7 +241,8 @@ class SearchFragment : Fragment(), BackHandler {
} }
private fun updateSearchWithLabel(searchState: SearchState) { private fun updateSearchWithLabel(searchState: SearchState) {
searchWithShortcuts.visibility = if (searchState.showShortcutEnginePicker) View.VISIBLE else View.GONE searchWithShortcuts.visibility =
if (searchState.showShortcutEnginePicker) View.VISIBLE else View.GONE
} }
private fun updateSearchShortuctsIcon(searchState: SearchState) { private fun updateSearchShortuctsIcon(searchState: SearchState) {
@ -246,7 +256,11 @@ class SearchFragment : Fragment(), BackHandler {
} }
} }
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
when (requestCode) { when (requestCode) {
REQUEST_CODE_CAMERA_PERMISSIONS -> qrFeature.withFeature { REQUEST_CODE_CAMERA_PERMISSIONS -> qrFeature.withFeature {
it.onPermissionsResult(permissions, grantResults) it.onPermissionsResult(permissions, grantResults)
@ -270,6 +284,7 @@ class SearchFragment : Fragment(), BackHandler {
} }
companion object { companion object {
private const val SHARED_TRANSITION_MS = 200L
private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1 private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1
} }
} }

Loading…
Cancel
Save