2020-06-17 05:10:06 +02:00
|
|
|
/* 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.tabtray
|
|
|
|
|
|
|
|
import androidx.annotation.VisibleForTesting
|
|
|
|
import androidx.navigation.NavController
|
2020-07-22 19:57:41 +02:00
|
|
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
2020-06-17 05:10:06 +02:00
|
|
|
import mozilla.components.browser.session.Session
|
|
|
|
import mozilla.components.concept.engine.prompt.ShareData
|
2020-07-24 00:56:45 +02:00
|
|
|
import mozilla.components.concept.tabstray.Tab
|
|
|
|
import mozilla.components.feature.tabs.TabsUseCases
|
2020-06-17 05:10:06 +02:00
|
|
|
import org.mozilla.fenix.HomeActivity
|
|
|
|
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
2020-07-24 00:56:45 +02:00
|
|
|
import org.mozilla.fenix.components.TabCollectionStorage
|
2020-06-17 05:10:06 +02:00
|
|
|
import org.mozilla.fenix.ext.components
|
|
|
|
import org.mozilla.fenix.ext.sessionsOfType
|
2020-07-22 19:57:41 +02:00
|
|
|
import org.mozilla.fenix.home.HomeFragment
|
2020-06-17 05:10:06 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* [TabTrayDialogFragment] controller.
|
|
|
|
*
|
|
|
|
* Delegated by View Interactors, handles container business logic and operates changes on it.
|
|
|
|
*/
|
2020-07-24 00:56:45 +02:00
|
|
|
@Suppress("TooManyFunctions")
|
2020-06-17 05:10:06 +02:00
|
|
|
interface TabTrayController {
|
|
|
|
fun onNewTabTapped(private: Boolean)
|
|
|
|
fun onTabTrayDismissed()
|
|
|
|
fun onShareTabsClicked(private: Boolean)
|
2020-07-24 00:56:45 +02:00
|
|
|
fun onSaveToCollectionClicked(selectedTabs: Set<Tab>)
|
2020-06-17 05:10:06 +02:00
|
|
|
fun onCloseAllTabsClicked(private: Boolean)
|
2020-07-24 00:56:45 +02:00
|
|
|
fun handleBackPressed(): Boolean
|
|
|
|
fun onModeRequested(): TabTrayDialogFragmentState.Mode
|
|
|
|
fun handleAddSelectedTab(tab: Tab)
|
|
|
|
fun handleRemoveSelectedTab(tab: Tab)
|
|
|
|
fun handleOpenTab(tab: Tab)
|
|
|
|
fun handleEnterMultiselect()
|
2020-06-17 05:10:06 +02:00
|
|
|
}
|
|
|
|
|
2020-07-24 00:56:45 +02:00
|
|
|
/**
|
|
|
|
* Default behavior of [TabTrayController]. Other implementations are possible.
|
|
|
|
*
|
|
|
|
* @param activity [HomeActivity] used for context and other Android interactions.
|
|
|
|
* @param navController [NavController] used for navigation.
|
|
|
|
* @param dismissTabTray callback allowing to request this entire Fragment to be dismissed.
|
|
|
|
* @param tabTrayDialogFragmentStore [TabTrayDialogFragmentStore] holding the State for all Views displayed
|
|
|
|
* in this Controller's Fragment.
|
|
|
|
* @param dismissTabTrayAndNavigateHome callback allowing showing an undo snackbar after tab deletion.
|
|
|
|
* @param selectTabUseCase [TabsUseCases.SelectTabUseCase] callback allowing for selecting a tab.
|
|
|
|
* @param registerCollectionStorageObserver callback allowing for registering the [TabCollectionStorage.Observer]
|
|
|
|
* when needed.
|
|
|
|
* @param showChooseCollectionDialog callback allowing saving a list of sessions to an existing collection.
|
|
|
|
* @param showAddNewCollectionDialog callback allowing for saving a list of sessions to a new collection.
|
|
|
|
*/
|
2020-07-27 18:48:41 +02:00
|
|
|
@Suppress("TooManyFunctions")
|
2020-06-17 05:10:06 +02:00
|
|
|
class DefaultTabTrayController(
|
|
|
|
private val activity: HomeActivity,
|
|
|
|
private val navController: NavController,
|
|
|
|
private val dismissTabTray: () -> Unit,
|
2020-07-22 19:57:41 +02:00
|
|
|
private val dismissTabTrayAndNavigateHome: (String) -> Unit,
|
2020-07-24 00:56:45 +02:00
|
|
|
private val registerCollectionStorageObserver: () -> Unit,
|
|
|
|
private val tabTrayDialogFragmentStore: TabTrayDialogFragmentStore,
|
|
|
|
private val selectTabUseCase: TabsUseCases.SelectTabUseCase,
|
|
|
|
private val showChooseCollectionDialog: (List<Session>) -> Unit,
|
|
|
|
private val showAddNewCollectionDialog: (List<Session>) -> Unit
|
2020-06-17 05:10:06 +02:00
|
|
|
) : TabTrayController {
|
2020-07-24 00:56:45 +02:00
|
|
|
private val tabCollectionStorage = activity.components.core.tabCollectionStorage
|
|
|
|
|
2020-06-17 05:10:06 +02:00
|
|
|
override fun onNewTabTapped(private: Boolean) {
|
2020-07-03 16:47:18 +02:00
|
|
|
val startTime = activity.components.core.engine.profiler?.getProfilerTime()
|
2020-06-17 05:10:06 +02:00
|
|
|
activity.browsingModeManager.mode = BrowsingMode.fromBoolean(private)
|
|
|
|
navController.navigate(TabTrayDialogFragmentDirections.actionGlobalHome(focusOnAddressBar = true))
|
|
|
|
dismissTabTray()
|
2020-07-24 00:56:45 +02:00
|
|
|
activity.components.core.engine.profiler?.addMarker(
|
|
|
|
"DefaultTabTrayController.onNewTabTapped",
|
|
|
|
startTime
|
|
|
|
)
|
2020-06-17 05:10:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onTabTrayDismissed() {
|
|
|
|
dismissTabTray()
|
|
|
|
}
|
|
|
|
|
2020-07-24 00:56:45 +02:00
|
|
|
override fun onSaveToCollectionClicked(selectedTabs: Set<Tab>) {
|
|
|
|
val sessionList = selectedTabs.map {
|
|
|
|
activity.components.core.sessionManager.findSessionById(it.id) ?: return
|
2020-06-17 05:10:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Only register the observer right before moving to collection creation
|
|
|
|
registerCollectionStorageObserver()
|
|
|
|
|
2020-07-24 00:56:45 +02:00
|
|
|
when {
|
|
|
|
tabCollectionStorage.cachedTabCollections.isNotEmpty() -> {
|
|
|
|
showChooseCollectionDialog(sessionList)
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
showAddNewCollectionDialog(sessionList)
|
|
|
|
}
|
|
|
|
}
|
2020-06-17 05:10:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onShareTabsClicked(private: Boolean) {
|
|
|
|
val tabs = getListOfSessions(private)
|
|
|
|
val data = tabs.map {
|
|
|
|
ShareData(url = it.url, title = it.title)
|
|
|
|
}
|
|
|
|
val directions = TabTrayDialogFragmentDirections.actionGlobalShareFragment(
|
|
|
|
data = data.toTypedArray()
|
|
|
|
)
|
|
|
|
navController.navigate(directions)
|
|
|
|
}
|
|
|
|
|
2020-07-22 19:57:41 +02:00
|
|
|
@OptIn(ExperimentalCoroutinesApi::class)
|
2020-06-17 05:10:06 +02:00
|
|
|
override fun onCloseAllTabsClicked(private: Boolean) {
|
2020-07-22 19:57:41 +02:00
|
|
|
val sessionsToClose = if (private) {
|
|
|
|
HomeFragment.ALL_PRIVATE_TABS
|
2020-06-17 05:10:06 +02:00
|
|
|
} else {
|
2020-07-22 19:57:41 +02:00
|
|
|
HomeFragment.ALL_NORMAL_TABS
|
2020-06-17 05:10:06 +02:00
|
|
|
}
|
|
|
|
|
2020-07-22 19:57:41 +02:00
|
|
|
dismissTabTrayAndNavigateHome(sessionsToClose)
|
2020-06-17 05:10:06 +02:00
|
|
|
}
|
|
|
|
|
2020-07-24 00:56:45 +02:00
|
|
|
override fun handleAddSelectedTab(tab: Tab) {
|
|
|
|
tabTrayDialogFragmentStore.dispatch(TabTrayDialogFragmentAction.AddItemForCollection(tab))
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleRemoveSelectedTab(tab: Tab) {
|
|
|
|
tabTrayDialogFragmentStore.dispatch(TabTrayDialogFragmentAction.RemoveItemForCollection(tab))
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleBackPressed(): Boolean {
|
|
|
|
return if (tabTrayDialogFragmentStore.state.mode is TabTrayDialogFragmentState.Mode.MultiSelect) {
|
|
|
|
tabTrayDialogFragmentStore.dispatch(TabTrayDialogFragmentAction.ExitMultiSelectMode)
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-17 05:10:06 +02:00
|
|
|
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
|
|
|
private fun getListOfSessions(private: Boolean): List<Session> {
|
|
|
|
return activity.components.core.sessionManager.sessionsOfType(private = private).toList()
|
|
|
|
}
|
2020-07-24 00:56:45 +02:00
|
|
|
|
|
|
|
override fun onModeRequested(): TabTrayDialogFragmentState.Mode {
|
|
|
|
return tabTrayDialogFragmentStore.state.mode
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleOpenTab(tab: Tab) {
|
|
|
|
selectTabUseCase.invoke(tab.id)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleEnterMultiselect() {
|
|
|
|
tabTrayDialogFragmentStore.dispatch(TabTrayDialogFragmentAction.EnterMultiSelectMode)
|
|
|
|
}
|
2020-06-17 05:10:06 +02:00
|
|
|
}
|