mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-03 23:15:31 +00:00
Bug 1822744 - Part 2: Add ToolbarController for handling home toolbar related functionalities
This commit is contained in:
parent
d99eee09cd
commit
b1ad36df71
@ -119,6 +119,7 @@ import org.mozilla.fenix.home.sessioncontrol.DefaultSessionControlController
|
||||
import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor
|
||||
import org.mozilla.fenix.home.sessioncontrol.SessionControlView
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionHeaderViewHolder
|
||||
import org.mozilla.fenix.home.toolbar.DefaultToolbarController
|
||||
import org.mozilla.fenix.home.topsites.DefaultTopSitesView
|
||||
import org.mozilla.fenix.nimbus.FxNimbus
|
||||
import org.mozilla.fenix.onboarding.FenixOnboarding
|
||||
@ -427,6 +428,11 @@ class HomeFragment : Fragment() {
|
||||
activity = activity,
|
||||
hideOnboarding = ::hideOnboardingAndOpenSearch,
|
||||
),
|
||||
toolbarController = DefaultToolbarController(
|
||||
activity = activity,
|
||||
store = components.core.store,
|
||||
navController = findNavController(),
|
||||
),
|
||||
)
|
||||
|
||||
updateLayout(binding.root)
|
||||
|
@ -27,11 +27,9 @@ import mozilla.components.feature.tab.collections.ext.invoke
|
||||
import mozilla.components.feature.tabs.TabsUseCases
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.support.ktx.android.view.showKeyboard
|
||||
import mozilla.components.support.ktx.kotlin.isUrl
|
||||
import mozilla.telemetry.glean.private.NoExtras
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.GleanMetrics.Collections
|
||||
import org.mozilla.fenix.GleanMetrics.Events
|
||||
import org.mozilla.fenix.GleanMetrics.HomeScreen
|
||||
import org.mozilla.fenix.GleanMetrics.Pings
|
||||
import org.mozilla.fenix.GleanMetrics.Pocket
|
||||
@ -148,21 +146,6 @@ interface SessionControlController {
|
||||
*/
|
||||
fun handleToggleCollectionExpanded(collection: TabCollection, expand: Boolean)
|
||||
|
||||
/**
|
||||
* @see [ToolbarInteractor.onPasteAndGo]
|
||||
*/
|
||||
fun handlePasteAndGo(clipboardText: String)
|
||||
|
||||
/**
|
||||
* @see [ToolbarInteractor.onPaste]
|
||||
*/
|
||||
fun handlePaste(clipboardText: String)
|
||||
|
||||
/**
|
||||
* @see [ToolbarInteractor.onNavigateSearch]
|
||||
*/
|
||||
fun handleNavigateSearch()
|
||||
|
||||
/**
|
||||
* @see [CollectionInteractor.onAddTabsToCollectionTapped]
|
||||
*/
|
||||
@ -559,51 +542,6 @@ class DefaultSessionControlController(
|
||||
navController.nav(R.id.homeFragment, directions)
|
||||
}
|
||||
|
||||
override fun handlePasteAndGo(clipboardText: String) {
|
||||
val searchEngine = store.state.search.selectedOrDefaultSearchEngine
|
||||
|
||||
activity.openToBrowserAndLoad(
|
||||
searchTermOrURL = clipboardText,
|
||||
newTab = true,
|
||||
from = BrowserDirection.FromHome,
|
||||
engine = searchEngine,
|
||||
)
|
||||
|
||||
if (clipboardText.isUrl() || searchEngine == null) {
|
||||
Events.enteredUrl.record(Events.EnteredUrlExtra(autocomplete = false))
|
||||
} else {
|
||||
val searchAccessPoint = MetricsUtils.Source.ACTION
|
||||
MetricsUtils.recordSearchMetrics(
|
||||
searchEngine,
|
||||
searchEngine == store.state.search.selectedOrDefaultSearchEngine,
|
||||
searchAccessPoint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun handlePaste(clipboardText: String) {
|
||||
val directions = HomeFragmentDirections.actionGlobalSearchDialog(
|
||||
sessionId = null,
|
||||
pastedText = clipboardText,
|
||||
)
|
||||
navController.nav(R.id.homeFragment, directions)
|
||||
}
|
||||
|
||||
override fun handleNavigateSearch() {
|
||||
val directions =
|
||||
HomeFragmentDirections.actionGlobalSearchDialog(
|
||||
sessionId = null,
|
||||
)
|
||||
|
||||
navController.nav(
|
||||
R.id.homeFragment,
|
||||
directions,
|
||||
BrowserAnimator.getToolbarNavOptions(activity),
|
||||
)
|
||||
|
||||
Events.searchBarTapped.record(Events.SearchBarTappedExtra("HOME"))
|
||||
}
|
||||
|
||||
override fun handleMessageClicked(message: Message) {
|
||||
messageController.onMessagePressed(message)
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem.RecentHistoryGrou
|
||||
import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem.RecentHistoryHighlight
|
||||
import org.mozilla.fenix.home.recentvisits.controller.RecentVisitsController
|
||||
import org.mozilla.fenix.home.recentvisits.interactor.RecentVisitsInteractor
|
||||
import org.mozilla.fenix.home.toolbar.ToolbarController
|
||||
import org.mozilla.fenix.home.toolbar.ToolbarInteractor
|
||||
import org.mozilla.fenix.onboarding.controller.OnboardingController
|
||||
import org.mozilla.fenix.onboarding.interactor.OnboardingInteractor
|
||||
@ -233,6 +234,7 @@ class SessionControlInteractor(
|
||||
private val recentVisitsController: RecentVisitsController,
|
||||
private val pocketStoriesController: PocketStoriesController,
|
||||
private val onboardingController: OnboardingController,
|
||||
private val toolbarController: ToolbarController,
|
||||
) : CollectionInteractor,
|
||||
OnboardingInteractor,
|
||||
TopSiteInteractor,
|
||||
@ -329,15 +331,15 @@ class SessionControlInteractor(
|
||||
}
|
||||
|
||||
override fun onPasteAndGo(clipboardText: String) {
|
||||
controller.handlePasteAndGo(clipboardText)
|
||||
toolbarController.handlePasteAndGo(clipboardText)
|
||||
}
|
||||
|
||||
override fun onPaste(clipboardText: String) {
|
||||
controller.handlePaste(clipboardText)
|
||||
toolbarController.handlePaste(clipboardText)
|
||||
}
|
||||
|
||||
override fun onNavigateSearch() {
|
||||
controller.handleNavigateSearch()
|
||||
toolbarController.handleNavigateSearch()
|
||||
}
|
||||
|
||||
override fun onRemoveCollectionsPlaceholder() {
|
||||
|
@ -0,0 +1,91 @@
|
||||
/* 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.toolbar
|
||||
|
||||
import androidx.navigation.NavController
|
||||
import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.support.ktx.kotlin.isUrl
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.GleanMetrics.Events
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.browser.BrowserAnimator
|
||||
import org.mozilla.fenix.components.metrics.MetricsUtils
|
||||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.home.HomeFragmentDirections
|
||||
|
||||
/**
|
||||
* An interface that handles the view manipulation of the home screen toolbar.
|
||||
*/
|
||||
interface ToolbarController {
|
||||
/**
|
||||
* @see [ToolbarInteractor.onPasteAndGo]
|
||||
*/
|
||||
fun handlePasteAndGo(clipboardText: String)
|
||||
|
||||
/**
|
||||
* @see [ToolbarInteractor.onPaste]
|
||||
*/
|
||||
fun handlePaste(clipboardText: String)
|
||||
|
||||
/**
|
||||
* @see [ToolbarInteractor.onNavigateSearch]
|
||||
*/
|
||||
fun handleNavigateSearch()
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation of [ToolbarController].
|
||||
*/
|
||||
class DefaultToolbarController(
|
||||
private val activity: HomeActivity,
|
||||
private val store: BrowserStore,
|
||||
private val navController: NavController,
|
||||
) : ToolbarController {
|
||||
override fun handlePasteAndGo(clipboardText: String) {
|
||||
val searchEngine = store.state.search.selectedOrDefaultSearchEngine
|
||||
|
||||
activity.openToBrowserAndLoad(
|
||||
searchTermOrURL = clipboardText,
|
||||
newTab = true,
|
||||
from = BrowserDirection.FromHome,
|
||||
engine = searchEngine,
|
||||
)
|
||||
|
||||
if (clipboardText.isUrl() || searchEngine == null) {
|
||||
Events.enteredUrl.record(Events.EnteredUrlExtra(autocomplete = false))
|
||||
} else {
|
||||
val searchAccessPoint = MetricsUtils.Source.ACTION
|
||||
MetricsUtils.recordSearchMetrics(
|
||||
searchEngine,
|
||||
searchEngine == store.state.search.selectedOrDefaultSearchEngine,
|
||||
searchAccessPoint,
|
||||
)
|
||||
}
|
||||
}
|
||||
override fun handlePaste(clipboardText: String) {
|
||||
val directions = HomeFragmentDirections.actionGlobalSearchDialog(
|
||||
sessionId = null,
|
||||
pastedText = clipboardText,
|
||||
)
|
||||
navController.nav(R.id.homeFragment, directions)
|
||||
}
|
||||
|
||||
override fun handleNavigateSearch() {
|
||||
val directions =
|
||||
HomeFragmentDirections.actionGlobalSearchDialog(
|
||||
sessionId = null,
|
||||
)
|
||||
|
||||
navController.nav(
|
||||
R.id.homeFragment,
|
||||
directions,
|
||||
BrowserAnimator.getToolbarNavOptions(activity),
|
||||
)
|
||||
|
||||
Events.searchBarTapped.record(Events.SearchBarTappedExtra("HOME"))
|
||||
}
|
||||
}
|
@ -973,67 +973,6 @@ class DefaultSessionControlControllerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handlePasteAndGo() {
|
||||
assertNull(Events.enteredUrl.testGetValue())
|
||||
assertNull(Events.performedSearch.testGetValue())
|
||||
|
||||
createController().handlePasteAndGo("text")
|
||||
|
||||
verify {
|
||||
activity.openToBrowserAndLoad(
|
||||
searchTermOrURL = "text",
|
||||
newTab = true,
|
||||
from = BrowserDirection.FromHome,
|
||||
engine = searchEngine,
|
||||
)
|
||||
}
|
||||
|
||||
assertNotNull(Events.performedSearch.testGetValue())
|
||||
|
||||
createController().handlePasteAndGo("https://mozilla.org")
|
||||
verify {
|
||||
activity.openToBrowserAndLoad(
|
||||
searchTermOrURL = "https://mozilla.org",
|
||||
newTab = true,
|
||||
from = BrowserDirection.FromHome,
|
||||
engine = searchEngine,
|
||||
)
|
||||
}
|
||||
assertNotNull(Events.enteredUrl.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handlePaste() {
|
||||
createController().handlePaste("text")
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
match<NavDirections> { it.actionId == R.id.action_global_search_dialog },
|
||||
null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleNavigateSearch() {
|
||||
assertNull(Events.searchBarTapped.testGetValue())
|
||||
|
||||
createController().handleNavigateSearch()
|
||||
|
||||
assertNotNull(Events.searchBarTapped.testGetValue())
|
||||
val recordedEvents = Events.searchBarTapped.testGetValue()!!
|
||||
assertEquals(1, recordedEvents.size)
|
||||
assertEquals("HOME", recordedEvents.single().extra?.getValue("source"))
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
match<NavDirections> { it.actionId == R.id.action_global_search_dialog },
|
||||
any<NavOptions>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleRemoveCollectionsPlaceholder() {
|
||||
createController().handleRemoveCollectionsPlaceholder()
|
||||
|
@ -24,6 +24,7 @@ import org.mozilla.fenix.home.recenttabs.controller.RecentTabController
|
||||
import org.mozilla.fenix.home.recentvisits.controller.RecentVisitsController
|
||||
import org.mozilla.fenix.home.sessioncontrol.DefaultSessionControlController
|
||||
import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor
|
||||
import org.mozilla.fenix.home.toolbar.ToolbarController
|
||||
import org.mozilla.fenix.onboarding.controller.OnboardingController
|
||||
|
||||
class SessionControlInteractorTest {
|
||||
@ -34,6 +35,7 @@ class SessionControlInteractorTest {
|
||||
private val recentBookmarksController: RecentBookmarksController = mockk(relaxed = true)
|
||||
private val pocketStoriesController: PocketStoriesController = mockk(relaxed = true)
|
||||
private val onboardingController: OnboardingController = mockk(relaxed = true)
|
||||
private val toolbarController: ToolbarController = mockk(relaxed = true)
|
||||
|
||||
// Note: the recent visits tests are handled in [RecentVisitsInteractorTest] and [RecentVisitsControllerTest]
|
||||
private val recentVisitsController: RecentVisitsController = mockk(relaxed = true)
|
||||
@ -50,6 +52,7 @@ class SessionControlInteractorTest {
|
||||
recentVisitsController,
|
||||
pocketStoriesController,
|
||||
onboardingController,
|
||||
toolbarController,
|
||||
)
|
||||
}
|
||||
|
||||
@ -137,19 +140,19 @@ class SessionControlInteractorTest {
|
||||
@Test
|
||||
fun onPaste() {
|
||||
interactor.onPaste("text")
|
||||
verify { controller.handlePaste("text") }
|
||||
verify { toolbarController.handlePaste("text") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onPasteAndGo() {
|
||||
interactor.onPasteAndGo("text")
|
||||
verify { controller.handlePasteAndGo("text") }
|
||||
verify { toolbarController.handlePasteAndGo("text") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onNavigateSearch() {
|
||||
interactor.onNavigateSearch()
|
||||
verify { controller.handleNavigateSearch() }
|
||||
verify { toolbarController.handleNavigateSearch() }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -20,6 +20,7 @@ import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem.RecentHistoryHigh
|
||||
import org.mozilla.fenix.home.recentvisits.controller.RecentVisitsController
|
||||
import org.mozilla.fenix.home.sessioncontrol.DefaultSessionControlController
|
||||
import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor
|
||||
import org.mozilla.fenix.home.toolbar.ToolbarController
|
||||
import org.mozilla.fenix.onboarding.controller.OnboardingController
|
||||
|
||||
class RecentVisitsInteractorTest {
|
||||
@ -31,6 +32,7 @@ class RecentVisitsInteractorTest {
|
||||
private val pocketStoriesController: PocketStoriesController = mockk(relaxed = true)
|
||||
private val recentVisitsController: RecentVisitsController = mockk(relaxed = true)
|
||||
private val onboardingController: OnboardingController = mockk(relaxed = true)
|
||||
private val toolbarController: ToolbarController = mockk(relaxed = true)
|
||||
|
||||
private lateinit var interactor: SessionControlInteractor
|
||||
|
||||
@ -44,6 +46,7 @@ class RecentVisitsInteractorTest {
|
||||
recentVisitsController,
|
||||
pocketStoriesController,
|
||||
onboardingController,
|
||||
toolbarController,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,141 @@
|
||||
/* 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.toolbar
|
||||
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDirections
|
||||
import androidx.navigation.NavOptions
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import mozilla.components.browser.state.search.SearchEngine
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.SearchState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.service.glean.testing.GleanTestRule
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
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.BrowserDirection
|
||||
import org.mozilla.fenix.GleanMetrics.Events
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class) // For gleanTestRule
|
||||
class DefaultToolbarControllerTest {
|
||||
|
||||
@get:Rule
|
||||
val gleanTestRule = GleanTestRule(testContext)
|
||||
|
||||
private val activity: HomeActivity = mockk(relaxed = true)
|
||||
private val navController: NavController = mockk(relaxed = true)
|
||||
private val settings: Settings = mockk(relaxed = true)
|
||||
|
||||
private val searchEngine = SearchEngine(
|
||||
id = "test",
|
||||
name = "Test Engine",
|
||||
icon = mockk(relaxed = true),
|
||||
type = SearchEngine.Type.BUNDLED,
|
||||
resultUrls = listOf("https://example.org/?q={searchTerms}"),
|
||||
)
|
||||
|
||||
private lateinit var store: BrowserStore
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
store = BrowserStore(
|
||||
initialState = BrowserState(
|
||||
search = SearchState(
|
||||
regionSearchEngines = listOf(searchEngine),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
every { navController.currentDestination } returns mockk {
|
||||
every { id } returns R.id.homeFragment
|
||||
}
|
||||
every { activity.settings() } returns settings
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN Paste & Go toolbar menu is clicked THEN open the browser with the clipboard text as the search term`() {
|
||||
assertNull(Events.enteredUrl.testGetValue())
|
||||
assertNull(Events.performedSearch.testGetValue())
|
||||
|
||||
var clipboardText = "text"
|
||||
createController().handlePasteAndGo(clipboardText)
|
||||
|
||||
verify {
|
||||
activity.openToBrowserAndLoad(
|
||||
searchTermOrURL = clipboardText,
|
||||
newTab = true,
|
||||
from = BrowserDirection.FromHome,
|
||||
engine = searchEngine,
|
||||
)
|
||||
}
|
||||
|
||||
assertNotNull(Events.performedSearch.testGetValue())
|
||||
|
||||
clipboardText = "https://mozilla.org"
|
||||
createController().handlePasteAndGo(clipboardText)
|
||||
|
||||
verify {
|
||||
activity.openToBrowserAndLoad(
|
||||
searchTermOrURL = clipboardText,
|
||||
newTab = true,
|
||||
from = BrowserDirection.FromHome,
|
||||
engine = searchEngine,
|
||||
)
|
||||
}
|
||||
|
||||
assertNotNull(Events.enteredUrl.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN Paste toolbar menu is clicked THEN navigate to the search dialog`() {
|
||||
createController().handlePaste("text")
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
match<NavDirections> { it.actionId == R.id.action_global_search_dialog },
|
||||
null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN the toolbar is tapped THEN navigate to the search dialog`() {
|
||||
assertNull(Events.searchBarTapped.testGetValue())
|
||||
|
||||
createController().handleNavigateSearch()
|
||||
|
||||
assertNotNull(Events.searchBarTapped.testGetValue())
|
||||
|
||||
val recordedEvents = Events.searchBarTapped.testGetValue()!!
|
||||
assertEquals(1, recordedEvents.size)
|
||||
assertEquals("HOME", recordedEvents.single().extra?.getValue("source"))
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
match<NavDirections> { it.actionId == R.id.action_global_search_dialog },
|
||||
any<NavOptions>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createController() = DefaultToolbarController(
|
||||
activity = activity,
|
||||
store = store,
|
||||
navController = navController,
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user