Skip to content
This repository has been archived by the owner on Feb 20, 2023. It is now read-only.

Commit

Permalink
For #25491 - Refactor InactiveTabs interactors and controllers
Browse files Browse the repository at this point in the history
  • Loading branch information
MozillaNoah authored and mergify[bot] committed Jun 22, 2022
1 parent 717e95a commit 5f7fd53
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 192 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ 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.home.HomeFragment
import org.mozilla.fenix.ext.DEFAULT_ACTIVE_DAYS
import org.mozilla.fenix.ext.potentialInactiveTabs
import org.mozilla.fenix.home.HomeFragment
import org.mozilla.fenix.tabstray.ext.isActiveDownload
import java.util.concurrent.TimeUnit

Expand Down Expand Up @@ -98,11 +97,6 @@ interface TabsTrayController {
tabs: Collection<TabSessionState>,
numOfDays: Long = DEFAULT_ACTIVE_DAYS + 1
)

/**
* Deletes all inactive tabs.
*/
fun handleDeleteAllInactiveTabs()
}

@Suppress("TooManyFunctions")
Expand Down Expand Up @@ -274,12 +268,4 @@ class DefaultTabsTrayController(
dismissTray()
navigateToHomeAndDeleteSession(sessionId)
}

override fun handleDeleteAllInactiveTabs() {
TabsTray.closeAllInactiveTabs.record(NoExtras())
browserStore.state.potentialInactiveTabs.map { it.id }.let {
tabsUseCases.removeTabs(it)
}
showUndoSnackbarForTab(false)
}
}
20 changes: 19 additions & 1 deletion app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ 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
import org.mozilla.fenix.tabstray.browser.SelectionBannerBinding
import org.mozilla.fenix.tabstray.browser.SelectionBannerBinding.VisibilityModifier
import org.mozilla.fenix.tabstray.browser.SelectionHandleBinding
Expand Down Expand Up @@ -80,6 +83,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
private lateinit var browserTrayInteractor: BrowserTrayInteractor
private lateinit var tabsTrayInteractor: TabsTrayInteractor
private lateinit var tabsTrayController: DefaultTabsTrayController
private lateinit var inactiveTabsInteractor: DefaultInactiveTabsInteractor
private lateinit var navigationInteractor: DefaultNavigationInteractor
@VisibleForTesting internal lateinit var trayBehaviorManager: TabSheetBehaviorManager

Expand Down Expand Up @@ -227,6 +231,17 @@ class TabsTrayFragment : AppCompatDialogFragment() {
requireComponents.useCases.tabsUseCases.selectTab,
)

inactiveTabsInteractor = DefaultInactiveTabsInteractor(
controller = DefaultInactiveTabsController(
appStore = requireComponents.appStore,
settings = requireContext().settings(),
browserStore = requireComponents.core.store,
tabsUseCases = requireComponents.useCases.tabsUseCases,
showUndoSnackbar = ::showUndoSnackbarForTab,
),
browserInteractor = browserTrayInteractor,
)

setupMenu(navigationInteractor)
setupPager(
context = view.context,
Expand All @@ -235,6 +250,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
trayInteractor = tabsTrayInteractor,
browserInteractor = browserTrayInteractor,
navigationInteractor = navigationInteractor,
inactiveTabsInteractor = inactiveTabsInteractor,
)

