Skip to content
This repository has been archived by the owner on May 15, 2024. It is now read-only.

Commit

Permalink
[fenix] For mozilla-mobile/fenix#28266 - Merge `BrowserTrayInteractor…
Browse files Browse the repository at this point in the history
…` into `TabsTrayInteractor`
  • Loading branch information
MozillaNoah authored and mergify[bot] committed Jan 24, 2023
1 parent bcf6838 commit f0dd1c6
Show file tree
Hide file tree
Showing 21 changed files with 298 additions and 343 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import kotlinx.coroutines.flow.map
import mozilla.components.lib.state.helpers.AbstractBinding
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
import org.mozilla.fenix.R
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor

/**
* A binding that show a FAB in tab tray used to open a new tab.
Expand All @@ -20,7 +19,7 @@ import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
class FloatingActionButtonBinding(
private val store: TabsTrayStore,
private val actionButton: ExtendedFloatingActionButton,
private val interactor: BrowserTrayInteractor,
private val interactor: TabsTrayInteractor,
) : AbstractBinding<TabsTrayState>(store) {

override suspend fun onState(flow: Flow<TabsTrayState>) {
Expand Down
126 changes: 110 additions & 16 deletions fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,24 @@ import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.browser.storage.sync.Tab
import mozilla.components.concept.base.profiler.Profiler
import mozilla.components.concept.engine.mediasession.MediaSession.PlaybackState
import mozilla.components.feature.downloads.ui.DownloadCancelDialogFragment
import mozilla.components.feature.tabs.TabsUseCases
import mozilla.components.lib.state.DelicateAction
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.TabsTray
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.components.metrics.Event
import org.mozilla.fenix.ext.DEFAULT_ACTIVE_DAYS
import org.mozilla.fenix.home.HomeFragment
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.browser.SelectTabUseCaseWrapper
import org.mozilla.fenix.tabstray.ext.isActiveDownload
import org.mozilla.fenix.tabstray.ext.isSelect
import java.util.concurrent.TimeUnit
import org.mozilla.fenix.GleanMetrics.Tab as GleanTab

Expand Down Expand Up @@ -60,7 +64,6 @@ interface TabsTrayController : SyncedTabsController {
/**
* Deletes the [TabSessionState] with the specified [tabId] or calls [DownloadCancelDialogFragment]
* if user tries to close the last private tab while private downloads are active.
* Tracks [Event.ClosedExistingTab] in case of deletion.
*
* @param tabId The id of the [TabSessionState] to be removed from TabsTray.
* @param source app feature from which the tab with [tabId] was closed.
Expand All @@ -69,7 +72,6 @@ interface TabsTrayController : SyncedTabsController {

/**
* Deletes the [TabSessionState] with the specified [tabId]
* Tracks [Event.ClosedExistingTab] in case of deletion.
*
* @param tabId The id of the [TabSessionState] to be removed from TabsTray.
* @param source app feature from which the tab with [tabId] was closed.
Expand All @@ -86,9 +88,9 @@ interface TabsTrayController : SyncedTabsController {
/**
* Moves [tabId] next to before/after [targetId]
*
* @param tabId The tabs to be moved
* @param targetId The id of the tab that the [tab] will be placed next to
* @param placeAfter Place [tabs] before or after the target
* @param tabId The tab to be moved.
* @param targetId The id of the tab that the moved tab will be placed next to.
* @param placeAfter [Boolean] indicating whether to place the tab before or after the target.
*/
fun handleTabsMove(tabId: String, targetId: String?, placeAfter: Boolean)

Expand All @@ -113,13 +115,62 @@ interface TabsTrayController : SyncedTabsController {
* Handles when a tab item is click either to play/pause.
*/
fun handleMediaClicked(tab: SessionState)

/**
* Handles a user's tab click while in multi select mode.
*
* @param tab [TabSessionState] that was clicked.
* @param holder [SelectionHolder] used to access the current selection of tabs.
* @param source App feature from which the tab was clicked.
*/
fun handleMultiSelectClicked(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
source: String?,
)

/**
* Adds the provided tab to the current selection of tabs.
*
* @param tab [TabSessionState] that was long clicked.
* @param holder [SelectionHolder] used to access the current selection of tabs.
*/
fun handleTabLongClick(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
): Boolean

/**
* Adds the provided tab to the current selection of tabs.
*
* @param tab [TabSessionState] to be selected.
* @param source App feature from which the tab was selected.
*/
fun handleTabSelected(
tab: TabSessionState,
source: String?,
)

/**
* Removes the provided tab from the current selection of tabs.
*
* @param tab [TabSessionState] to be unselected.
*/
fun handleTabUnselected(tab: TabSessionState)

/**
* Exits multi select mode when the back button was pressed.
*
* @return true if the button press was consumed.
*/
fun handleBackPressed(): Boolean
}

/**
* Default implementation of [TabsTrayController].
*
* @property activity [HomeActivity] used to perform top-level app actions.
* @property trayStore [TabsTrayStore] used to read/update the [TabsTrayState].
* @property tabsTrayStore [TabsTrayStore] used to read/update the [TabsTrayState].
* @property browserStore [BrowserStore] used to read/update the current [BrowserState].
* @property browsingModeManager [BrowsingModeManager] used to read/update the current [BrowsingMode].
* @property navController [NavController] used to navigate away from the tabs tray.
Expand All @@ -134,7 +185,7 @@ interface TabsTrayController : SyncedTabsController {
@Suppress("TooManyFunctions", "LongParameterList")
class DefaultTabsTrayController(
private val activity: HomeActivity,
private val trayStore: TabsTrayStore,
private val tabsTrayStore: TabsTrayStore,
private val browserStore: BrowserStore,
private val browsingModeManager: BrowsingModeManager,
private val navController: NavController,
Expand All @@ -148,6 +199,12 @@ class DefaultTabsTrayController(
internal val showCancelledDownloadWarning: (downloadCount: Int, tabId: String?, source: String?) -> Unit,
) : TabsTrayController {

private val selectTabWrapper by lazy {
SelectTabUseCaseWrapper(tabsUseCases.selectTab) {
handleNavigateToBrowser()
}
}

override fun handleOpeningNewTab(isPrivate: Boolean) {
val startTime = profiler?.getProfilerTime()
browsingModeManager.mode = BrowsingMode.fromBoolean(isPrivate)
Expand All @@ -164,7 +221,7 @@ class DefaultTabsTrayController(

override fun handleTrayScrollingToPosition(position: Int, smoothScroll: Boolean) {
selectTabPosition(position, smoothScroll)
trayStore.dispatch(TabsTrayAction.PageSelected(Page.positionToPage(position)))
tabsTrayStore.dispatch(TabsTrayAction.PageSelected(Page.positionToPage(position)))
}

/**
Expand Down Expand Up @@ -242,13 +299,6 @@ class DefaultTabsTrayController(
showUndoSnackbarForTab(isPrivate)
}

/**
* Moves [tabId] next to before/after [targetId]
*
* @param tabId The tabs to be moved
* @param targetId The id of the tab that the [tab] will be placed next to
* @param placeAfter Place [tabs] before or after the target
*/
override fun handleTabsMove(
tabId: String,
targetId: String?,
Expand Down Expand Up @@ -330,4 +380,48 @@ class DefaultTabsTrayController(
from = BrowserDirection.FromTabsTray,
)
}

override fun handleMultiSelectClicked(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
source: String?,
) {
val selected = holder.selectedItems
when {
selected.isEmpty() && tabsTrayStore.state.mode.isSelect().not() -> {
handleTabSelected(tab, source)
}
tab.id in selected.map { it.id } -> handleTabUnselected(tab)
else -> tabsTrayStore.dispatch(TabsTrayAction.AddSelectTab(tab))
}
}

override fun handleTabLongClick(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
): Boolean {
return if (holder.selectedItems.isEmpty()) {
Collections.longPress.record(NoExtras())
tabsTrayStore.dispatch(TabsTrayAction.AddSelectTab(tab))
true
} else {
false
}
}

override fun handleTabSelected(tab: TabSessionState, source: String?) {
selectTabWrapper.invoke(tab.id, source)
}

override fun handleTabUnselected(tab: TabSessionState) {
tabsTrayStore.dispatch(TabsTrayAction.RemoveSelectTab(tab))
}

override fun handleBackPressed(): Boolean {
if (tabsTrayStore.state.mode is TabsTrayState.Mode.Select) {
tabsTrayStore.dispatch(TabsTrayAction.ExitSelectMode)
return true
}
return false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ package org.mozilla.fenix.tabstray

import android.app.Dialog
import android.content.Context
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor

/**
* Default tabs tray dialog implementation for overriding the default on back pressed.
*/
class TabsTrayDialog(
context: Context,
theme: Int,
private val interactor: () -> BrowserTrayInteractor,
private val interactor: () -> TabsTrayInteractor,
) : Dialog(context, theme) {
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
if (interactor.invoke().onBackPressed()) {
if (interactor().onBackPressed()) {
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ import org.mozilla.fenix.ext.runIfFragmentIsAttached
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.home.HomeScreenViewModel
import org.mozilla.fenix.share.ShareFragment
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
import org.mozilla.fenix.tabstray.browser.DefaultBrowserTrayInteractor
import org.mozilla.fenix.tabstray.browser.DefaultInactiveTabsController
import org.mozilla.fenix.tabstray.browser.DefaultInactiveTabsInteractor
import org.mozilla.fenix.tabstray.browser.InactiveTabsInteractor
Expand Down Expand Up @@ -80,7 +78,6 @@ enum class TabsTrayAccessPoint {
class TabsTrayFragment : AppCompatDialogFragment() {

@VisibleForTesting internal lateinit var tabsTrayStore: TabsTrayStore
private lateinit var browserTrayInteractor: BrowserTrayInteractor
private lateinit var tabsTrayInteractor: TabsTrayInteractor
private lateinit var tabsTrayController: DefaultTabsTrayController
private lateinit var inactiveTabsInteractor: DefaultInactiveTabsInteractor
Expand Down Expand Up @@ -120,7 +117,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
}

override fun onCreateDialog(savedInstanceState: Bundle?) =
TabsTrayDialog(requireContext(), theme) { browserTrayInteractor }
TabsTrayDialog(requireContext(), theme) { tabsTrayInteractor }

override fun onCreateView(
inflater: LayoutInflater,
Expand Down Expand Up @@ -213,7 +210,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {

tabsTrayController = DefaultTabsTrayController(
activity = activity,
trayStore = tabsTrayStore,
tabsTrayStore = tabsTrayStore,
browserStore = requireComponents.core.store,
browsingModeManager = activity.browsingModeManager,
navController = findNavController(),
Expand All @@ -227,13 +224,8 @@ class TabsTrayFragment : AppCompatDialogFragment() {
showCancelledDownloadWarning = ::showCancelledDownloadWarning,
)

tabsTrayInteractor = DefaultTabsTrayInteractor(tabsTrayController)

browserTrayInteractor = DefaultBrowserTrayInteractor(
tabsTrayStore,
tabsTrayInteractor,
tabsTrayController,
requireComponents.useCases.tabsUseCases.selectTab,
tabsTrayInteractor = DefaultTabsTrayInteractor(
controller = tabsTrayController,
)

inactiveTabsInteractor = DefaultInactiveTabsInteractor(
Expand All @@ -244,7 +236,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
tabsUseCases = requireComponents.useCases.tabsUseCases,
showUndoSnackbar = ::showUndoSnackbarForTab,
),
browserInteractor = browserTrayInteractor,
tabsTrayInteractor = tabsTrayInteractor,
)

setupMenu(navigationInteractor)
Expand All @@ -253,8 +245,6 @@ class TabsTrayFragment : AppCompatDialogFragment() {
lifecycleOwner = viewLifecycleOwner,
store = tabsTrayStore,
trayInteractor = tabsTrayInteractor,
browserInteractor = browserTrayInteractor,
navigationInteractor = navigationInteractor,
inactiveTabsInteractor = inactiveTabsInteractor,
)

Expand Down Expand Up @@ -332,7 +322,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
feature = FloatingActionButtonBinding(
store = tabsTrayStore,
actionButton = fabButtonBinding.newTabButton,
interactor = browserTrayInteractor,
interactor = tabsTrayInteractor,
),
owner = this,
view = view,
Expand Down Expand Up @@ -495,17 +485,13 @@ class TabsTrayFragment : AppCompatDialogFragment() {
lifecycleOwner: LifecycleOwner,
store: TabsTrayStore,
trayInteractor: TabsTrayInteractor,
browserInteractor: BrowserTrayInteractor,
navigationInteractor: NavigationInteractor,
inactiveTabsInteractor: InactiveTabsInteractor,
) {
tabsTrayBinding.tabsTray.apply {
adapter = TrayPagerAdapter(
context = context,
lifecycleOwner = lifecycleOwner,
tabsTrayStore = store,
browserInteractor = browserInteractor,
navInteractor = navigationInteractor,
tabsTrayInteractor = trayInteractor,
browserStore = requireComponents.core.store,
appStore = requireComponents.appStore,
Expand Down
Loading

0 comments on commit f0dd1c6

Please sign in to comment.