From 8f51a9968a867d535b2566f35cd69ffd7769e049 Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Fri, 29 Apr 2022 21:43:21 -0400 Subject: [PATCH] For #26026 - Refactor the FenixTabCounterMenu creation from HomeFragment to TabCounterBuilder --- .../org/mozilla/fenix/home/HomeFragment.kt | 49 ++-------- .../mozilla/fenix/home/TabCounterBuilder.kt | 81 ++++++++++++++++ .../fenix/home/TabCounterBuilderTest.kt | 96 +++++++++++++++++++ 3 files changed, 183 insertions(+), 43 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/home/TabCounterBuilder.kt create mode 100644 app/src/test/java/org/mozilla/fenix/home/TabCounterBuilderTest.kt 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 2559e4473afa..422fcedde640 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -70,11 +70,9 @@ import mozilla.components.service.glean.private.NoExtras import mozilla.components.support.base.feature.ViewBoundFeatureWrapper import mozilla.components.support.ktx.android.content.res.resolveAttribute import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged -import mozilla.components.ui.tabcounter.TabCounterMenu import org.mozilla.fenix.Config import org.mozilla.fenix.GleanMetrics.Events import org.mozilla.fenix.GleanMetrics.HomeScreen -import org.mozilla.fenix.GleanMetrics.StartOnHome import org.mozilla.fenix.GleanMetrics.Wallpapers import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R @@ -84,7 +82,6 @@ import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.PrivateShortcutCreateManager import org.mozilla.fenix.components.TabCollectionStorage import org.mozilla.fenix.components.appstate.AppAction -import org.mozilla.fenix.components.toolbar.FenixTabCounterMenu import org.mozilla.fenix.components.toolbar.ToolbarPosition import org.mozilla.fenix.databinding.FragmentHomeBinding import org.mozilla.fenix.ext.components @@ -510,7 +507,12 @@ class HomeFragment : Fragment() { hideOnboardingIfNeeded = ::hideOnboardingIfNeeded, ).build() - createTabCounterMenu() + TabCounterBuilder( + context = requireContext(), + browsingModeManager = browsingModeManager, + navController = findNavController(), + tabCounter = binding.tabButton, + ).build() binding.toolbar.compoundDrawablePadding = view.resources.getDimensionPixelSize(R.dimen.search_bar_search_engine_icon_padding) @@ -528,11 +530,6 @@ class HomeFragment : Fragment() { true } - binding.tabButton.setOnClickListener { - StartOnHome.openTabsTray.record(NoExtras()) - openTabsTray() - } - PrivateBrowsingButtonView(binding.privateBrowsingButton, browsingModeManager) { newMode -> sessionControlInteractor.onPrivateModeButtonClicked( newMode, @@ -627,40 +624,6 @@ class HomeFragment : Fragment() { } } - private fun createTabCounterMenu() { - val browsingModeManager = (activity as HomeActivity).browsingModeManager - val mode = browsingModeManager.mode - - val onItemTapped: (TabCounterMenu.Item) -> Unit = { - if (it is TabCounterMenu.Item.NewTab) { - browsingModeManager.mode = BrowsingMode.Normal - } else if (it is TabCounterMenu.Item.NewPrivateTab) { - browsingModeManager.mode = BrowsingMode.Private - } - } - - val tabCounterMenu = FenixTabCounterMenu( - requireContext(), - onItemTapped, - iconColor = if (mode == BrowsingMode.Private) { - ContextCompat.getColor(requireContext(), R.color.fx_mobile_private_text_color_primary) - } else { - null - } - ) - - val inverseBrowsingMode = when (mode) { - BrowsingMode.Normal -> BrowsingMode.Private - BrowsingMode.Private -> BrowsingMode.Normal - } - - tabCounterMenu.updateMenu(showOnly = inverseBrowsingMode) - binding.tabButton.setOnLongClickListener { - tabCounterMenu.menuController.show(anchor = it) - true - } - } - private fun removeAllTabsAndShowSnackbar(sessionCode: String) { if (sessionCode == ALL_PRIVATE_TABS) { requireComponents.useCases.tabsUseCases.removePrivateTabs() diff --git a/app/src/main/java/org/mozilla/fenix/home/TabCounterBuilder.kt b/app/src/main/java/org/mozilla/fenix/home/TabCounterBuilder.kt new file mode 100644 index 000000000000..92bc60063fe8 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/home/TabCounterBuilder.kt @@ -0,0 +1,81 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.home + +import android.content.Context +import androidx.core.content.ContextCompat +import androidx.navigation.NavController +import mozilla.components.ui.tabcounter.TabCounter +import mozilla.components.ui.tabcounter.TabCounterMenu +import mozilla.telemetry.glean.private.NoExtras +import org.mozilla.fenix.GleanMetrics.StartOnHome +import org.mozilla.fenix.R +import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager +import org.mozilla.fenix.components.toolbar.FenixTabCounterMenu +import org.mozilla.fenix.ext.nav + +/** + * Helper class for building the [FenixTabCounterMenu]. + * + * @property context An Android [Context]. + * @property browsingModeManager [BrowsingModeManager] used for fetching the current browsing mode. + * @property navController [NavController] used for navigation. + * @property tabCounter The [TabCounter] that will be setup with event handlers. + */ +class TabCounterBuilder( + private val context: Context, + private val browsingModeManager: BrowsingModeManager, + private val navController: NavController, + private val tabCounter: TabCounter, +) { + + /** + * Builds the [FenixTabCounterMenu]. + */ + fun build() { + val tabCounterMenu = FenixTabCounterMenu( + context = context, + onItemTapped = ::onItemTapped, + iconColor = if (browsingModeManager.mode == BrowsingMode.Private) { + ContextCompat.getColor(context, R.color.fx_mobile_private_text_color_primary) + } else { + null + } + ) + + tabCounterMenu.updateMenu( + showOnly = when (browsingModeManager.mode) { + BrowsingMode.Normal -> BrowsingMode.Private + BrowsingMode.Private -> BrowsingMode.Normal + } + ) + + tabCounter.setOnLongClickListener { + tabCounterMenu.menuController.show(anchor = it) + true + } + + tabCounter.setOnClickListener { + StartOnHome.openTabsTray.record(NoExtras()) + + navController.nav( + R.id.homeFragment, + HomeFragmentDirections.actionGlobalTabsTrayFragment() + ) + } + } + + /** + * Callback invoked when a menu item is tapped on. + */ + internal fun onItemTapped(item: TabCounterMenu.Item) { + if (item is TabCounterMenu.Item.NewTab) { + browsingModeManager.mode = BrowsingMode.Normal + } else if (item is TabCounterMenu.Item.NewPrivateTab) { + browsingModeManager.mode = BrowsingMode.Private + } + } +} diff --git a/app/src/test/java/org/mozilla/fenix/home/TabCounterBuilderTest.kt b/app/src/test/java/org/mozilla/fenix/home/TabCounterBuilderTest.kt new file mode 100644 index 000000000000..31a416631f94 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/home/TabCounterBuilderTest.kt @@ -0,0 +1,96 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.home + +import androidx.navigation.NavController +import io.mockk.mockk +import io.mockk.verify +import mozilla.components.support.test.robolectric.testContext +import mozilla.components.ui.tabcounter.TabCounter +import mozilla.components.ui.tabcounter.TabCounterMenu +import mozilla.telemetry.glean.testing.GleanTestRule +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.GleanMetrics.StartOnHome +import org.mozilla.fenix.R +import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager +import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager +import org.mozilla.fenix.ext.nav +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import org.mozilla.fenix.utils.Settings + +@RunWith(FenixRobolectricTestRunner::class) +class TabCounterBuilderTest { + + @get:Rule + val gleanTestRule = GleanTestRule(testContext) + + private lateinit var navController: NavController + private lateinit var browsingModeManager: BrowsingModeManager + private lateinit var settings: Settings + private lateinit var modeDidChange: (BrowsingMode) -> Unit + private lateinit var tabCounterBuilder: TabCounterBuilder + private lateinit var tabCounter: TabCounter + + @Before + fun setup() { + navController = mockk(relaxed = true) + settings = mockk(relaxed = true) + modeDidChange = mockk(relaxed = true) + + tabCounter = TabCounter(testContext) + + browsingModeManager = DefaultBrowsingModeManager( + _mode = BrowsingMode.Normal, + settings = settings, + modeDidChange = modeDidChange, + ) + + tabCounterBuilder = TabCounterBuilder( + context = testContext, + browsingModeManager = browsingModeManager, + navController = navController, + tabCounter = tabCounter, + ) + } + + @Test + fun `WHEN tab counter is clicked THEN navigate to tabs tray and record metrics`() { + tabCounterBuilder.build() + + assertNull(StartOnHome.openTabsTray.testGetValue()) + + tabCounter.performClick() + + assertNotNull(StartOnHome.openTabsTray.testGetValue()) + + verify { + navController.nav( + R.id.homeFragment, + HomeFragmentDirections.actionGlobalTabsTrayFragment() + ) + } + } + + @Test + fun `WHEN New tab menu item is tapped THEN set browsing mode to normal`() { + tabCounterBuilder.onItemTapped(TabCounterMenu.Item.NewTab) + + assertEquals(BrowsingMode.Normal, browsingModeManager.mode) + } + + @Test + fun `WHEN New private tab menu item is tapped THEN set browsing mode to private`() { + tabCounterBuilder.onItemTapped(TabCounterMenu.Item.NewPrivateTab) + + assertEquals(BrowsingMode.Private, browsingModeManager.mode) + } +}