setupBackgroundDismissalListener {
Expand Down Expand Up @@ -476,7 +492,8 @@ class TabsTrayFragment : AppCompatDialogFragment() {
store: TabsTrayStore,
trayInteractor: TabsTrayInteractor,
browserInteractor: BrowserTrayInteractor,
navigationInteractor: NavigationInteractor
navigationInteractor: NavigationInteractor,
inactiveTabsInteractor: InactiveTabsInteractor
) {
tabsTrayBinding.tabsTray.apply {
adapter = TrayPagerAdapter(
Expand All @@ -488,6 +505,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
tabsTrayInteractor = trayInteractor,
browserStore = requireComponents.core.store,
appStore = requireComponents.appStore,
inactiveTabsInteractor = inactiveTabsInteractor,
)
isUserInputEnabled = false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ interface TabsTrayInteractor {
targetId: String?,
placeAfter: Boolean
)

/**
* Deletes all inactive tabs.
*/
fun onDeleteInactiveTabs()
}

/**
Expand Down Expand Up @@ -96,8 +91,4 @@ class DefaultTabsTrayInteractor(
override fun onInactiveDebugClicked(tabs: Collection<TabSessionState>) {
controller.forceTabsAsInactive(tabs)
}

override fun onDeleteInactiveTabs() {
controller.handleDeleteAllInactiveTabs()
}
}
19 changes: 3 additions & 16 deletions app/src/main/java/org/mozilla/fenix/tabstray/TrayPagerAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@ import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.RecyclerView
import mozilla.components.browser.state.store.BrowserStore
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.tabstray.browser.BrowserTabsAdapter
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
import org.mozilla.fenix.tabstray.browser.DefaultInactiveTabsInteractor
import org.mozilla.fenix.tabstray.browser.InactiveTabsAdapter
import org.mozilla.fenix.tabstray.browser.InactiveTabsController
import org.mozilla.fenix.tabstray.browser.InactiveTabsInteractor
import org.mozilla.fenix.tabstray.browser.TabGroupAdapter
import org.mozilla.fenix.tabstray.browser.TitleHeaderAdapter
import org.mozilla.fenix.tabstray.viewholders.AbstractPageViewHolder
Expand All @@ -37,7 +34,8 @@ class TrayPagerAdapter(
@VisibleForTesting internal val navInteractor: NavigationInteractor,
@VisibleForTesting internal val tabsTrayInteractor: TabsTrayInteractor,
@VisibleForTesting internal val browserStore: BrowserStore,
@VisibleForTesting internal val appStore: AppStore
@VisibleForTesting internal val appStore: AppStore,
@VisibleForTesting internal val inactiveTabsInteractor: InactiveTabsInteractor,
) : RecyclerView.Adapter<AbstractPageViewHolder>() {

/**
Expand All @@ -50,7 +48,6 @@ class TrayPagerAdapter(
InactiveTabsAdapter(
lifecycleOwner = lifecycleOwner,
tabsTrayStore = tabsTrayStore,
tabsTrayInteractor = tabsTrayInteractor,
inactiveTabsInteractor = inactiveTabsInteractor,
featureName = INACTIVE_TABS_FEATURE_NAME,
),
Expand All @@ -60,16 +57,6 @@ class TrayPagerAdapter(
)
}

private val inactiveTabsInteractor by lazy {
DefaultInactiveTabsInteractor(
InactiveTabsController(
appStore = context.components.appStore,
settings = context.settings(),
browserInteractor = browserInteractor,
)
)
}

private val privateAdapter by lazy {
BrowserTabsAdapter(
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class InactiveTabViewHolder(
composeView: ComposeView,
lifecycleOwner: LifecycleOwner,
private val tabsTrayStore: TabsTrayStore,
private val tabsTrayInteractor: TabsTrayInteractor,
private val inactiveTabsInteractor: InactiveTabsInteractor,
) : ComposeViewHolder(composeView, lifecycleOwner) {

Expand All @@ -65,7 +64,7 @@ class InactiveTabViewHolder(
expanded = expanded,
showAutoCloseDialog = showAutoClosePrompt,
onHeaderClick = { inactiveTabsInteractor.onHeaderClicked(!expanded) },
onDeleteAllButtonClick = tabsTrayInteractor::onDeleteInactiveTabs,
onDeleteAllButtonClick = inactiveTabsInteractor::onDeleteAllInactiveTabsClicked,
onAutoCloseDismissClick = {
inactiveTabsInteractor.onCloseClicked()
showAutoClosePrompt = !showAutoClosePrompt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.RecyclerView
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayState
import org.mozilla.fenix.tabstray.TabsTrayStore

Expand All @@ -17,7 +16,6 @@ import org.mozilla.fenix.tabstray.TabsTrayStore
*
* @param lifecycleOwner [LifecycleOwner] to which the Composable will be tied to.
* @param tabsTrayStore [TabsTrayStore] used to listen for changes to [TabsTrayState.inactiveTabs].
* @param tabsTrayInteractor [TabsTrayInteractor] used to handle deleting all inactive tabs.
* @param inactiveTabsInteractor [InactiveTabsInteractor] used to respond to interactions with the inactive tabs header
* and the auto close dialog.
* @param featureName [String] representing the name of the inactive tabs feature for telemetry reporting.
Expand All @@ -26,7 +24,6 @@ import org.mozilla.fenix.tabstray.TabsTrayStore
class InactiveTabsAdapter(
private val lifecycleOwner: LifecycleOwner,
private val tabsTrayStore: TabsTrayStore,
private val tabsTrayInteractor: TabsTrayInteractor,
private val inactiveTabsInteractor: InactiveTabsInteractor,
override val featureName: String,
) : RecyclerView.Adapter<InactiveTabViewHolder>(), FeatureNameHolder {
Expand All @@ -39,7 +36,6 @@ class InactiveTabsAdapter(
lifecycleOwner = lifecycleOwner,
tabsTrayStore = tabsTrayStore,
inactiveTabsInteractor = inactiveTabsInteractor,
tabsTrayInteractor = tabsTrayInteractor,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,79 @@
package org.mozilla.fenix.tabstray.browser

import mozilla.components.browser.state.state.TabSessionState
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.feature.tabs.TabsUseCases
import mozilla.telemetry.glean.private.NoExtras
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.appstate.AppAction.UpdateInactiveExpanded
import org.mozilla.fenix.tabstray.TrayPagerAdapter.Companion.INACTIVE_TABS_FEATURE_NAME
import org.mozilla.fenix.ext.potentialInactiveTabs
import org.mozilla.fenix.utils.Settings
import org.mozilla.fenix.GleanMetrics.TabsTray as TabsTrayMetrics

/**
* Default behavior for handling all user interactions with the Inactive Tabs feature.
*
* @param appStore [AppStore] used to dispatch any [AppAction].
* @param settings [Settings] used to update any user preferences.
* @param browserInteractor [BrowserTrayInteractor] used to respond to interactions with specific inactive tabs.
* Contract for how all user interactions with the Inactive Tabs feature are to be handled.
*/
class InactiveTabsController(
private val appStore: AppStore,
private val settings: Settings,
private val browserInteractor: BrowserTrayInteractor,
) {
interface InactiveTabsController {

/**
* Opens the given inactive tab.
*/
fun openInactiveTab(tab: TabSessionState) {
TabsTrayMetrics.openInactiveTab.add()
browserInteractor.onTabSelected(tab, INACTIVE_TABS_FEATURE_NAME)
}
fun openInactiveTab(tab: TabSessionState)

/**
* Closes the given inactive tab.
*/
fun closeInactiveTab(tab: TabSessionState) {
TabsTrayMetrics.closeInactiveTab.add()
browserInteractor.onTabClosed(tab, INACTIVE_TABS_FEATURE_NAME)
}
fun closeInactiveTab(tab: TabSessionState)

/**
* Updates the inactive card to be expanded to display all the tabs, or collapsed with only
* the title showing.
*/
fun updateCardExpansion(isExpanded: Boolean) {
fun updateCardExpansion(isExpanded: Boolean)

/**
* Dismiss the auto-close dialog.
*/
fun dismissAutoCloseDialog()

/**
* Enable the auto-close feature with the "after a month" setting.
*/
fun enableInactiveTabsAutoClose()

/**
* Delete all inactive tabs.
*/
fun deleteAllInactiveTabs()
}

/**
* Default behavior for handling all user interactions with the Inactive Tabs feature.
*
* @param appStore [AppStore] used to dispatch any [AppAction].
* @param settings [Settings] used to update any user preferences.
* @param browserStore [BrowserStore] used to obtain all inactive tabs.
* @param tabsUseCases [TabsUseCases] used to perform the deletion of all inactive tabs.
* @param showUndoSnackbar Invoked when deleting all inactive tabs.
*/
class DefaultInactiveTabsController(
private val appStore: AppStore,
private val settings: Settings,
private val browserStore: BrowserStore,
private val tabsUseCases: TabsUseCases,
private val showUndoSnackbar: (Boolean) -> Unit,
) : InactiveTabsController {

override fun openInactiveTab(tab: TabSessionState) {
TabsTrayMetrics.openInactiveTab.add()
}

override fun closeInactiveTab(tab: TabSessionState) {
TabsTrayMetrics.closeInactiveTab.add()
}

override fun updateCardExpansion(isExpanded: Boolean) {
appStore.dispatch(UpdateInactiveExpanded(isExpanded))

when (isExpanded) {
Expand All @@ -55,18 +86,12 @@ class InactiveTabsController(
}
}

/**
* Dismiss the auto-close dialog.
*/
fun close() {
override fun dismissAutoCloseDialog() {
markDialogAsShown()
TabsTrayMetrics.autoCloseDimissed.record(NoExtras())
}

/**
* Enable the auto-close feature with the after a month setting.
*/
fun enableAutoClosed() {
override fun enableInactiveTabsAutoClose() {
markDialogAsShown()
settings.closeTabsAfterOneMonth = true
settings.closeTabsAfterOneWeek = false
Expand All @@ -75,6 +100,14 @@ class InactiveTabsController(
TabsTrayMetrics.autoCloseTurnOnClicked.record(NoExtras())
}

override fun deleteAllInactiveTabs() {
TabsTrayMetrics.closeAllInactiveTabs.record(NoExtras())
browserStore.state.potentialInactiveTabs.map { it.id }.let {
tabsUseCases.removeTabs(it)
}
showUndoSnackbar(false)
}

/**
* Marks the dialog as shown and to not be displayed again.
*/
Expand Down
Loading

0 comments on commit 5f7fd53

Please sign in to comment.