diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt
index 91203d4c5f..a6b422fdb4 100644
--- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt
+++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt
@@ -120,6 +120,16 @@ interface SessionControlController {
*/
fun handleSelectTopSite(topSite: TopSite)
+ /**
+ * @see [TopSiteInteractor.onSettingsClicked]
+ */
+ fun handleTopSiteSettingsClicked()
+
+ /**
+ * @see [TopSiteInteractor.onSponsorPrivacyClicked]
+ */
+ fun handleSponsorPrivacyClicked()
+
/**
* @see [OnboardingInteractor.onStartBrowsingClicked]
*/
@@ -414,6 +424,21 @@ class DefaultSessionControlController(
activity.openToBrowser(BrowserDirection.FromHome)
}
+ override fun handleTopSiteSettingsClicked() {
+ navController.nav(
+ R.id.homeFragment,
+ HomeFragmentDirections.actionGlobalHomeSettingsFragment()
+ )
+ }
+
+ override fun handleSponsorPrivacyClicked() {
+ activity.openToBrowserAndLoad(
+ searchTermOrURL = SupportUtils.getGenericSumoURLForTopic(SupportUtils.SumoTopic.SPONSOR_PRIVACY),
+ newTab = true,
+ from = BrowserDirection.FromHome
+ )
+ }
+
@VisibleForTesting
internal fun getAvailableSearchEngines() =
activity.components.core.store.state.search.searchEngines +
diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt
index d9e244e41f..61574ea0fe 100644
--- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt
+++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt
@@ -213,6 +213,18 @@ interface TopSiteInteractor {
*/
fun onSelectTopSite(topSite: TopSite)
+ /**
+ * Navigates to the Homepage Settings. Called when an user clicks on the "Settings" top site
+ * menu item.
+ */
+ fun onSettingsClicked()
+
+ /**
+ * Opens the sponsor privacy support articles. Called when an user clicks on the
+ * "Our sponsors & your privacy" top site menu item.
+ */
+ fun onSponsorPrivacyClicked()
+
/**
* Called when top site menu is opened.
*/
@@ -301,6 +313,14 @@ class SessionControlInteractor(
controller.handleSelectTopSite(topSite)
}
+ override fun onSettingsClicked() {
+ controller.handleTopSiteSettingsClicked()
+ }
+
+ override fun onSponsorPrivacyClicked() {
+ controller.handleSponsorPrivacyClicked()
+ }
+
override fun onStartBrowsingClicked() {
controller.handleStartBrowsingClicked()
}
diff --git a/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemMenu.kt b/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemMenu.kt
index cda98e5124..85305557ca 100644
--- a/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemMenu.kt
+++ b/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemMenu.kt
@@ -7,41 +7,80 @@ package org.mozilla.fenix.home.topsites
import android.content.Context
import mozilla.components.browser.menu.BrowserMenuBuilder
import mozilla.components.browser.menu.item.SimpleBrowserMenuItem
+import mozilla.components.feature.top.sites.TopSite
import org.mozilla.fenix.R
+/**
+ * Helper class for building a context menu for a top site item.
+ *
+ * @property context An Android context.
+ * @property topSite The [TopSite] to show the context menu for.
+ * @property onItemTapped Callback invoked when the user taps on a menu item.
+ */
class TopSiteItemMenu(
private val context: Context,
- private val isPinnedSite: Boolean,
+ private val topSite: TopSite,
private val onItemTapped: (Item) -> Unit = {}
) {
sealed class Item {
object OpenInPrivateTab : Item()
object RenameTopSite : Item()
object RemoveTopSite : Item()
+ object Settings : Item()
+ object SponsorPrivacy : Item()
}
val menuBuilder by lazy { BrowserMenuBuilder(menuItems) }
private val menuItems by lazy {
+ val isPinnedSite = topSite is TopSite.Pinned || topSite is TopSite.Default
+ val isProvidedSite = topSite is TopSite.Provided
+
listOfNotNull(
SimpleBrowserMenuItem(
context.getString(R.string.bookmark_menu_open_in_private_tab_button)
) {
onItemTapped.invoke(Item.OpenInPrivateTab)
},
- if (isPinnedSite) SimpleBrowserMenuItem(
- context.getString(R.string.rename_top_site)
- ) {
- onItemTapped.invoke(Item.RenameTopSite)
- } else null,
- SimpleBrowserMenuItem(
- if (isPinnedSite) {
- context.getString(R.string.remove_top_site)
- } else {
- context.getString(R.string.delete_from_history)
+ if (isPinnedSite) {
+ SimpleBrowserMenuItem(
+ context.getString(R.string.rename_top_site)
+ ) {
+ onItemTapped.invoke(Item.RenameTopSite)
}
- ) {
- onItemTapped.invoke(Item.RemoveTopSite)
+ } else {
+ null
+ },
+ if (!isProvidedSite) {
+ SimpleBrowserMenuItem(
+ if (isPinnedSite) {
+ context.getString(R.string.remove_top_site)
+ } else {
+ context.getString(R.string.delete_from_history)
+ }
+ ) {
+ onItemTapped.invoke(Item.RemoveTopSite)
+ }
+ } else {
+ null
+ },
+ if (isProvidedSite) {
+ SimpleBrowserMenuItem(
+ context.getString(R.string.top_sites_menu_settings)
+ ) {
+ onItemTapped.invoke(Item.Settings)
+ }
+ } else {
+ null
+ },
+ if (isProvidedSite) {
+ SimpleBrowserMenuItem(
+ context.getString(R.string.top_sites_menu_sponsor_privacy)
+ ) {
+ onItemTapped.invoke(Item.SponsorPrivacy)
+ }
+ } else {
+ null
}
)
}
diff --git a/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt
index 915bb3b2f5..19037c2f60 100644
--- a/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt
+++ b/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt
@@ -43,7 +43,7 @@ class TopSiteItemViewHolder(
val topSiteMenu = TopSiteItemMenu(
context = view.context,
- isPinnedSite = topSite is TopSite.Pinned || topSite is TopSite.Default
+ topSite = topSite
) { item ->
when (item) {
is TopSiteItemMenu.Item.OpenInPrivateTab -> interactor.onOpenInPrivateTabClicked(
@@ -55,12 +55,16 @@ class TopSiteItemViewHolder(
is TopSiteItemMenu.Item.RemoveTopSite -> interactor.onRemoveTopSiteClicked(
topSite
)
+ is TopSiteItemMenu.Item.Settings -> interactor.onSettingsClicked()
+ is TopSiteItemMenu.Item.SponsorPrivacy -> interactor.onSponsorPrivacyClicked()
}
}
val menu = topSiteMenu.menuBuilder.build(view.context).show(anchor = it)
+
it.setOnTouchListener @SuppressLint("ClickableViewAccessibility") { v, event ->
onTouchEvent(v, event, menu)
}
+
true
}
}
diff --git a/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt b/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt
index 225cee8148..4100ff8356 100644
--- a/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt
+++ b/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt
@@ -53,7 +53,8 @@ object SupportUtils {
CUSTOM_SEARCH_ENGINES("custom-search-engines"),
SYNC_SETUP("how-set-firefox-sync-firefox-android"),
QR_CAMERA_ACCESS("qr-camera-access"),
- SMARTBLOCK("smartblock-enhanced-tracking-protection")
+ SMARTBLOCK("smartblock-enhanced-tracking-protection"),
+ SPONSOR_PRIVACY("sponsor-privacy")
}
enum class MozillaPage(internal val path: String) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1050e2f132..c57e2d6485 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1901,6 +1901,10 @@
OK
Cancel
+
+ Settings
+
+ Our sponsors & your privacy
diff --git a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt
index 740058f10c..372775b892 100644
--- a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt
+++ b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt
@@ -931,6 +931,33 @@ class DefaultSessionControlControllerTest {
}
}
+ @Test
+ fun `WHEN handleTopSiteSettingsClicked is called THEN navigate to the HomeSettingsFragment`() {
+ createController().handleTopSiteSettingsClicked()
+
+ verify {
+ navController.navigate(
+ match {
+ it.actionId == R.id.action_global_homeSettingsFragment
+ },
+ null
+ )
+ }
+ }
+
+ @Test
+ fun `WHEN handleSponsorPrivacyClicked is called THEN `() {
+ createController().handleSponsorPrivacyClicked()
+
+ verify {
+ activity.openToBrowserAndLoad(
+ searchTermOrURL = SupportUtils.getGenericSumoURLForTopic(SupportUtils.SumoTopic.SPONSOR_PRIVACY),
+ newTab = true,
+ from = BrowserDirection.FromHome
+ )
+ }
+ }
+
private fun createController(
hideOnboarding: () -> Unit = { },
registerCollectionStorageObserver: () -> Unit = { },
diff --git a/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt
index 6dca109f71..3e7c0fd8ba 100644
--- a/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt
+++ b/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt
@@ -205,6 +205,18 @@ class SessionControlInteractorTest {
verify { controller.handlePrivateModeButtonClicked(newMode, hasBeenOnboarded) }
}
+ @Test
+ fun `WHEN onSettingsClicked is called THEN handleTopSiteSettingsClicked is called`() {
+ interactor.onSettingsClicked()
+ verify { controller.handleTopSiteSettingsClicked() }
+ }
+
+ @Test
+ fun `WHEN onSponsorPrivacyClicked is called THEN handleSponsorPrivacyClicked is called`() {
+ interactor.onSponsorPrivacyClicked()
+ verify { controller.handleSponsorPrivacyClicked() }
+ }
+
@Test
fun `GIVEN a PocketStoriesInteractor WHEN stories are shown THEN handle it in a PocketStoriesController`() {
val shownStories: List = mockk()