1
0
Fork 0

Part 5: Refactor HomeMenu<->HomeFragment interaction

This refactor "reverses" relationship between these two classes, allowing
HomeMenu to inform its parent, HomeFragment, of any changes to the menu.

Once that's in place, we start observing account manager changes (once its ready)
for account problems.

This solves two problems:
- initialization of the account manager is no longer necessary to build a home menu
- home menu now starts observing changes to the account manager's state (before it was static)
master
Grisha Kruglov 2020-03-30 09:48:40 -07:00 committed by Grisha Kruglov
parent 029fae4559
commit 057e28d4e4
2 changed files with 87 additions and 48 deletions

View File

@ -64,7 +64,7 @@ import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import mozilla.appservices.places.BookmarkRoot import mozilla.appservices.places.BookmarkRoot
import mozilla.components.browser.menu.ext.getHighlight import mozilla.components.browser.menu.view.MenuButton
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.SessionManager
import mozilla.components.browser.state.store.BrowserStore import mozilla.components.browser.state.store.BrowserStore
@ -107,6 +107,7 @@ import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.FragmentPreDrawManager import org.mozilla.fenix.utils.FragmentPreDrawManager
import org.mozilla.fenix.utils.allowUndo import org.mozilla.fenix.utils.allowUndo
import org.mozilla.fenix.whatsnew.WhatsNew import org.mozilla.fenix.whatsnew.WhatsNew
import java.lang.ref.WeakReference
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.min import kotlin.math.min
@ -321,20 +322,13 @@ class HomeFragment : Fragment() {
} }
} }
with(view.menuButton) { createHomeMenu(context!!, WeakReference(view.menuButton))
menuBuilder = createHomeMenu(context!!).menuBuilder
val primaryTextColor = ContextCompat.getColor( view.menuButton.setColorFilter(ContextCompat.getColor(
context, context!!,
ThemeManager.resolveAttribute(R.attr.primaryText, context) ThemeManager.resolveAttribute(R.attr.primaryText, context!!)
) ))
setColorFilter(primaryTextColor)
// Immediately check for `What's new` highlight. If home items that change over time
// are added, this will need to be called repeatedly.
setHighlight(menuBuilder?.items?.getHighlight())
}
view.toolbar.compoundDrawablePadding = view.toolbar.compoundDrawablePadding =
view.resources.getDimensionPixelSize(R.dimen.search_bar_search_engine_icon_padding) view.resources.getDimensionPixelSize(R.dimen.search_bar_search_engine_icon_padding)
view.toolbar_wrapper.setOnClickListener { view.toolbar_wrapper.setOnClickListener {
@ -607,8 +601,10 @@ class HomeFragment : Fragment() {
} }
@SuppressWarnings("ComplexMethod") @SuppressWarnings("ComplexMethod")
private fun createHomeMenu(context: Context): HomeMenu { private fun createHomeMenu(context: Context, menuButtonView: WeakReference<MenuButton>) = HomeMenu(
return HomeMenu(context) { this,
context,
onItemTapped = {
when (it) { when (it) {
HomeMenu.Item.Settings -> { HomeMenu.Item.Settings -> {
invokePendingDeleteJobs() invokePendingDeleteJobs()
@ -676,8 +672,10 @@ class HomeFragment : Fragment() {
) )
} }
} }
} },
} onHighlightPresent = { menuButtonView.get()?.setHighlight(it) },
onMenuBuilderChanged = { menuButtonView.get()?.menuBuilder = it }
)
private fun subscribeToTabCollections(): Observer<List<TabCollection>> { private fun subscribeToTabCollections(): Observer<List<TabCollection>> {
return Observer<List<TabCollection>> { return Observer<List<TabCollection>> {

View File

@ -6,12 +6,18 @@ package org.mozilla.fenix.home
import android.content.Context import android.content.Context
import androidx.core.content.ContextCompat.getColor import androidx.core.content.ContextCompat.getColor
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import mozilla.components.browser.menu.BrowserMenuBuilder import mozilla.components.browser.menu.BrowserMenuBuilder
import mozilla.components.browser.menu.BrowserMenuHighlight import mozilla.components.browser.menu.BrowserMenuHighlight
import mozilla.components.browser.menu.ext.getHighlight
import mozilla.components.browser.menu.item.BrowserMenuCategory import mozilla.components.browser.menu.item.BrowserMenuCategory
import mozilla.components.browser.menu.item.BrowserMenuDivider import mozilla.components.browser.menu.item.BrowserMenuDivider
import mozilla.components.browser.menu.item.BrowserMenuHighlightableItem import mozilla.components.browser.menu.item.BrowserMenuHighlightableItem
import mozilla.components.browser.menu.item.BrowserMenuImageText import mozilla.components.browser.menu.item.BrowserMenuImageText
import mozilla.components.concept.sync.AccountObserver
import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.android.content.getColorFromAttr
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
@ -20,8 +26,11 @@ import org.mozilla.fenix.utils.Settings
import org.mozilla.fenix.whatsnew.WhatsNew import org.mozilla.fenix.whatsnew.WhatsNew
class HomeMenu( class HomeMenu(
private val lifecycleOwner: LifecycleOwner,
private val context: Context, private val context: Context,
private val onItemTapped: (Item) -> Unit = {} private val onItemTapped: (Item) -> Unit = {},
private val onMenuBuilderChanged: (BrowserMenuBuilder) -> Unit = {},
private val onHighlightPresent: (BrowserMenuHighlight) -> Unit = {}
) { ) {
sealed class Item { sealed class Item {
object WhatsNew : Item() object WhatsNew : Item()
@ -34,9 +43,6 @@ class HomeMenu(
object Sync : Item() object Sync : Item()
} }
val menuBuilder by lazy { BrowserMenuBuilder(menuItems) }
private val hasAccountProblem get() = context.components.backgroundServices.accountManager.accountNeedsReauth()
private val primaryTextColor = private val primaryTextColor =
ThemeManager.resolveAttribute(R.attr.primaryText, context) ThemeManager.resolveAttribute(R.attr.primaryText, context)
private val syncDisconnectedColor = ThemeManager.resolveAttribute(R.attr.syncDisconnected, context) private val syncDisconnectedColor = ThemeManager.resolveAttribute(R.attr.syncDisconnected, context)
@ -45,21 +51,7 @@ class HomeMenu(
private val menuCategoryTextColor = private val menuCategoryTextColor =
ThemeManager.resolveAttribute(R.attr.menuCategoryText, context) ThemeManager.resolveAttribute(R.attr.menuCategoryText, context)
private val menuItems by lazy { private val coreMenuItems by lazy {
val reconnectToSyncItem = BrowserMenuHighlightableItem(
context.getString(R.string.sync_reconnect),
R.drawable.ic_sync_disconnected,
iconTintColorResource = syncDisconnectedColor,
textColorResource = primaryTextColor,
highlight = BrowserMenuHighlight.HighPriority(
backgroundTint = syncDisconnectedBackgroundColor
),
isHighlighted = { true }
) {
onItemTapped.invoke(Item.Sync)
}
val whatsNewItem = BrowserMenuHighlightableItem( val whatsNewItem = BrowserMenuHighlightableItem(
context.getString(R.string.browser_menu_whats_new), context.getString(R.string.browser_menu_whats_new),
R.drawable.ic_whats_new, R.drawable.ic_whats_new,
@ -103,16 +95,7 @@ class HomeMenu(
onItemTapped.invoke(Item.Help) onItemTapped.invoke(Item.Help)
} }
val quitItem = BrowserMenuImageText( listOfNotNull(
context.getString(R.string.delete_browsing_data_on_quit_action),
R.drawable.ic_exit,
primaryTextColor
) {
onItemTapped.invoke(Item.Quit)
}
val items = listOfNotNull(
if (hasAccountProblem) reconnectToSyncItem else null,
whatsNewItem, whatsNewItem,
BrowserMenuDivider(), BrowserMenuDivider(),
BrowserMenuCategory( BrowserMenuCategory(
@ -125,8 +108,66 @@ class HomeMenu(
settingsItem, settingsItem,
helpItem, helpItem,
if (Settings.getInstance(context).shouldDeleteBrowsingDataOnQuit) quitItem else null if (Settings.getInstance(context).shouldDeleteBrowsingDataOnQuit) quitItem else null
) ).also { items ->
items.getHighlight()?.let { onHighlightPresent(it) }
}
}
items init {
// Report initial state.
onMenuBuilderChanged(BrowserMenuBuilder(coreMenuItems))
// Observe account state changes, and update menu item builder with a new set of items.
context.components.backgroundServices.accountManagerAvailableQueue.runIfReadyOrQueue {
// This task isn't relevant if our parent fragment isn't around anymore.
if (lifecycleOwner.lifecycle.currentState == Lifecycle.State.DESTROYED) {
return@runIfReadyOrQueue
}
context.components.backgroundServices.accountManager.register(object : AccountObserver {
override fun onAuthenticationProblems() {
onMenuBuilderChanged(BrowserMenuBuilder(
listOf(reconnectToSyncItem) + coreMenuItems
))
}
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
onMenuBuilderChanged(BrowserMenuBuilder(
coreMenuItems
))
}
override fun onLoggedOut() {
onMenuBuilderChanged(BrowserMenuBuilder(
coreMenuItems
))
}
}, lifecycleOwner)
}
}
// 'Reconnect' and 'Quit' items aren't needed most of the time, so we'll only create the if necessary.
private val reconnectToSyncItem by lazy {
BrowserMenuHighlightableItem(
context.getString(R.string.sync_reconnect),
R.drawable.ic_sync_disconnected,
iconTintColorResource = syncDisconnectedColor,
textColorResource = primaryTextColor,
highlight = BrowserMenuHighlight.HighPriority(
backgroundTint = syncDisconnectedBackgroundColor
),
isHighlighted = { true }
) {
onItemTapped.invoke(Item.Sync)
}
}
private val quitItem by lazy {
BrowserMenuImageText(
context.getString(R.string.delete_browsing_data_on_quit_action),
R.drawable.ic_exit,
primaryTextColor
) {
onItemTapped.invoke(Item.Quit)
}
} }
} }