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 1cec01474..497a187d7 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 @@ -17,13 +17,16 @@ import mozilla.components.feature.media.ext.pauseIfPlaying import mozilla.components.feature.media.ext.playIfPaused import mozilla.components.feature.media.state.MediaStateMachine import mozilla.components.feature.tab.collections.TabCollection +import mozilla.components.feature.top.sites.TopSite import mozilla.components.feature.tab.collections.Tab as ComponentTab import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R +import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager import org.mozilla.fenix.collections.SaveCollectionStep import org.mozilla.fenix.components.TabCollectionStorage +import org.mozilla.fenix.components.TopSiteStorage import org.mozilla.fenix.ext.components import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.MetricController @@ -82,6 +85,11 @@ interface SessionControlController { */ fun handleDeleteCollectionTapped(collection: TabCollection) + /** + * @see [TopSiteInteractor.onOpenInPrivateTabClicked] + */ + fun handleOpenInPrivateTabClicked(topSite: TopSite) + /** * @see [TabSessionInteractor.onPauseMediaClicked] */ @@ -97,6 +105,11 @@ interface SessionControlController { */ fun handlePrivateBrowsingLearnMoreClicked() + /** + * @see [TopSiteInteractor.onRemoveTopSiteClicked] + */ + fun handleRemoveTopSiteClicked(topSite: TopSite) + /** * @see [CollectionInteractor.onRenameCollectionTapped] */ @@ -133,7 +146,7 @@ interface SessionControlController { fun handleToggleCollectionExpanded(collection: TabCollection, expand: Boolean) } -@SuppressWarnings("TooManyFunctions") +@SuppressWarnings("TooManyFunctions", "LargeClass") class DefaultSessionControlController( private val activity: HomeActivity, private val store: HomeFragmentStore, @@ -156,6 +169,8 @@ class DefaultSessionControlController( get() = activity.components.core.sessionManager private val tabCollectionStorage: TabCollectionStorage get() = activity.components.core.tabCollectionStorage + private val topSiteStorage: TopSiteStorage + get() = activity.components.core.topSiteStorage override fun handleCloseTab(sessionId: String) { closeTab.invoke(sessionId) @@ -244,6 +259,17 @@ class DefaultSessionControlController( showDeleteCollectionPrompt(collection) } + override fun handleOpenInPrivateTabClicked(topSite: TopSite) { + with(activity) { + browsingModeManager.mode = BrowsingMode.Private + openToBrowserAndLoad( + searchTermOrURL = topSite.url, + newTab = true, + from = BrowserDirection.FromHome + ) + } + } + override fun handlePauseMediaClicked() { MediaStateMachine.state.pauseIfPlaying() } @@ -261,6 +287,12 @@ class DefaultSessionControlController( ) } + override fun handleRemoveTopSiteClicked(topSite: TopSite) { + lifecycleScope.launch(Dispatchers.IO) { + topSiteStorage.removeTopSite(topSite) + } + } + override fun handleRenameCollectionTapped(collection: TabCollection) { showCollectionCreationFragment( step = SaveCollectionStep.RenameCollection, 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 2fa4bf0d7..0c4581cdd 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 @@ -7,6 +7,7 @@ package org.mozilla.fenix.home.sessioncontrol import android.view.View import mozilla.components.feature.tab.collections.Tab import mozilla.components.feature.tab.collections.TabCollection +import mozilla.components.feature.top.sites.TopSite /** * Interface for collection related actions in the [SessionControlInteractor]. @@ -153,6 +154,21 @@ interface TabSessionInteractor { * Interface for top site related actions in the [SessionControlInteractor]. */ interface TopSiteInteractor { + /** + * Opens the given top site in private mode. Called when an user clicks on the "Open in private + * tab" top site menu item. + * + * @param topSite The top site that will be open in private mode. + */ + fun onOpenInPrivateTabClicked(topSite: TopSite) + + /** + * Removes the given top site. Called when an user clicks on the "Remove" top site menu item. + * + * @param topSite The top site that will be removed. + */ + fun onRemoveTopSiteClicked(topSite: TopSite) + /** * Selects the given top site. Called when a user clicks on a top site. * @@ -202,6 +218,10 @@ class SessionControlInteractor( controller.handleDeleteCollectionTapped(collection) } + override fun onOpenInPrivateTabClicked(topSite: TopSite) { + controller.handleOpenInPrivateTabClicked(topSite) + } + override fun onPauseMediaClicked() { controller.handlePauseMediaClicked() } @@ -214,6 +234,10 @@ class SessionControlInteractor( controller.handlePrivateBrowsingLearnMoreClicked() } + override fun onRemoveTopSiteClicked(topSite: TopSite) { + controller.handleRemoveTopSiteClicked(topSite) + } + override fun onRenameCollectionTapped(collection: TabCollection) { controller.handleRenameCollectionTapped(collection) } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt index a668af173..2d5cefb14 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt @@ -4,10 +4,13 @@ package org.mozilla.fenix.home.sessioncontrol.viewholders.topsites +import android.content.Context import android.view.View import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.top_site_item.view.* import mozilla.components.feature.top.sites.TopSite +import mozilla.components.browser.menu.BrowserMenuBuilder +import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.loadIntoView @@ -18,11 +21,26 @@ class TopSiteItemViewHolder( private val interactor: TopSiteInteractor ) : RecyclerView.ViewHolder(view) { private lateinit var topSite: TopSite + private var topSiteMenu: TopSiteItemMenu init { + topSiteMenu = TopSiteItemMenu(view.context) { + when (it) { + is TopSiteItemMenu.Item.OpenInPrivateTab -> interactor.onOpenInPrivateTabClicked( + topSite + ) + is TopSiteItemMenu.Item.RemoveTopSite -> interactor.onRemoveTopSiteClicked(topSite) + } + } + view.top_site_item.setOnClickListener { interactor.onSelectTopSite(topSite.url) } + + view.top_site_item.setOnLongClickListener() { + topSiteMenu.menuBuilder.build(view.context).show(anchor = it) + return@setOnLongClickListener true + } } fun bind(topSite: TopSite) { @@ -35,3 +53,31 @@ class TopSiteItemViewHolder( const val LAYOUT_ID = R.layout.top_site_item } } + +class TopSiteItemMenu( + private val context: Context, + private val onItemTapped: (Item) -> Unit = {} +) { + sealed class Item { + object OpenInPrivateTab : Item() + object RemoveTopSite : Item() + } + + val menuBuilder by lazy { BrowserMenuBuilder(menuItems) } + + private val menuItems by lazy { + listOf( + SimpleBrowserMenuItem( + context.getString(R.string.bookmark_menu_open_in_private_tab_button) + ) { + onItemTapped.invoke(Item.OpenInPrivateTab) + }, + + SimpleBrowserMenuItem( + context.getString(R.string.remove_top_site) + ) { + onItemTapped.invoke(Item.RemoveTopSite) + } + ) + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b0aa7eb05..aa93f3aed 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -426,6 +426,8 @@ Rename collection Open tabs + + Remove