diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryController.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryController.kt index ebdcea699..48733b5ca 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryController.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryController.kt @@ -6,25 +6,40 @@ package org.mozilla.fenix.library.history +import android.content.ClipData +import android.content.ClipboardManager +import android.content.res.Resources +import androidx.navigation.NavController +import mozilla.components.concept.engine.prompt.ShareData +import org.mozilla.fenix.R +import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.components.FenixSnackbar + interface HistoryController { - fun handleOpen(item: HistoryItem) + fun handleOpen(item: HistoryItem, mode: BrowsingMode? = null) fun handleSelect(item: HistoryItem) fun handleDeselect(item: HistoryItem) fun handleBackPressed(): Boolean fun handleModeSwitched() fun handleDeleteAll() fun handleDeleteSome(items: Set) + fun handleCopyUrl(item: HistoryItem) + fun handleShare(item: HistoryItem) } class DefaultHistoryController( private val store: HistoryFragmentStore, - private val openToBrowser: (item: HistoryItem) -> Unit, + private val navController: NavController, + private val resources: Resources, + private val snackbar: FenixSnackbar, + private val clipboardManager: ClipboardManager, + private val openToBrowser: (item: HistoryItem, mode: BrowsingMode?) -> Unit, private val displayDeleteAll: () -> Unit, private val invalidateOptionsMenu: () -> Unit, private val deleteHistoryItems: (Set) -> Unit ) : HistoryController { - override fun handleOpen(item: HistoryItem) { - openToBrowser(item) + override fun handleOpen(item: HistoryItem, mode: BrowsingMode?) { + openToBrowser(item, mode) } override fun handleSelect(item: HistoryItem) { @@ -55,4 +70,21 @@ class DefaultHistoryController( override fun handleDeleteSome(items: Set) { deleteHistoryItems.invoke(items) } + + override fun handleCopyUrl(item: HistoryItem) { + val urlClipData = ClipData.newPlainText(item.url, item.url) + clipboardManager.primaryClip = urlClipData + with(snackbar) { + setText(resources.getString(R.string.url_copied)) + show() + } + } + + override fun handleShare(item: HistoryItem) { + navController.navigate( + HistoryFragmentDirections.actionHistoryFragmentToShareFragment( + data = arrayOf(ShareData(url = item.url, title = item.title)) + ) + ) + } } diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt index c22eb0415..d52928fc4 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt @@ -4,6 +4,8 @@ package org.mozilla.fenix.library.history +import android.content.ClipboardManager +import android.content.Context.CLIPBOARD_SERVICE import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater @@ -15,6 +17,7 @@ import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import kotlinx.android.synthetic.main.fragment_history.view.* import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -27,6 +30,7 @@ import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.Components +import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.components.history.createSynchronousPagedHistoryProvider import org.mozilla.fenix.components.metrics.Event @@ -58,6 +62,10 @@ class HistoryFragment : LibraryPageFragment(), UserInteractionHandl } val historyController: HistoryController = DefaultHistoryController( historyStore, + findNavController(), + resources, + FenixSnackbar.make(view, FenixSnackbar.LENGTH_LONG), + activity?.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager, ::openItem, ::displayDeleteAllDialog, ::invalidateOptionsMenu, @@ -183,8 +191,11 @@ class HistoryFragment : LibraryPageFragment(), UserInteractionHandl override fun onBackPressed(): Boolean = historyView.onBackPressed() - private fun openItem(item: HistoryItem) { + private fun openItem(item: HistoryItem, mode: BrowsingMode? = null) { requireComponents.analytics.metrics.track(Event.HistoryItemOpened) + + mode?.let { (activity as HomeActivity).browsingModeManager.mode = it } + (activity as HomeActivity).openToBrowserAndLoad( searchTermOrURL = item.url, newTab = true, diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryInteractor.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryInteractor.kt index ffcf1b6e1..f41fb5562 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryInteractor.kt @@ -4,10 +4,13 @@ package org.mozilla.fenix.library.history +import org.mozilla.fenix.browser.browsingmode.BrowsingMode + /** * Interactor for the history screen * Provides implementations for the HistoryViewInteractor */ +@SuppressWarnings("TooManyFunctions") class HistoryInteractor( private val historyController: HistoryController ) : HistoryViewInteractor { @@ -31,6 +34,22 @@ class HistoryInteractor( historyController.handleModeSwitched() } + override fun onCopyPressed(item: HistoryItem) { + historyController.handleCopyUrl(item) + } + + override fun onSharePressed(item: HistoryItem) { + historyController.handleShare(item) + } + + override fun onOpenInNormalTab(item: HistoryItem) { + historyController.handleOpen(item, BrowsingMode.Normal) + } + + override fun onOpenInPrivateTab(item: HistoryItem) { + historyController.handleOpen(item, BrowsingMode.Private) + } + override fun onDeleteAll() { historyController.handleDeleteAll() } diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryItemMenu.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryItemMenu.kt index aeb0489bb..7e638c786 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryItemMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryItemMenu.kt @@ -16,13 +16,29 @@ class HistoryItemMenu( private val onItemTapped: (Item) -> Unit = {} ) : LibraryItemMenu { sealed class Item { + object Copy : Item() + object Share : Item() + object OpenInNewTab : Item() + object OpenInPrivateTab : Item() object Delete : Item() } override val menuBuilder by lazy { BrowserMenuBuilder(menuItems) } private val menuItems by lazy { - listOf( + listOfNotNull( + SimpleBrowserMenuItem(context.getString(R.string.history_menu_copy_button)) { + onItemTapped.invoke(Item.Copy) + }, + SimpleBrowserMenuItem(context.getString(R.string.history_menu_share_button)) { + onItemTapped.invoke(Item.Share) + }, + SimpleBrowserMenuItem(context.getString(R.string.history_menu_open_in_new_tab_button)) { + onItemTapped.invoke(Item.OpenInNewTab) + }, + SimpleBrowserMenuItem(context.getString(R.string.history_menu_open_in_private_tab_button)) { + onItemTapped.invoke(Item.OpenInPrivateTab) + }, SimpleBrowserMenuItem( context.getString(R.string.history_delete_item), textColorResource = ThemeManager.resolveAttribute(R.attr.destructive, context) diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryView.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryView.kt index 9c3097e49..129546ed1 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryView.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryView.kt @@ -33,6 +33,34 @@ interface HistoryViewInteractor : SelectionInteractor { */ fun onModeSwitched() + /** + * Copies the URL of a history item to the copy-paste buffer. + * + * @param item the history item to copy the URL from + */ + fun onCopyPressed(item: HistoryItem) + + /** + * Opens the share sheet for a history item. + * + * @param item the history item to share + */ + fun onSharePressed(item: HistoryItem) + + /** + * Opens a history item in a new tab. + * + * @param item the history item to open in a new tab + */ + fun onOpenInNormalTab(item: HistoryItem) + + /** + * Opens a history item in a private tab. + * + * @param item the history item to open in a private tab + */ + fun onOpenInPrivateTab(item: HistoryItem) + /** * Called when delete all is tapped */ diff --git a/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt index 526144d1f..7bf7bd2ce 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/viewholders/HistoryListItemViewHolder.kt @@ -11,6 +11,7 @@ import kotlinx.android.synthetic.main.library_site_item.view.* import org.mozilla.fenix.R import org.mozilla.fenix.ext.hideAndDisable import org.mozilla.fenix.ext.showAndEnable +import org.mozilla.fenix.lib.Do import org.mozilla.fenix.library.SelectionHolder import org.mozilla.fenix.library.history.HistoryFragmentState import org.mozilla.fenix.library.history.HistoryInteractor @@ -98,7 +99,12 @@ class HistoryListItemViewHolder( private fun setupMenu() { val historyMenu = HistoryItemMenu(itemView.context) { val item = this.item ?: return@HistoryItemMenu - when (it) { + + Do exhaustive when (it) { + HistoryItemMenu.Item.Copy -> historyInteractor.onCopyPressed(item) + HistoryItemMenu.Item.Share -> historyInteractor.onSharePressed(item) + HistoryItemMenu.Item.OpenInNewTab -> historyInteractor.onOpenInNormalTab(item) + HistoryItemMenu.Item.OpenInPrivateTab -> historyInteractor.onOpenInPrivateTab(item) HistoryItemMenu.Item.Delete -> historyInteractor.onDeleteSome(setOf(item)) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6af5bd3a0..7b1111b18 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -454,6 +454,14 @@ Are you sure you want to clear your history? Clear + + Copy + + Share + + Open in new tab + + Open in private tab Delete