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.withContext
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.SessionManager
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.allowUndo
import org.mozilla.fenix.whatsnew.WhatsNew
import java.lang.ref.WeakReference
import kotlin.math.abs
import kotlin.math.min
@ -321,20 +322,13 @@ class HomeFragment : Fragment() {
}
}
with(view.menuButton) {
menuBuilder = createHomeMenu(context!!).menuBuilder
createHomeMenu(context!!, WeakReference(view.menuButton))
val primaryTextColor = ContextCompat.getColor(
context,
ThemeManager.resolveAttribute(R.attr.primaryText, context)
)
view.menuButton.setColorFilter(ContextCompat.getColor(
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.resources.getDimensionPixelSize(R.dimen.search_bar_search_engine_icon_padding)
view.toolbar_wrapper.setOnClickListener {
@ -607,8 +601,10 @@ class HomeFragment : Fragment() {
}
@SuppressWarnings("ComplexMethod")
private fun createHomeMenu(context: Context): HomeMenu {
return HomeMenu(context) {
private fun createHomeMenu(context: Context, menuButtonView: WeakReference<MenuButton>) = HomeMenu(
this,
context,
onItemTapped = {
when (it) {
HomeMenu.Item.Settings -> {
invokePendingDeleteJobs()
@ -676,8 +672,10 @@ class HomeFragment : Fragment() {
)
}
}
}
}
},
onHighlightPresent = { menuButtonView.get()?.setHighlight(it) },
onMenuBuilderChanged = { menuButtonView.get()?.menuBuilder = it }
)
private fun subscribeToTabCollections(): Observer<List<TabCollection>> {
return Observer<List<TabCollection>> {

View File

@ -6,12 +6,18 @@ package org.mozilla.fenix.home
import android.content.Context
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.BrowserMenuHighlight
import mozilla.components.browser.menu.ext.getHighlight
import mozilla.components.browser.menu.item.BrowserMenuCategory
import mozilla.components.browser.menu.item.BrowserMenuDivider
import mozilla.components.browser.menu.item.BrowserMenuHighlightableItem
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 org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
@ -20,8 +26,11 @@ import org.mozilla.fenix.utils.Settings
import org.mozilla.fenix.whatsnew.WhatsNew
class HomeMenu(
private val lifecycleOwner: LifecycleOwner,
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 {
object WhatsNew : Item()
@ -34,9 +43,6 @@ class HomeMenu(
object Sync : Item()
}
val menuBuilder by lazy { BrowserMenuBuilder(menuItems) }
private val hasAccountProblem get() = context.components.backgroundServices.accountManager.accountNeedsReauth()
private val primaryTextColor =
ThemeManager.resolveAttribute(R.attr.primaryText, context)
private val syncDisconnectedColor = ThemeManager.resolveAttribute(R.attr.syncDisconnected, context)
@ -45,21 +51,7 @@ class HomeMenu(
private val menuCategoryTextColor =
ThemeManager.resolveAttribute(R.attr.menuCategoryText, context)
private val menuItems 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)
}
private val coreMenuItems by lazy {
val whatsNewItem = BrowserMenuHighlightableItem(
context.getString(R.string.browser_menu_whats_new),
R.drawable.ic_whats_new,
@ -103,16 +95,7 @@ class HomeMenu(
onItemTapped.invoke(Item.Help)
}
val quitItem = BrowserMenuImageText(
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,
listOfNotNull(
whatsNewItem,
BrowserMenuDivider(),
BrowserMenuCategory(
@ -125,8 +108,66 @@ class HomeMenu(
settingsItem,
helpItem,
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)
}
}
}