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
parent
029fae4559
commit
057e28d4e4
|
@ -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>> {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue