[fenix] For https://github.com/mozilla-mobile/fenix/issues/28266 - Merge `BrowserTrayInteractor` into `TabsTrayInteractor`

pull/600/head
Noah Bond 1 year ago committed by mergify[bot]
parent 4fa35e3d37
commit 6ed5a569c8

@ -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.
@ -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>) {

@ -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
@ -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.
@ -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.
@ -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)
@ -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.
@ -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,
@ -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)
@ -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)))
}
/**
@ -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?,
@ -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
}
}

@ -6,7 +6,6 @@ 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.
@ -14,11 +13,11 @@ import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
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
}

@ -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
@ -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
@ -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,
@ -213,7 +210,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
tabsTrayController = DefaultTabsTrayController(
activity = activity,
trayStore = tabsTrayStore,
tabsTrayStore = tabsTrayStore,
browserStore = requireComponents.core.store,
browsingModeManager = activity.browsingModeManager,
navController = findNavController(),
@ -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(
@ -244,7 +236,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
tabsUseCases = requireComponents.useCases.tabsUseCases,
showUndoSnackbar = ::showUndoSnackbarForTab,
),
browserInteractor = browserTrayInteractor,
tabsTrayInteractor = tabsTrayInteractor,
)
setupMenu(navigationInteractor)
@ -253,8 +245,6 @@ class TabsTrayFragment : AppCompatDialogFragment() {
lifecycleOwner = viewLifecycleOwner,
store = tabsTrayStore,
trayInteractor = tabsTrayInteractor,
browserInteractor = browserTrayInteractor,
navigationInteractor = navigationInteractor,
inactiveTabsInteractor = inactiveTabsInteractor,
)
@ -332,7 +322,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
feature = FloatingActionButtonBinding(
store = tabsTrayStore,
actionButton = fabButtonBinding.newTabButton,
interactor = browserTrayInteractor,
interactor = tabsTrayInteractor,
),
owner = this,
view = view,
@ -495,8 +485,6 @@ class TabsTrayFragment : AppCompatDialogFragment() {
lifecycleOwner: LifecycleOwner,
store: TabsTrayStore,
trayInteractor: TabsTrayInteractor,
browserInteractor: BrowserTrayInteractor,
navigationInteractor: NavigationInteractor,
inactiveTabsInteractor: InactiveTabsInteractor,
) {
tabsTrayBinding.tabsTray.apply {
@ -504,8 +492,6 @@ class TabsTrayFragment : AppCompatDialogFragment() {
context = context,
lifecycleOwner = lifecycleOwner,
tabsTrayStore = store,
browserInteractor = browserInteractor,
navInteractor = navigationInteractor,
tabsTrayInteractor = trayInteractor,
browserStore = requireComponents.core.store,
appStore = requireComponents.appStore,

@ -6,76 +6,126 @@ package org.mozilla.fenix.tabstray
import mozilla.components.browser.state.state.TabSessionState
import mozilla.components.browser.storage.sync.Tab
import mozilla.components.browser.tabstray.TabsTray
import org.mozilla.fenix.selection.SelectionHolder
/**
* Interactor for responding to all user actions in the tabs tray.
*/
interface TabsTrayInteractor : SyncedTabsInteractor {
interface TabsTrayInteractor : SyncedTabsInteractor, TabsTray.Delegate {
/**
* Set the current tray item to the clamped [position].
* Invoked when a page in the tabs tray is selected.
*
* @param position The position on the tray to focus.
* @param smoothScroll If true, animate the scrolling from the current tab to [position].
*/
fun onTrayPositionSelected(position: Int, smoothScroll: Boolean)
/**
* Dismisses the tabs tray and navigates to the browser.
*/
fun onBrowserTabSelected()
/**
* Invoked when a tab is removed from the tabs tray with the given [tabId].
* @param source app feature from which the [TabSessionState] with [tabId] was closed.
*/
fun onDeleteTab(tabId: String, source: String? = null)
/**
* Invoked when the user confirmed tab removal that would lead to cancelled private downloads.
*
* @param source is the app feature from which the [TabSessionState] with [tabId] was closed.
*/
fun onDeletePrivateTabWarningAccepted(tabId: String, source: String? = null)
/**
* Invoked when [TabSessionState]s need to be deleted.
* Invoked when tabs are requested to be deleted.
*
* @param tabs The group of [TabSessionState] to be deleted.
*/
fun onDeleteTabs(tabs: Collection<TabSessionState>)
/**
* Called when clicking the debug menu option for inactive tabs.
* Invoked when the debug menu option for inactive tabs is clicked.
*
* @param tabs The group of [TabSessionState] to be made inactive.
*/
fun onInactiveDebugClicked(tabs: Collection<TabSessionState>)
/**
* Invoked when [tabId] should be moved to before/after [targetId] from a drag-drop operation
* Invoked when a drag-drop operation with a tab is completed.
*
* @param tabId ID of the tab being moved.
* @param targetId ID of the tab the moved tab's new neighbor.
* @param placeAfter [Boolean] indicating whether the moved tab is being placed before or after [targetId].
*/
fun onTabsMove(
tabId: String,
targetId: String?,
placeAfter: Boolean,
)
/**
* Invoked when the TabTray's Floating Action Button is clicked.
*
* @param isPrivate [Boolean] indicating whether the FAB was clicked in the private page of the tabs tray.
*/
fun onFabClicked(isPrivate: Boolean)
/**
* Invoked when the recently closed item is clicked.
*/
fun onRecentlyClosedClicked()
/**
* Invoked when the a tab's media controls are clicked.
*
* @param tab [TabSessionState] to close.
*/
fun onMediaClicked(tab: TabSessionState)
/**
* Invoked when tabs are clicked when multi-selection is enabled.
*
* @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 onMultiSelectClicked(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
source: String?,
)
/**
* Invoked when a tab is long clicked.
*
* @param tab [TabSessionState] that was clicked.
* @param holder [SelectionHolder] used to access the current selection of tabs.
*/
fun onTabLongClicked(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
): Boolean
/**
* Invoked when the back button is pressed.
*
* @return true if the back button press was consumed.
*/
fun onBackPressed(): Boolean
/**
* Invoked when a tab is unselected.
*
* @param tab [TabSessionState] that was unselected.
*/
fun onTabUnselected(tab: TabSessionState)
}
/**
* Default implementation of [TabsTrayInteractor].
*
* @property controller [TabsTrayController] to which user actions can be delegated for actual app update.
* @property controller [TabsTrayController] to which user actions can be delegated for app updates.
*/
class DefaultTabsTrayInteractor(
private val controller: TabsTrayController,
) : TabsTrayInteractor {
override fun onTrayPositionSelected(position: Int, smoothScroll: Boolean) {
controller.handleTrayScrollingToPosition(position, smoothScroll)
}
override fun onBrowserTabSelected() {
controller.handleNavigateToBrowser()
}
override fun onDeleteTab(tabId: String, source: String?) {
controller.handleTabDeletion(tabId, source)
}
override fun onDeletePrivateTabWarningAccepted(tabId: String, source: String?) {
controller.handleDeleteTabWarningAccepted(tabId, source)
}
@ -99,4 +149,42 @@ class DefaultTabsTrayInteractor(
override fun onSyncedTabClicked(tab: Tab) {
controller.handleSyncedTabClicked(tab)
}
override fun onBackPressed(): Boolean = controller.handleBackPressed()
override fun onTabClosed(tab: TabSessionState, source: String?) {
controller.handleTabDeletion(tab.id, source)
}
override fun onTabSelected(tab: TabSessionState, source: String?) {
controller.handleTabSelected(tab, source)
}
override fun onFabClicked(isPrivate: Boolean) {
controller.handleOpeningNewTab(isPrivate)
}
override fun onRecentlyClosedClicked() {
controller.handleNavigateToRecentlyClosed()
}
override fun onMediaClicked(tab: TabSessionState) {
controller.handleMediaClicked(tab)
}
override fun onMultiSelectClicked(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
source: String?,
) {
controller.handleMultiSelectClicked(tab, holder, source)
}
override fun onTabLongClicked(tab: TabSessionState, holder: SelectionHolder<TabSessionState>): Boolean {
return controller.handleTabLongClick(tab, holder)
}
override fun onTabUnselected(tab: TabSessionState) {
controller.handleTabUnselected(tab)
}
}

@ -14,7 +14,6 @@ import androidx.recyclerview.widget.RecyclerView
import mozilla.components.browser.state.store.BrowserStore
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.tabstray.browser.BrowserTabsAdapter
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
import org.mozilla.fenix.tabstray.browser.InactiveTabsAdapter
import org.mozilla.fenix.tabstray.browser.InactiveTabsInteractor
import org.mozilla.fenix.tabstray.viewholders.AbstractPageViewHolder
@ -27,8 +26,6 @@ class TrayPagerAdapter(
internal val context: Context,
internal val lifecycleOwner: LifecycleOwner,
internal val tabsTrayStore: TabsTrayStore,
internal val browserInteractor: BrowserTrayInteractor,
internal val navInteractor: NavigationInteractor,
internal val tabsTrayInteractor: TabsTrayInteractor,
internal val browserStore: BrowserStore,
internal val appStore: AppStore,
@ -48,14 +45,14 @@ class TrayPagerAdapter(
inactiveTabsInteractor = inactiveTabsInteractor,
featureName = INACTIVE_TABS_FEATURE_NAME,
),
BrowserTabsAdapter(context, browserInteractor, tabsTrayStore, TABS_TRAY_FEATURE_NAME, lifecycleOwner),
BrowserTabsAdapter(context, tabsTrayInteractor, tabsTrayStore, TABS_TRAY_FEATURE_NAME, lifecycleOwner),
)
}
private val privateAdapter by lazy {
BrowserTabsAdapter(
context,
browserInteractor,
tabsTrayInteractor,
tabsTrayStore,
TABS_TRAY_FEATURE_NAME,
lifecycleOwner,

@ -39,6 +39,7 @@ import org.mozilla.fenix.ext.removeAndDisable
import org.mozilla.fenix.ext.removeTouchDelegate
import org.mozilla.fenix.ext.showAndEnable
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayState
import org.mozilla.fenix.tabstray.TabsTrayStore
@ -73,7 +74,7 @@ abstract class AbstractBrowserTabViewHolder(
internal val urlView: TextView? = itemView.findViewById(R.id.mozac_browser_tabstray_url)
private val playPauseButtonView: ImageButton = itemView.findViewById(R.id.play_pause_button)
abstract val interactor: BrowserTrayInteractor
abstract val interactor: TabsTrayInteractor
abstract val thumbnailSize: Int
override var tab: TabSessionState? = null
@ -207,14 +208,14 @@ abstract class AbstractBrowserTabViewHolder(
private fun setSelectionInteractor(
item: TabSessionState,
holder: SelectionHolder<TabSessionState>,
interactor: BrowserTrayInteractor,
interactor: TabsTrayInteractor,
) {
itemView.setOnClickListener {
interactor.onMultiSelectClicked(item, holder, featureName)
}
itemView.setOnLongClickListener {
interactor.onLongClicked(item, holder)
interactor.onTabLongClicked(item, holder)
}
setDragInteractor(item, holder, interactor)
}
@ -223,7 +224,7 @@ abstract class AbstractBrowserTabViewHolder(
private fun setDragInteractor(
item: TabSessionState,
holder: SelectionHolder<TabSessionState>,
interactor: BrowserTrayInteractor,
interactor: TabsTrayInteractor,
) {
// Since I immediately pass the event to onTouchEvent if it's not a move
// The ClickableViewAccessibility warning isn't useful
@ -248,7 +249,7 @@ abstract class AbstractBrowserTabViewHolder(
// Only start deselect+drag if the user drags far enough
val dist = PointF.length(touchStart.x - motionEvent.x, touchStart.y - motionEvent.y)
if (dist > ViewConfiguration.get(parent.context).scaledTouchSlop) {
interactor.deselect(item) // Exit selection mode
interactor.onTabUnselected(item) // Exit selection mode
touchStartPoint = null
val dragOffset = PointF(motionEvent.x, motionEvent.y)
val shadow = BlankDragShadowBuilder()

@ -17,6 +17,7 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.TabTrayGridItemBinding
import org.mozilla.fenix.ext.increaseTapArea
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayStore
import kotlin.math.max
@ -25,7 +26,7 @@ sealed class BrowserTabViewHolder(itemView: View) : RecyclerView.ViewHolder(item
* A RecyclerView ViewHolder implementation for "tab" items with grid layout.
*
* @param imageLoader [ImageLoader] used to load tab thumbnails.
* @param interactor [BrowserTrayInteractor] handling tabs interactions in a tab tray.
* @param interactor [TabsTrayInteractor] handling tabs interactions in a tab tray.
* @param store [TabsTrayStore] containing the complete state of tabs tray and methods to update that.
* @param selectionHolder [SelectionHolder]<[TabSessionState]> for helping with selecting
* any number of displayed [TabSessionState]s.
@ -34,7 +35,7 @@ sealed class BrowserTabViewHolder(itemView: View) : RecyclerView.ViewHolder(item
*/
class GridViewHolder(
imageLoader: ImageLoader,
override val interactor: BrowserTrayInteractor,
override val interactor: TabsTrayInteractor,
store: TabsTrayStore,
selectionHolder: SelectionHolder<TabSessionState>? = null,
itemView: View,
@ -79,7 +80,7 @@ sealed class BrowserTabViewHolder(itemView: View) : RecyclerView.ViewHolder(item
* A RecyclerView ViewHolder implementation for "tab" items with list layout.
*
* @param imageLoader [ImageLoader] used to load tab thumbnails.
* @param interactor [BrowserTrayInteractor] handling tabs interactions in a tab tray.
* @param interactor [TabsTrayInteractor] handling tabs interactions in a tab tray.
* @param store [TabsTrayStore] containing the complete state of tabs tray and methods to update that.
* @param selectionHolder [SelectionHolder]<[TabSessionState]> for helping with selecting
* any number of displayed [TabSessionState]s.
@ -88,7 +89,7 @@ sealed class BrowserTabViewHolder(itemView: View) : RecyclerView.ViewHolder(item
*/
class ListViewHolder(
imageLoader: ImageLoader,
override val interactor: BrowserTrayInteractor,
override val interactor: TabsTrayInteractor,
store: TabsTrayStore,
selectionHolder: SelectionHolder<TabSessionState>? = null,
itemView: View,

@ -22,6 +22,7 @@ import org.mozilla.fenix.databinding.TabTrayGridItemBinding
import org.mozilla.fenix.databinding.TabTrayItemBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayStore
import org.mozilla.fenix.tabstray.browser.compose.ComposeGridViewHolder
import org.mozilla.fenix.tabstray.browser.compose.ComposeListViewHolder
@ -30,14 +31,14 @@ import org.mozilla.fenix.tabstray.browser.compose.ComposeListViewHolder
* A [RecyclerView.Adapter] for browser tabs.
*
* @param context [Context] used for various platform interactions or accessing [Components]
* @param interactor [BrowserTrayInteractor] handling tabs interactions in a tab tray.
* @param interactor [TabsTrayInteractor] handling tabs interactions in a tab tray.
* @param store [TabsTrayStore] containing the complete state of tabs tray and methods to update that.
* @param featureName [String] representing the name of the feature displaying tabs. Used in telemetry reporting.
* @param viewLifecycleOwner [LifecycleOwner] life cycle owner for the view.
*/
class BrowserTabsAdapter(
private val context: Context,
val interactor: BrowserTrayInteractor,
val interactor: TabsTrayInteractor,
private val store: TabsTrayStore,
override val featureName: String,
internal val viewLifecycleOwner: LifecycleOwner,
@ -133,12 +134,16 @@ class BrowserTabsAdapter(
ViewType.GRID.layoutRes -> {
val gridBinding = TabTrayGridItemBinding.bind(holder.itemView)
selectedMaskView = gridBinding.checkboxInclude.selectedMask
gridBinding.mozacBrowserTabstrayClose.setOnClickListener { interactor.close(tab, featureName) }
gridBinding.mozacBrowserTabstrayClose.setOnClickListener {
interactor.onTabClosed(tab, featureName)
}
}
ViewType.LIST.layoutRes -> {
val listBinding = TabTrayItemBinding.bind(holder.itemView)
selectedMaskView = listBinding.checkboxInclude.selectedMask
listBinding.mozacBrowserTabstrayClose.setOnClickListener { interactor.close(tab, featureName) }
listBinding.mozacBrowserTabstrayClose.setOnClickListener {
interactor.onTabClosed(tab, featureName)
}
}
}

@ -1,213 +0,0 @@
/* 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.tabstray.browser
import mozilla.components.browser.state.state.TabSessionState
import mozilla.components.browser.tabstray.TabsTray
import mozilla.components.feature.tabs.TabsUseCases
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.telemetry.glean.private.NoExtras
import org.mozilla.fenix.GleanMetrics.Collections
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.selection.SelectionInteractor
import org.mozilla.fenix.tabstray.TabsTrayAction
import org.mozilla.fenix.tabstray.TabsTrayController
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayState.Mode
import org.mozilla.fenix.tabstray.TabsTrayStore
import org.mozilla.fenix.tabstray.ext.isSelect
/**
* For interacting with UI that is specifically for [AbstractBrowserTrayList] and other browser
* tab tray views.
*/
interface BrowserTrayInteractor : SelectionInteractor<TabSessionState>, UserInteractionHandler, TabsTray.Delegate {
/**
* Open a tab.
*
* @param tab [TabSessionState] to open in browser.
* @param source app feature from which the [tab] was opened.
*/
fun open(tab: TabSessionState, source: String? = null)
/**
* Close the tab.
*
* @param tab [TabSessionState] to close.
* @param source app feature from which the [tab] was closed.
*/
fun close(tab: TabSessionState, source: String? = null)
/**
* TabTray's Floating Action Button clicked.
*/
fun onFabClicked(isPrivate: Boolean)
/**
* Recently Closed item is clicked.
*/
fun onRecentlyClosedClicked()
/**
* Indicates Play/Pause item is clicked.
* @param tab [TabSessionState] to close.
*/
fun onMediaClicked(tab: TabSessionState)
/**
* Handles clicks when multi-selection is enabled.
*/
fun onMultiSelectClicked(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
source: String?,
)
/**
* Handles long click events when tab item is clicked.
*/
fun onLongClicked(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
): Boolean
}
/**
* A default implementation of [BrowserTrayInteractor].
*/
@Suppress("TooManyFunctions")
class DefaultBrowserTrayInteractor(
private val store: TabsTrayStore,
private val trayInteractor: TabsTrayInteractor,
private val controller: TabsTrayController,
private val selectTab: TabsUseCases.SelectTabUseCase,
) : BrowserTrayInteractor {
private val selectTabWrapper by lazy {
SelectTabUseCaseWrapper(selectTab) {
trayInteractor.onBrowserTabSelected()
}
}
/**
* See [SelectionInteractor.open]
*/
override fun open(item: TabSessionState) {
open(item, null)
}
/**
* See [BrowserTrayInteractor.open].
*/
override fun open(tab: TabSessionState, source: String?) {
selectTab(tab, source)
}
/**
* See [BrowserTrayInteractor.close].
*/
override fun close(tab: TabSessionState, source: String?) {
closeTab(tab, source)
}
/**
* See [SelectionInteractor.select]
*/
override fun select(item: TabSessionState) {
store.dispatch(TabsTrayAction.AddSelectTab(item))
}
/**
* See [SelectionInteractor.deselect]
*/
override fun deselect(item: TabSessionState) {
store.dispatch(TabsTrayAction.RemoveSelectTab(item))
}
/**
* See [UserInteractionHandler.onBackPressed]
*
* TODO move this to the navigation interactor when it lands.
*/
override fun onBackPressed(): Boolean {
if (store.state.mode is Mode.Select) {
store.dispatch(TabsTrayAction.ExitSelectMode)
return true
}
return false
}
override fun onTabClosed(tab: TabSessionState, source: String?) {
closeTab(tab, source)
}
override fun onTabSelected(tab: TabSessionState, source: String?) {
selectTab(tab, source)
}
/**
* See [BrowserTrayInteractor.onFabClicked]
*/
override fun onFabClicked(isPrivate: Boolean) {
controller.handleOpeningNewTab(isPrivate)
}
/**
* See [BrowserTrayInteractor.onRecentlyClosedClicked]
*/
override fun onRecentlyClosedClicked() {
controller.handleNavigateToRecentlyClosed()
}
/**
* See [BrowserTrayInteractor.onMultiSelectClicked]
*/
override fun onMediaClicked(tab: TabSessionState) {
controller.handleMediaClicked(tab)
}
/**
* See [BrowserTrayInteractor.onMultiSelectClicked]
*/
override fun onMultiSelectClicked(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
source: String?,
) {
val selected = holder.selectedItems
when {
selected.isEmpty() && store.state.mode.isSelect().not() -> {
onTabSelected(tab, source)
}
tab.id in selected.map { it.id } -> deselect(tab)
else -> select(tab)
}
}
/**
* See [BrowserTrayInteractor.onLongClicked]
*/
override fun onLongClicked(
tab: TabSessionState,
holder: SelectionHolder<TabSessionState>,
): Boolean {
return if (holder.selectedItems.isEmpty()) {
Collections.longPress.record(NoExtras())
select(tab)
true
} else {
false
}
}
private fun selectTab(tab: TabSessionState, source: String? = null) {
selectTabWrapper.invoke(tab.id, source)
}
private fun closeTab(tab: TabSessionState, source: String? = null) {
trayInteractor.onDeleteTab(tab.id, source)
}
}

@ -5,6 +5,7 @@
package org.mozilla.fenix.tabstray.browser
import mozilla.components.browser.state.state.TabSessionState
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TrayPagerAdapter
/**
@ -53,12 +54,12 @@ interface InactiveTabsInteractor {
*
* @param controller An instance of [InactiveTabsController] which will be delegated for all
* user interactions.
* @param browserInteractor [BrowserTrayInteractor] used to respond to interactions with specific
* @param tabsTrayInteractor [TabsTrayInteractor] used to respond to interactions with specific
* inactive tabs.
*/
class DefaultInactiveTabsInteractor(
private val controller: InactiveTabsController,
private val browserInteractor: BrowserTrayInteractor,
private val tabsTrayInteractor: TabsTrayInteractor,
) : InactiveTabsInteractor {
/**
@ -87,7 +88,7 @@ class DefaultInactiveTabsInteractor(
*/
override fun onInactiveTabClicked(tab: TabSessionState) {
controller.handleInactiveTabClicked(tab)
browserInteractor.onTabSelected(tab, TrayPagerAdapter.INACTIVE_TABS_FEATURE_NAME)
tabsTrayInteractor.onTabSelected(tab, TrayPagerAdapter.INACTIVE_TABS_FEATURE_NAME)
}
/**
@ -95,7 +96,7 @@ class DefaultInactiveTabsInteractor(
*/
override fun onInactiveTabClosed(tab: TabSessionState) {
controller.handleCloseInactiveTabClicked(tab)
browserInteractor.onTabClosed(tab, TrayPagerAdapter.INACTIVE_TABS_FEATURE_NAME)
tabsTrayInteractor.onTabClosed(tab, TrayPagerAdapter.INACTIVE_TABS_FEATURE_NAME)
}
/**

@ -17,14 +17,14 @@ import mozilla.components.browser.tabstray.TabsTrayStyling
import mozilla.components.lib.state.ext.observeAsComposableState
import org.mozilla.fenix.compose.tabstray.TabGridItem
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayState
import org.mozilla.fenix.tabstray.TabsTrayStore
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
/**
* A Compose ViewHolder implementation for "tab" items with grid layout.
*
* @param interactor [BrowserTrayInteractor] handling tabs interactions in a tab tray.
* @param interactor [TabsTrayInteractor] handling tabs interactions in a tab tray.
* @param store [TabsTrayStore] containing the complete state of tabs tray and methods to update that.
* @param selectionHolder [SelectionHolder]<[TabSessionState]> for helping with selecting
* any number of displayed [TabSessionState]s.
@ -33,7 +33,7 @@ import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
* @param viewLifecycleOwner [LifecycleOwner] to which this Composable will be tied to.
*/
class ComposeGridViewHolder(
private val interactor: BrowserTrayInteractor,
private val interactor: TabsTrayInteractor,
private val store: TabsTrayStore,
private val selectionHolder: SelectionHolder<TabSessionState>? = null,
composeItemView: ComposeView,
@ -79,7 +79,7 @@ class ComposeGridViewHolder(
private fun onLongClick(tab: TabSessionState) {
val holder = selectionHolder ?: return
interactor.onLongClicked(tab, holder)
interactor.onTabLongClicked(tab, holder)
}
@Composable

@ -17,14 +17,14 @@ import mozilla.components.browser.tabstray.TabsTrayStyling
import mozilla.components.lib.state.ext.observeAsComposableState
import org.mozilla.fenix.compose.tabstray.TabListItem
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayState
import org.mozilla.fenix.tabstray.TabsTrayStore
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
/**
* A Compose ViewHolder implementation for "tab" items with list layout.
*
* @param interactor [BrowserTrayInteractor] handling tabs interactions in a tab tray.
* @param interactor [TabsTrayInteractor] handling tabs interactions in a tab tray.
* @param tabsTrayStore [TabsTrayStore] containing the complete state of tabs tray and methods to update that.
* @param selectionHolder [SelectionHolder]<[TabSessionState]> for helping with selecting
* any number of displayed [TabSessionState]s.
@ -33,7 +33,7 @@ import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
* @param viewLifecycleOwner [LifecycleOwner] to which this Composable will be tied to.
*/
class ComposeListViewHolder(
private val interactor: BrowserTrayInteractor,
private val interactor: TabsTrayInteractor,
private val tabsTrayStore: TabsTrayStore,
private val selectionHolder: SelectionHolder<TabSessionState>? = null,
composeItemView: ComposeView,
@ -82,7 +82,7 @@ class ComposeListViewHolder(
private fun onLongClick(tab: TabSessionState) {
val holder = selectionHolder ?: return
interactor.onLongClicked(tab, holder)
interactor.onTabLongClicked(tab, holder)
}
@Composable

@ -4,6 +4,7 @@
package org.mozilla.fenix.tabstray
import io.mockk.every
import io.mockk.mockk
import io.mockk.verifySequence
import mozilla.components.browser.state.state.TabSessionState
@ -12,41 +13,45 @@ import org.junit.Test
class DefaultTabsTrayInteractorTest {
val controller: TabsTrayController = mockk(relaxed = true)
val trayInteractor = DefaultTabsTrayInteractor(controller)
val interactor = DefaultTabsTrayInteractor(controller)
@Test
fun `GIVEN user selecting a new tray page WHEN onTrayPositionSelected is called THEN the Interactor delegates the controller`() {
trayInteractor.onTrayPositionSelected(14, true)
fun `WHEN user selects a new tray page THEN the Interactor delegates to the controller`() {
interactor.onTrayPositionSelected(14, true)
verifySequence { controller.handleTrayScrollingToPosition(14, true) }
}
@Test
fun `GIVEN user selecting a new browser tab WHEN onBrowserTabSelected is called THEN the Interactor delegates the controller`() {
trayInteractor.onBrowserTabSelected()
fun `WHEN user selects a new browser tab THEN the Interactor delegates to the controller`() {
val tab: TabSessionState = mockk()
interactor.onTabSelected(tab, null)
verifySequence { controller.handleNavigateToBrowser() }
verifySequence { controller.handleTabSelected(tab, null) }
}
@Test
fun `GIVEN user deleted one browser tab page WHEN onDeleteTab is called THEN the Interactor delegates the controller`() {
trayInteractor.onDeleteTab("testTabId")
fun `WHEN user deletes one browser tab page THEN the Interactor delegates to the controller`() {
val tab: TabSessionState = mockk()
val id = "testTabId"
every { tab.id } returns id
interactor.onTabClosed(tab)
verifySequence { controller.handleTabDeletion("testTabId") }
verifySequence { controller.handleTabDeletion(id) }
}
@Test
fun `GIVEN user confirmed downloads cancellation WHEN onDeletePrivateTabWarningAccepted is called THEN the Interactor delegates the controller`() {
trayInteractor.onDeletePrivateTabWarningAccepted("testTabId")
fun `WHEN user confirms downloads cancellation THEN the Interactor delegates to the controller`() {
interactor.onDeletePrivateTabWarningAccepted("testTabId")
verifySequence { controller.handleDeleteTabWarningAccepted("testTabId") }
}
@Test
fun `GIVEN user deleted multiple browser tabs WHEN onDeleteTabs is called THEN the Interactor delegates the controller`() {
fun `WHEN user deletes multiple browser tabs THEN the Interactor delegates to the controller`() {
val tabsToDelete = listOf<TabSessionState>(mockk(), mockk())
trayInteractor.onDeleteTabs(tabsToDelete)
interactor.onDeleteTabs(tabsToDelete)
verifySequence { controller.handleMultipleTabsDeletion(tabsToDelete) }
}

@ -19,7 +19,6 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
class FloatingActionButtonBindingTest {
@ -28,7 +27,7 @@ class FloatingActionButtonBindingTest {
val coroutinesTestRule = MainCoroutineRule()
private val actionButton: ExtendedFloatingActionButton = mockk(relaxed = true)
private val interactor: BrowserTrayInteractor = mockk(relaxed = true)
private val interactor: TabsTrayInteractor = mockk(relaxed = true)
@Before
fun setup() {

@ -8,13 +8,12 @@ import android.content.Context
import io.mockk.mockk
import io.mockk.verify
import org.junit.Test
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
class TabsTrayDialogTest {
@Test
fun `WHEN onBackPressed THEN invoke interactor`() {
val context = mockk<Context>(relaxed = true)
val interactor = mockk<BrowserTrayInteractor>(relaxed = true)
val interactor = mockk<TabsTrayInteractor>(relaxed = true)
val dialog = TabsTrayDialog(context, 0) { interactor }
@Suppress("DEPRECATION")

@ -53,7 +53,6 @@ import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.helpers.MockkRetryTestRule
import org.mozilla.fenix.home.HomeScreenViewModel
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
import org.mozilla.fenix.tabstray.browser.InactiveTabsInteractor
import org.mozilla.fenix.tabstray.ext.showWithTheme
import org.mozilla.fenix.utils.allowUndo
@ -222,8 +221,6 @@ class TabsTrayFragmentTest {
val store: TabsTrayStore = mockk()
val lifecycleOwner = mockk<LifecycleOwner>(relaxed = true)
val trayInteractor: TabsTrayInteractor = mockk()
val browserInteractor: BrowserTrayInteractor = mockk()
val navigationInteractor: NavigationInteractor = mockk()
val inactiveTabsInteractor: InactiveTabsInteractor = mockk()
val browserStore: BrowserStore = mockk()
every { context.components.core.store } returns browserStore
@ -233,8 +230,6 @@ class TabsTrayFragmentTest {
lifecycleOwner = lifecycleOwner,
store = store,
trayInteractor = trayInteractor,
browserInteractor = browserInteractor,
navigationInteractor = navigationInteractor,
inactiveTabsInteractor = inactiveTabsInteractor,
)
@ -243,8 +238,6 @@ class TabsTrayFragmentTest {
assertSame(lifecycleOwner, adapter.lifecycleOwner)
assertSame(store, adapter.tabsTrayStore)
assertSame(trayInteractor, adapter.tabsTrayInteractor)
assertSame(browserInteractor, adapter.browserInteractor)
assertSame(navigationInteractor, adapter.navInteractor)
assertSame(browserStore, adapter.browserStore)
assertFalse(tabsTrayBinding.tabsTray.isUserInputEnabled)
}

@ -31,6 +31,7 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayStore
@RunWith(FenixRobolectricTestRunner::class)
@ -40,7 +41,7 @@ class AbstractBrowserTabViewHolderTest {
val store = TabsTrayStore()
val browserStore = BrowserStore()
val interactor = mockk<BrowserTrayInteractor>(relaxed = true)
val interactor = mockk<TabsTrayInteractor>(relaxed = true)
@Test
fun `WHEN itemView is clicked THEN interactor invokes open`() {
@ -165,7 +166,7 @@ class AbstractBrowserTabViewHolderTest {
trayStore: TabsTrayStore,
selectionHolder: SelectionHolder<TabSessionState>?,
store: BrowserStore,
override val interactor: BrowserTrayInteractor,
override val interactor: TabsTrayInteractor,
featureName: String = "Test",
) : AbstractBrowserTabViewHolder(itemView, imageLoader, trayStore, selectionHolder, featureName, store) {
override val thumbnailSize: Int

@ -21,13 +21,14 @@ import org.mozilla.fenix.databinding.TabTrayItemBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayStore
@RunWith(FenixRobolectricTestRunner::class)
class BrowserTabsAdapterTest {
private val context = testContext
private val interactor = mockk<BrowserTrayInteractor>(relaxed = true)
private val interactor = mockk<TabsTrayInteractor>(relaxed = true)
private val store = TabsTrayStore()
@Test

@ -9,12 +9,13 @@ import io.mockk.verify
import mozilla.components.browser.state.state.ContentState
import mozilla.components.browser.state.state.TabSessionState
import org.junit.Test
import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TrayPagerAdapter
class DefaultInactiveTabsInteractorTest {
private val controller: InactiveTabsController = mockk(relaxed = true)
private val browserInteractor: BrowserTrayInteractor = mockk(relaxed = true)
private val interactor: TabsTrayInteractor = mockk(relaxed = true)
@Test
fun `WHEN the inactive tabs header is clicked THEN update the expansion state of the inactive tabs card`() {
@ -49,7 +50,7 @@ class DefaultInactiveTabsInteractorTest {
createInteractor().onInactiveTabClicked(tab)
verify { controller.handleInactiveTabClicked(tab) }
verify { browserInteractor.onTabSelected(tab, TrayPagerAdapter.INACTIVE_TABS_FEATURE_NAME) }
verify { interactor.onTabSelected(tab, TrayPagerAdapter.INACTIVE_TABS_FEATURE_NAME) }
}
@Test
@ -64,7 +65,7 @@ class DefaultInactiveTabsInteractorTest {
createInteractor().onInactiveTabClosed(tab)
verify { controller.handleCloseInactiveTabClicked(tab) }
verify { browserInteractor.onTabClosed(tab, TrayPagerAdapter.INACTIVE_TABS_FEATURE_NAME) }
verify { interactor.onTabClosed(tab, TrayPagerAdapter.INACTIVE_TABS_FEATURE_NAME) }
}
@Test
@ -77,7 +78,7 @@ class DefaultInactiveTabsInteractorTest {
private fun createInteractor(): DefaultInactiveTabsInteractor {
return DefaultInactiveTabsInteractor(
controller = controller,
browserInteractor = browserInteractor,
tabsTrayInteractor = interactor,
)
}
}

@ -23,21 +23,19 @@ import org.mozilla.fenix.tabstray.TabsTrayInteractor
import org.mozilla.fenix.tabstray.TabsTrayStore
import org.mozilla.fenix.tabstray.browser.AbstractBrowserTrayList
import org.mozilla.fenix.tabstray.browser.BrowserTabsAdapter
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
@RunWith(FenixRobolectricTestRunner::class)
class AbstractBrowserPageViewHolderTest {
val tabsTrayStore: TabsTrayStore = TabsTrayStore()
val browserStore = BrowserStore()
val interactor = mockk<TabsTrayInteractor>(relaxed = true)
val browserTrayInteractor = mockk<BrowserTrayInteractor>(relaxed = true)
init {
every { testContext.components.core.thumbnailStorage } returns mockk()
every { testContext.components.settings } returns mockk(relaxed = true)
}
val adapter =
BrowserTabsAdapter(testContext, browserTrayInteractor, tabsTrayStore, "Test", mockk())
BrowserTabsAdapter(testContext, interactor, tabsTrayStore, "Test", mockk())
@Test
fun `WHEN tabs inserted THEN show tray`() {

Loading…
Cancel
Save