From 8bed44819da614224095e5b22d9cd03304c49282 Mon Sep 17 00:00:00 2001 From: Denys M Date: Sat, 25 May 2019 02:12:50 +0300 Subject: [PATCH] Fixes #2254/#2709. Observe browser sessions changes on `HomeFragment`. --- .../org/mozilla/fenix/home/HomeFragment.kt | 141 ++++++++++++------ 1 file changed, 94 insertions(+), 47 deletions(-) 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 e72f4c616..80739a014 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -82,7 +82,6 @@ import kotlin.math.roundToInt @SuppressWarnings("TooManyFunctions", "LargeClass") class HomeFragment : Fragment(), CoroutineScope, AccountObserver { private val bus = ActionBusFactory.get(this) - private var sessionObserver: SessionManager.Observer? = null private var tabCollectionObserver: Observer>? = null private val singleSessionObserver = object : Session.Observer { @@ -91,6 +90,7 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { emitSessionChanges() } } + private lateinit var sessionObserver: BrowserSessionsObserver private var homeMenu: HomeMenu? = null @@ -108,6 +108,10 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { super.onCreate(savedInstanceState) postponeEnterTransition() sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move) + + sessionObserver = BrowserSessionsObserver(requireComponents.core.sessionManager, singleSessionObserver) { + emitSessionChanges() + } } override fun onCreateView( @@ -298,14 +302,12 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { getManagedEmitter().onNext(SessionControlChange.ModeChange(mode)) emitSessionChanges() - sessionObserver = subscribeToSessions() + sessionObserver.onStart() tabCollectionObserver = subscribeToTabCollections() } override fun onStop() { - sessionObserver?.let { - requireComponents.core.sessionManager.unregister(it) - } + sessionObserver.onStop() tabCollectionObserver?.let { requireComponents.core.tabCollectionStorage.getCollections().removeObserver(it) } @@ -491,9 +493,6 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { homeViewModel?.layoutManagerState = sessionControlComponent.view.layoutManager?.onSaveInstanceState() homeViewModel?.motionLayoutProgress = homeLayout?.progress ?: 0F - sessionObserver?.let { - requireComponents.core.sessionManager.unregister(it) - } } private fun setupHomeMenu() { @@ -545,45 +544,6 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { return observer } - private fun subscribeToSessions(): SessionManager.Observer { - val observer = object : SessionManager.Observer { - override fun onSessionAdded(session: Session) { - super.onSessionAdded(session) - session.register(singleSessionObserver, this@HomeFragment) - emitSessionChanges() - } - - override fun onSessionRemoved(session: Session) { - super.onSessionRemoved(session) - session.unregister(singleSessionObserver) - emitSessionChanges() - } - - override fun onSessionSelected(session: Session) { - super.onSessionSelected(session) - emitSessionChanges() - } - - override fun onSessionsRestored() { - super.onSessionsRestored() - requireComponents.core.sessionManager.sessions.forEach { - it.register(singleSessionObserver, this@HomeFragment) - } - emitSessionChanges() - } - - override fun onAllSessionsRemoved() { - super.onAllSessionsRemoved() - requireComponents.core.sessionManager.sessions.forEach { - it.unregister(singleSessionObserver) - } - emitSessionChanges() - } - } - requireComponents.core.sessionManager.register(observer, this) - return observer - } - private fun removeAllTabsWithUndo(isPrivate: Boolean) { val useCases = requireComponents.useCases.tabsUseCases @@ -731,3 +691,90 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver { private const val MOTION_LAYOUT_PROGRESS_ROUND_POINT = 0.25f } } + +/** + * Wrapper around sessions manager to obvserve changes in sessions. + * Similar to [mozilla.components.browser.session.utils.AllSessionsObserver] but ignores CustomTab sessions. + * + * Call [onStart] to start receiving updates into [onChanged] callback. + * Call [onStop] to stop receiving updates. + * + * @param manager [SessionManager] instance to subscribe to. + * @param observer [Session.Observer] instance that will recieve updates. + * @param onChanged callback that will be called when any of [SessionManager.Observer]'s events are fired. + */ +private class BrowserSessionsObserver( + private val manager: SessionManager, + private val observer: Session.Observer, + private val onChanged: () -> Unit +) { + + // TODO This is workaround. Should be removed when [mozilla.components.support.base.observer.ObserverRegistry] + // will not allow to subscribe to single session more than once. + private val observedSessions = mutableSetOf() + + /** + * Start observing + */ + fun onStart() { + manager.register(managerObserver) + subscribeToAll() + } + + /** + * Stop observing (will not receive updates till next [onStop] call) + */ + fun onStop() { + manager.unregister(managerObserver) + unsubscribeFromAll() + } + + private fun subscribeToAll() { + manager.sessions.forEach(::subscribeTo) + } + + private fun unsubscribeFromAll() { + manager.sessions.forEach(::unsubscribeFrom) + } + + private fun subscribeTo(session: Session) { + if (!observedSessions.contains(session)) { + session.register(observer) + observedSessions += session + } + } + + private fun unsubscribeFrom(session: Session) { + if (observedSessions.contains(session)) { + session.unregister(observer) + observedSessions -= session + } + } + + private val managerObserver = object : SessionManager.Observer { + + override fun onSessionAdded(session: Session) { + subscribeTo(session) + onChanged() + } + + override fun onSessionsRestored() { + subscribeToAll() + onChanged() + } + + override fun onAllSessionsRemoved() { + unsubscribeFromAll() + onChanged() + } + + override fun onSessionRemoved(session: Session) { + unsubscribeFrom(session) + onChanged() + } + + override fun onSessionSelected(session: Session) { + onChanged() + } + } +}