mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-07 15:20:38 +00:00
For #26227 - Remove search term tab groups from Jump Back In
This commit is contained in:
parent
9fb6eeb8cf
commit
fa00527dc6
@ -93,7 +93,6 @@ import org.mozilla.fenix.perf.StrictModeManager
|
||||
import org.mozilla.fenix.perf.lazyMonitored
|
||||
import org.mozilla.fenix.settings.SupportUtils
|
||||
import org.mozilla.fenix.settings.advanced.getSelectedLocale
|
||||
import org.mozilla.fenix.tabstray.SearchTermTabGroupMiddleware
|
||||
import org.mozilla.fenix.telemetry.TelemetryMiddleware
|
||||
import org.mozilla.fenix.utils.getUndoDelay
|
||||
import org.mozilla.geckoview.GeckoRuntime
|
||||
@ -247,7 +246,6 @@ class Core(
|
||||
AdsTelemetryMiddleware(adsTelemetry),
|
||||
LastMediaAccessMiddleware(),
|
||||
HistoryMetadataMiddleware(historyMetadataService),
|
||||
SearchTermTabGroupMiddleware()
|
||||
) + if (tabsPrioritizationEnable) {
|
||||
listOf(SessionPrioritizationMiddleware())
|
||||
} else {
|
||||
|
@ -12,11 +12,10 @@ import org.mozilla.fenix.components.AppStore
|
||||
import org.mozilla.fenix.ext.filterOutTab
|
||||
import org.mozilla.fenix.ext.getFilteredStories
|
||||
import org.mozilla.fenix.ext.recentSearchGroup
|
||||
import org.mozilla.fenix.gleanplumb.state.MessagingReducer
|
||||
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesSelectedCategory
|
||||
import org.mozilla.fenix.home.recenttabs.RecentTab
|
||||
import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem
|
||||
import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem.RecentHistoryGroup
|
||||
import org.mozilla.fenix.gleanplumb.state.MessagingReducer
|
||||
|
||||
/**
|
||||
* Reducer for [AppStore].
|
||||
@ -44,12 +43,7 @@ internal object AppStoreReducer {
|
||||
topSites = action.topSites,
|
||||
recentBookmarks = action.recentBookmarks,
|
||||
recentTabs = action.recentTabs,
|
||||
recentHistory = if (action.recentHistory.isNotEmpty() && action.recentTabs.isNotEmpty()) {
|
||||
val recentSearchGroup = action.recentTabs.find { it is RecentTab.SearchGroup } as RecentTab.SearchGroup?
|
||||
action.recentHistory.filterOut(recentSearchGroup?.searchTerm)
|
||||
} else {
|
||||
action.recentHistory
|
||||
}
|
||||
recentHistory = action.recentHistory,
|
||||
)
|
||||
is AppAction.CollectionExpanded -> {
|
||||
val newExpandedCollection = state.expandedCollections.toMutableSet()
|
||||
@ -69,10 +63,9 @@ internal object AppStoreReducer {
|
||||
state.copy(showCollectionPlaceholder = false)
|
||||
}
|
||||
is AppAction.RecentTabsChange -> {
|
||||
val recentSearchGroup = action.recentTabs.find { it is RecentTab.SearchGroup } as RecentTab.SearchGroup?
|
||||
state.copy(
|
||||
recentTabs = action.recentTabs,
|
||||
recentHistory = state.recentHistory.filterOut(recentSearchGroup?.searchTerm)
|
||||
recentHistory = state.recentHistory,
|
||||
)
|
||||
}
|
||||
is AppAction.RemoveRecentTab -> {
|
||||
@ -90,7 +83,7 @@ internal object AppStoreReducer {
|
||||
state.copy(recentBookmarks = state.recentBookmarks.filterNot { it.url == action.recentBookmark.url })
|
||||
}
|
||||
is AppAction.RecentHistoryChange -> state.copy(
|
||||
recentHistory = action.recentHistory.filterOut(state.recentSearchGroup?.searchTerm)
|
||||
recentHistory = action.recentHistory
|
||||
)
|
||||
is AppAction.RemoveRecentHistoryHighlight -> state.copy(
|
||||
recentHistory = state.recentHistory.filterNot {
|
||||
|
@ -4,16 +4,12 @@
|
||||
|
||||
package org.mozilla.fenix.ext
|
||||
|
||||
import mozilla.components.browser.state.selector.findTab
|
||||
import mozilla.components.browser.state.selector.normalTabs
|
||||
import mozilla.components.browser.state.selector.selectedNormalTab
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.TabGroup
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.feature.tabs.ext.hasMediaPlayed
|
||||
import org.mozilla.fenix.home.recenttabs.RecentTab
|
||||
import org.mozilla.fenix.tabstray.SEARCH_TERM_TAB_GROUPS
|
||||
import org.mozilla.fenix.tabstray.SEARCH_TERM_TAB_GROUPS_MIN_SIZE
|
||||
import org.mozilla.fenix.tabstray.ext.isNormalTabInactive
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -29,26 +25,13 @@ const val DEFAULT_ACTIVE_DAYS = 14L
|
||||
val maxActiveTime = TimeUnit.DAYS.toMillis(DEFAULT_ACTIVE_DAYS)
|
||||
|
||||
/**
|
||||
* Get the last opened normal tab, last tab with in progress media and last search term group, if available.
|
||||
* Get the last opened normal tab or last tab with in progress media.
|
||||
*
|
||||
* @return A list of the last opened tab not part of the last active search group and
|
||||
* the last active search group if these are available or an empty list.
|
||||
* @return A list of the last opened tab or an empty list.
|
||||
*/
|
||||
fun BrowserState.asRecentTabs(): List<RecentTab> {
|
||||
return mutableListOf<RecentTab>().apply {
|
||||
val mostRecentTabsGroup = lastSearchGroup
|
||||
val mostRecentTabNotInGroup = if (mostRecentTabsGroup == null) {
|
||||
lastOpenedNormalTab
|
||||
} else {
|
||||
listOf(selectedNormalTab)
|
||||
.plus(normalTabs.sortedByDescending { it.lastAccess })
|
||||
.filterNot { lastTabGroup?.tabIds?.contains(it?.id) ?: false }
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
mostRecentTabNotInGroup?.let { add(RecentTab.Tab(it)) }
|
||||
|
||||
mostRecentTabsGroup?.let { add(it) }
|
||||
lastOpenedNormalTab?.let { add(RecentTab.Tab(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,32 +59,6 @@ val BrowserState.inProgressMediaTab: TabSessionState?
|
||||
.filter { it.hasMediaPlayed() }
|
||||
.maxByOrNull { it.lastMediaAccessState.lastMediaAccess }
|
||||
|
||||
/**
|
||||
* Get the most recently accessed [TabGroup].
|
||||
* Result will be `null` if the currently open normal tabs are not part of a search group.
|
||||
*/
|
||||
val BrowserState.lastTabGroup: TabGroup?
|
||||
get() = tabPartitions[SEARCH_TERM_TAB_GROUPS]?.tabGroups
|
||||
?.lastOrNull { it.tabIds.size >= SEARCH_TERM_TAB_GROUPS_MIN_SIZE }
|
||||
|
||||
/**
|
||||
* Get the most recent search term group.
|
||||
*/
|
||||
val BrowserState.lastSearchGroup: RecentTab.SearchGroup?
|
||||
get() {
|
||||
val tabGroup = lastTabGroup ?: return null
|
||||
val firstTabId = tabGroup.tabIds.firstOrNull() ?: return null
|
||||
val firstTab = findTab(firstTabId) ?: return null
|
||||
|
||||
return RecentTab.SearchGroup(
|
||||
tabGroup.id,
|
||||
firstTabId,
|
||||
firstTab.content.url,
|
||||
firstTab.content.thumbnail,
|
||||
tabGroup.tabIds.size
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* List of all inactive tabs based on [maxActiveTime].
|
||||
* The user may have disabled the feature so for user interactions consider using the [actualInactiveTabs] method
|
||||
|
@ -8,7 +8,7 @@ import androidx.annotation.VisibleForTesting
|
||||
import org.mozilla.fenix.home.recenttabs.RecentTab
|
||||
|
||||
/**
|
||||
* Removes a [RecentTab.Tab] from a list of [RecentTab]. [RecentTab.SearchGroup]s will not be filtered.
|
||||
* Removes a [RecentTab.Tab] from a list of [RecentTab].
|
||||
*
|
||||
* @param tab [RecentTab] to remove from the list
|
||||
*/
|
||||
|
@ -7,7 +7,6 @@ package org.mozilla.fenix.home.recenttabs
|
||||
import android.graphics.Bitmap
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.map
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
@ -29,8 +28,7 @@ class RecentTabsListFeature(
|
||||
) : AbstractBinding<BrowserState>(browserStore) {
|
||||
|
||||
override suspend fun onState(flow: Flow<BrowserState>) {
|
||||
// Listen for changes regarding the currently selected tab, in progress media tab
|
||||
// and search term groups.
|
||||
// Listen for changes regarding the currently selected tab and in progress media tab.
|
||||
flow
|
||||
.map { it.asRecentTabs() }
|
||||
.ifChanged()
|
||||
|
@ -10,7 +10,7 @@ import androidx.navigation.NavController
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.feature.tabs.TabsUseCases.SelectTabUseCase
|
||||
import mozilla.components.service.glean.private.NoExtras
|
||||
import org.mozilla.fenix.GleanMetrics.SearchTerms
|
||||
import org.mozilla.fenix.GleanMetrics.RecentTabs
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.AppStore
|
||||
import org.mozilla.fenix.components.appstate.AppAction
|
||||
@ -18,7 +18,6 @@ import org.mozilla.fenix.ext.inProgressMediaTab
|
||||
import org.mozilla.fenix.home.HomeFragmentDirections
|
||||
import org.mozilla.fenix.home.recenttabs.RecentTab
|
||||
import org.mozilla.fenix.home.recenttabs.interactor.RecentTabInteractor
|
||||
import org.mozilla.fenix.GleanMetrics.RecentTabs as RecentTabs
|
||||
|
||||
/**
|
||||
* An interface that handles the view manipulation of the recent tabs in the Home screen.
|
||||
@ -30,11 +29,6 @@ interface RecentTabController {
|
||||
*/
|
||||
fun handleRecentTabClicked(tabId: String)
|
||||
|
||||
/**
|
||||
* @see [RecentTabInteractor.onRecentSearchGroupClicked]
|
||||
*/
|
||||
fun handleRecentSearchGroupClicked(tabId: String)
|
||||
|
||||
/**
|
||||
* @see [RecentTabInteractor.onRecentTabShowAllClicked]
|
||||
*/
|
||||
@ -76,15 +70,6 @@ class DefaultRecentTabsController(
|
||||
navController.navigate(HomeFragmentDirections.actionGlobalTabsTrayFragment())
|
||||
}
|
||||
|
||||
override fun handleRecentSearchGroupClicked(tabId: String) {
|
||||
SearchTerms.jumpBackInGroupTapped.record(NoExtras())
|
||||
navController.navigate(
|
||||
HomeFragmentDirections.actionGlobalTabsTrayFragment(
|
||||
focusGroupTabId = tabId
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun handleRecentTabRemoved(tab: RecentTab.Tab) {
|
||||
appStore.dispatch(AppAction.RemoveRecentTab(tab))
|
||||
}
|
||||
|
@ -17,13 +17,6 @@ interface RecentTabInteractor {
|
||||
*/
|
||||
fun onRecentTabClicked(tabId: String)
|
||||
|
||||
/**
|
||||
* Opens the tabs tray and scroll to the search group. Called when a user clicks on a search group.
|
||||
*
|
||||
* @param tabId The ID of the tab to open.
|
||||
*/
|
||||
fun onRecentSearchGroupClicked(tabId: String)
|
||||
|
||||
/**
|
||||
* Show the tabs tray. Called when a user clicks on the "Show all" button besides the recent
|
||||
* tabs.
|
||||
|
@ -58,7 +58,6 @@ class RecentTabViewHolder(
|
||||
RecentTabs(
|
||||
recentTabs = recentTabs.value ?: emptyList(),
|
||||
onRecentTabClick = { recentTabInteractor.onRecentTabClicked(it) },
|
||||
onRecentSearchGroupClick = { recentTabInteractor.onRecentSearchGroupClicked(it) },
|
||||
menuItems = listOf(
|
||||
RecentTabMenuItem(
|
||||
title = stringResource(id = R.string.recent_tab_menu_item_remove),
|
||||
|
@ -10,7 +10,6 @@ import android.graphics.Bitmap
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@ -29,7 +28,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.DropdownMenu
|
||||
import androidx.compose.material.DropdownMenuItem
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
@ -44,8 +42,6 @@ import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@ -53,7 +49,6 @@ import mozilla.components.browser.icons.compose.Loader
|
||||
import mozilla.components.browser.icons.compose.Placeholder
|
||||
import mozilla.components.browser.icons.compose.WithIcon
|
||||
import mozilla.components.ui.colors.PhotonColors
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.components
|
||||
import org.mozilla.fenix.compose.Image
|
||||
import org.mozilla.fenix.compose.ThumbnailCard
|
||||
@ -66,14 +61,12 @@ import org.mozilla.fenix.theme.FirefoxTheme
|
||||
* @param recentTabs List of [RecentTab] to display.
|
||||
* @param menuItems List of [RecentTabMenuItem] shown long clicking a [RecentTab].
|
||||
* @param onRecentTabClick Invoked when the user clicks on a recent tab.
|
||||
* @param onRecentSearchGroupClick Invoked when the user clicks on a recent search group.
|
||||
*/
|
||||
@Composable
|
||||
fun RecentTabs(
|
||||
recentTabs: List<RecentTab>,
|
||||
menuItems: List<RecentTabMenuItem>,
|
||||
onRecentTabClick: (String) -> Unit = {},
|
||||
onRecentSearchGroupClick: (String) -> Unit = {},
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
@ -88,16 +81,7 @@ fun RecentTabs(
|
||||
onRecentTabClick = onRecentTabClick
|
||||
)
|
||||
}
|
||||
is RecentTab.SearchGroup -> {
|
||||
if (components.settings.searchTermTabGroupsAreEnabled) {
|
||||
RecentSearchGroupItem(
|
||||
searchTerm = tab.searchTerm,
|
||||
tabId = tab.tabId,
|
||||
count = tab.count,
|
||||
onSearchGroupClick = onRecentSearchGroupClick
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,81 +169,6 @@ private fun RecentTabItem(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A recent search group item.
|
||||
*
|
||||
* @param searchTerm The search term for the group.
|
||||
* @param tabId The id of the last accessed tab in the group.
|
||||
* @param count Count of how many tabs belongs to the group.
|
||||
* @param onSearchGroupClick Invoked when the user clicks on a group.
|
||||
*/
|
||||
@Composable
|
||||
private fun RecentSearchGroupItem(
|
||||
searchTerm: String,
|
||||
tabId: String,
|
||||
count: Int,
|
||||
onSearchGroupClick: (String) -> Unit = {}
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(112.dp)
|
||||
.clickable { onSearchGroupClick(tabId) },
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
backgroundColor = FirefoxTheme.colors.layer2,
|
||||
elevation = 6.dp
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_search_group_thumbnail),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(108.dp, 80.dp),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
alignment = Alignment.Center
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.recent_tabs_search_term, searchTerm),
|
||||
color = FirefoxTheme.colors.textPrimary,
|
||||
fontSize = 14.sp,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 2,
|
||||
)
|
||||
|
||||
Row {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_all_tabs),
|
||||
modifier = Modifier.size(18.dp),
|
||||
contentDescription = null,
|
||||
tint = when (isSystemInDarkTheme()) {
|
||||
true -> FirefoxTheme.colors.textPrimary
|
||||
false -> FirefoxTheme.colors.textSecondary
|
||||
}
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.recent_tabs_search_term_count_2, count),
|
||||
color = FirefoxTheme.colors.textSecondary,
|
||||
fontSize = 12.sp,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A recent tab image.
|
||||
*
|
||||
|
@ -372,10 +372,6 @@ class SessionControlInteractor(
|
||||
recentTabController.handleRecentTabClicked(tabId)
|
||||
}
|
||||
|
||||
override fun onRecentSearchGroupClicked(tabId: String) {
|
||||
recentTabController.handleRecentSearchGroupClicked(tabId)
|
||||
}
|
||||
|
||||
override fun onRecentTabShowAllClicked() {
|
||||
recentTabController.handleRecentTabShowAllClicked()
|
||||
}
|
||||
|
@ -1,60 +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
|
||||
|
||||
import mozilla.components.browser.state.action.BrowserAction
|
||||
import mozilla.components.browser.state.action.HistoryMetadataAction
|
||||
import mozilla.components.browser.state.action.TabGroupAction
|
||||
import mozilla.components.browser.state.action.TabListAction
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.getGroupByName
|
||||
import mozilla.components.lib.state.Middleware
|
||||
import mozilla.components.lib.state.MiddlewareContext
|
||||
|
||||
const val SEARCH_TERM_TAB_GROUPS = "searchTermTabGroups"
|
||||
const val SEARCH_TERM_TAB_GROUPS_MIN_SIZE = 2
|
||||
|
||||
/**
|
||||
* This [Middleware] manages tab groups for search terms.
|
||||
*/
|
||||
class SearchTermTabGroupMiddleware : Middleware<BrowserState, BrowserAction> {
|
||||
|
||||
override fun invoke(
|
||||
context: MiddlewareContext<BrowserState, BrowserAction>,
|
||||
next: (BrowserAction) -> Unit,
|
||||
action: BrowserAction
|
||||
) {
|
||||
|
||||
next(action)
|
||||
|
||||
when (action) {
|
||||
is HistoryMetadataAction.SetHistoryMetadataKeyAction -> {
|
||||
action.historyMetadataKey.searchTerm?.let { searchTerm ->
|
||||
context.dispatch(
|
||||
TabGroupAction.AddTabAction(SEARCH_TERM_TAB_GROUPS, searchTerm, action.tabId)
|
||||
)
|
||||
}
|
||||
}
|
||||
is HistoryMetadataAction.DisbandSearchGroupAction -> {
|
||||
val group = context.state.tabPartitions[SEARCH_TERM_TAB_GROUPS]?.getGroupByName(action.searchTerm)
|
||||
group?.let {
|
||||
context.dispatch(TabGroupAction.RemoveTabGroupAction(SEARCH_TERM_TAB_GROUPS, it.id))
|
||||
}
|
||||
}
|
||||
is TabListAction.RestoreAction -> {
|
||||
action.tabs.forEach { tab ->
|
||||
tab.state.historyMetadata?.searchTerm?.let { searchTerm ->
|
||||
context.dispatch(
|
||||
TabGroupAction.AddTabAction(SEARCH_TERM_TAB_GROUPS, searchTerm, tab.state.id)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -153,7 +153,6 @@ class TabsTrayFragment : AppCompatDialogFragment() {
|
||||
initialState = TabsTrayState(
|
||||
selectedPage = initialPage,
|
||||
mode = initialMode,
|
||||
focusGroupTabId = args.focusGroupTabId
|
||||
),
|
||||
middlewares = listOf(
|
||||
TabsTrayMiddleware()
|
||||
|
@ -19,10 +19,9 @@ import org.mozilla.fenix.tabstray.syncedtabs.SyncedTabsListItem
|
||||
* @property mode Whether the browser tab list is in multi-select mode or not with the set of
|
||||
* currently selected tabs.
|
||||
* @property inactiveTabs The list of tabs are considered inactive.
|
||||
* @property normalTabs The list of normal tabs that do not fall under [inactiveTabs] or search term groups.
|
||||
* @property normalTabs The list of normal tabs that do not fall under [inactiveTabs].
|
||||
* @property privateTabs The list of tabs that are [ContentState.private].
|
||||
* @property syncing Whether the Synced Tabs feature should fetch the latest tabs from paired devices.
|
||||
* @property focusGroupTabId The search group tab id to focus. Defaults to null.
|
||||
*/
|
||||
data class TabsTrayState(
|
||||
val selectedPage: Page = Page.NormalTabs,
|
||||
@ -32,7 +31,6 @@ data class TabsTrayState(
|
||||
val privateTabs: List<TabSessionState> = emptyList(),
|
||||
val syncedTabs: List<SyncedTabsListItem> = emptyList(),
|
||||
val syncing: Boolean = false,
|
||||
val focusGroupTabId: String? = null
|
||||
) : State {
|
||||
|
||||
/**
|
||||
@ -130,11 +128,6 @@ sealed class TabsTrayAction : Action {
|
||||
*/
|
||||
object SyncCompleted : TabsTrayAction()
|
||||
|
||||
/**
|
||||
* Removes the [TabsTrayState.focusGroupTabId] of the [TabsTrayState].
|
||||
*/
|
||||
object ConsumeFocusGroupTabId : TabsTrayAction()
|
||||
|
||||
/**
|
||||
* Updates the list of tabs in [TabsTrayState.inactiveTabs].
|
||||
*/
|
||||
@ -184,8 +177,6 @@ internal object TabsTrayReducer {
|
||||
state.copy(syncing = true)
|
||||
is TabsTrayAction.SyncCompleted ->
|
||||
state.copy(syncing = false)
|
||||
is TabsTrayAction.ConsumeFocusGroupTabId ->
|
||||
state.copy(focusGroupTabId = null)
|
||||
is TabsTrayAction.UpdateInactiveTabs ->
|
||||
state.copy(inactiveTabs = action.tabs)
|
||||
is TabsTrayAction.UpdateNormalTabs ->
|
||||
|
@ -27,7 +27,6 @@ import org.mozilla.fenix.tabstray.TabsTrayInteractor
|
||||
import org.mozilla.fenix.tabstray.TabsTrayStore
|
||||
import org.mozilla.fenix.tabstray.ext.browserAdapter
|
||||
import org.mozilla.fenix.tabstray.ext.defaultBrowserLayoutColumns
|
||||
import org.mozilla.fenix.tabstray.ext.getNormalTrayTabs
|
||||
import org.mozilla.fenix.tabstray.ext.inactiveTabsAdapter
|
||||
import org.mozilla.fenix.tabstray.ext.isNormalTabInactive
|
||||
import org.mozilla.fenix.tabstray.ext.observeFirstInsert
|
||||
@ -79,7 +78,6 @@ class NormalBrowserPageViewHolder(
|
||||
layoutManager: RecyclerView.LayoutManager
|
||||
) {
|
||||
val concatAdapter = adapter as ConcatAdapter
|
||||
val browserAdapter = concatAdapter.browserAdapter
|
||||
val inactiveTabAdapter = concatAdapter.inactiveTabsAdapter
|
||||
val inactiveTabsAreEnabled = containerView.context.settings().inactiveTabsAreEnabled
|
||||
|
||||
@ -87,7 +85,6 @@ class NormalBrowserPageViewHolder(
|
||||
// It's safe to read the state directly (i.e. won't cause bugs because of the store actions
|
||||
// processed on a separate thread) instead of observing it because this value is only set during
|
||||
// the initialState of the TabsTrayStore being created.
|
||||
val focusGroupTabId = tabsTrayStore.state.focusGroupTabId
|
||||
|
||||
// Update tabs into the inactive adapter.
|
||||
if (inactiveTabsAreEnabled && selectedTab.isNormalTabInactive(maxActiveTime)) {
|
||||
@ -106,23 +103,6 @@ class NormalBrowserPageViewHolder(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (focusGroupTabId.isNullOrEmpty()) {
|
||||
// Updates tabs into the normal browser tabs adapter.
|
||||
browserAdapter.observeFirstInsert {
|
||||
val activeTabsList = browserStore.state.getNormalTrayTabs(inactiveTabsAreEnabled)
|
||||
activeTabsList.forEachIndexed { tabIndex, trayTab ->
|
||||
if (trayTab.id == selectedTab.id) {
|
||||
// Index is based on tabs above (inactive) with our calculated index.
|
||||
val indexToScrollTo = inactiveTabAdapter.itemCount + tabIndex
|
||||
|
||||
containerView.post { layoutManager.scrollToPosition(indexToScrollTo) }
|
||||
|
||||
return@observeFirstInsert
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary hack until https://github.com/mozilla-mobile/fenix/issues/21901 where the
|
||||
|
@ -161,11 +161,6 @@
|
||||
android:name="enterMultiselect"
|
||||
android:defaultValue="false"
|
||||
app:argType="boolean" />
|
||||
<argument
|
||||
android:name="focusGroupTabId"
|
||||
app:nullable="true"
|
||||
android:defaultValue="@null"
|
||||
app:argType="string" />
|
||||
<argument
|
||||
android:name="page"
|
||||
android:defaultValue="NormalTabs"
|
||||
|
@ -147,8 +147,7 @@ class AppStoreTest {
|
||||
// Add 2 RecentTabs to the AppStore
|
||||
// A new SearchGroup already shown in history should hide the HistoryGroup.
|
||||
val recentTab1: RecentTab.Tab = mockk()
|
||||
val recentTab2 = RecentTab.SearchGroup(group2.title, "tabId", "url", null, 2)
|
||||
val recentTabs: List<RecentTab> = listOf(recentTab1, recentTab2)
|
||||
val recentTabs: List<RecentTab> = listOf(recentTab1)
|
||||
appStore.dispatch(AppAction.RecentTabsChange(recentTabs)).join()
|
||||
|
||||
assertEquals(recentTabs, appStore.state.recentTabs)
|
||||
@ -208,20 +207,6 @@ class AppStoreTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test disbanding search group in AppStore`() = runTest {
|
||||
val g1 = RecentHistoryGroup(title = "test One")
|
||||
val g2 = RecentHistoryGroup(title = "test two")
|
||||
val h1 = RecentHistoryHighlight(title = "highlight One", url = "url1")
|
||||
val h2 = RecentHistoryHighlight(title = "highlight two", url = "url2")
|
||||
val recentHistory: List<RecentlyVisitedItem> = listOf(g1, g2, h1, h2)
|
||||
appStore.dispatch(AppAction.RecentHistoryChange(recentHistory)).join()
|
||||
assertEquals(recentHistory, appStore.state.recentHistory)
|
||||
|
||||
appStore.dispatch(AppAction.DisbandSearchGroupAction("Test one")).join()
|
||||
assertEquals(listOf(g2, h1, h2), appStore.state.recentHistory)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test changing hiding collections placeholder`() = runTest {
|
||||
assertTrue(appStore.state.showCollectionPlaceholder)
|
||||
@ -259,7 +244,7 @@ class AppStoreTest {
|
||||
val recentGroup = RecentTab.SearchGroup("testSearchTerm", "id", "url", null, 3)
|
||||
val collections: List<TabCollection> = listOf(mockk())
|
||||
val topSites: List<TopSite> = listOf(mockk(), mockk())
|
||||
val recentTabs: List<RecentTab> = listOf(mockk(), recentGroup, mockk())
|
||||
val recentTabs: List<RecentTab> = listOf(mockk(), mockk())
|
||||
val recentBookmarks: List<RecentBookmark> = listOf(mockk(), mockk())
|
||||
val group1 = RecentHistoryGroup(title = "test One")
|
||||
val group2 = RecentHistoryGroup(title = recentGroup.searchTerm.lowercase())
|
||||
|
@ -21,7 +21,6 @@ import org.mozilla.fenix.home.pocket.POCKET_STORIES_DEFAULT_CATEGORY_NAME
|
||||
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory
|
||||
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesSelectedCategory
|
||||
import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTabState
|
||||
import org.mozilla.fenix.home.recenttabs.RecentTab
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.random.Random
|
||||
@ -498,24 +497,6 @@ class AppStateTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN recentTabs contains a SearchGroup WHEN recentSearchGroup is called THEN return the group`() {
|
||||
val searchGroup: RecentTab.SearchGroup = mockk()
|
||||
val normalTab: RecentTab.Tab = mockk()
|
||||
val state = AppState(recentTabs = listOf(normalTab, searchGroup))
|
||||
|
||||
assertEquals(searchGroup, state.recentSearchGroup)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN recentTabs does not contains SearchGroup WHEN recentSearchGroup is called THEN return null`() {
|
||||
val normalTab1: RecentTab.Tab = mockk()
|
||||
val normalTab2: RecentTab.Tab = mockk()
|
||||
val state = AppState(recentTabs = listOf(normalTab1, normalTab2))
|
||||
|
||||
assertNull(state.recentSearchGroup)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN recent tabs disabled in settings WHEN checking to show tabs THEN section should not be shown`() {
|
||||
val settings = mockk<Settings> {
|
||||
|
@ -8,8 +8,6 @@ import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.LastMediaAccessState
|
||||
import mozilla.components.browser.state.state.TabGroup
|
||||
import mozilla.components.browser.state.state.TabPartition
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import mozilla.components.concept.storage.HistoryMetadataKey
|
||||
import org.junit.Assert.assertEquals
|
||||
@ -17,7 +15,6 @@ import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.home.recenttabs.RecentTab
|
||||
import org.mozilla.fenix.tabstray.SEARCH_TERM_TAB_GROUPS
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
class BrowserStateTest {
|
||||
@ -160,74 +157,6 @@ class BrowserStateTest {
|
||||
assertEquals(searchGroupTab, (result[0] as RecentTab.Tab).state)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN only normal tabs from a search group are open WHEN recentTabs is called THEN return only the tab group`() {
|
||||
val searchGroupTab1 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "1",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "Test",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
val searchGroupTab2 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "2",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "Test",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
val tabGroup = listOf(TabGroup("Test", "", listOf(searchGroupTab1.id, searchGroupTab2.id)))
|
||||
val browserState = BrowserState(
|
||||
tabs = listOf(searchGroupTab1, searchGroupTab2),
|
||||
tabPartitions = mapOf(Pair(SEARCH_TERM_TAB_GROUPS, TabPartition(SEARCH_TERM_TAB_GROUPS, tabGroup))),
|
||||
selectedTabId = searchGroupTab1.id
|
||||
)
|
||||
|
||||
val result = browserState.asRecentTabs()
|
||||
|
||||
assertEquals(1, result.size)
|
||||
assert(result[0] is RecentTab.SearchGroup)
|
||||
assertEquals(searchGroupTab1.historyMetadata?.searchTerm, (result[0] as RecentTab.SearchGroup).searchTerm)
|
||||
assertEquals(searchGroupTab1.id, (result[0] as RecentTab.SearchGroup).tabId)
|
||||
assertEquals(searchGroupTab1.content.url, (result[0] as RecentTab.SearchGroup).url)
|
||||
assertEquals(searchGroupTab1.content.thumbnail, (result[0] as RecentTab.SearchGroup).thumbnail)
|
||||
assertEquals(2, (result[0] as RecentTab.SearchGroup).count)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN tabs with different search terms are opened WHEN recentTabs is called THEN return the most recent tab and tab group`() {
|
||||
val searchGroupTab = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "1",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "Test",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
val otherTab = createTab(url = "https://www.mozilla.org/firefox", id = "2")
|
||||
val browserState = BrowserState(
|
||||
tabs = listOf(searchGroupTab, otherTab, searchGroupTab),
|
||||
tabPartitions = mapOf(Pair(SEARCH_TERM_TAB_GROUPS, TabPartition(SEARCH_TERM_TAB_GROUPS, listOf(TabGroup("Test", "", listOf("1", "3")))))),
|
||||
selectedTabId = searchGroupTab.id
|
||||
)
|
||||
|
||||
val result = browserState.asRecentTabs()
|
||||
|
||||
assertEquals(2, result.size)
|
||||
assertEquals(otherTab, (result[0] as RecentTab.Tab).state)
|
||||
assert(result[1] is RecentTab.SearchGroup)
|
||||
assertEquals("Test", (result[1] as RecentTab.SearchGroup).searchTerm)
|
||||
assertEquals(searchGroupTab.id, (result[1] as RecentTab.SearchGroup).tabId)
|
||||
assertEquals(searchGroupTab.content.url, (result[1] as RecentTab.SearchGroup).url)
|
||||
assertEquals(searchGroupTab.content.thumbnail, (result[1] as RecentTab.SearchGroup).thumbnail)
|
||||
assertEquals(2, (result[1] as RecentTab.SearchGroup).count)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the selected tab is a normal tab and tab group with one tab exists WHEN asRecentTabs is called THEN return only the normal tab`() {
|
||||
val selectedTab = createTab(url = "url", id = "3")
|
||||
@ -260,46 +189,6 @@ class BrowserStateTest {
|
||||
assertEquals(selectedTab, (result[0] as RecentTab.Tab).state)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the selected tab is a normal tab and tab group with two tabs exists WHEN asRecentTabs is called THEN return a list of these tabs`() {
|
||||
val selectedTab = createTab(url = "url", id = "3")
|
||||
val searchGroupTab1 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "4",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "Test",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
val searchGroupTab2 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "5",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "Test",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
val tabGroup = listOf(TabGroup("Test", "", listOf(searchGroupTab1.id, searchGroupTab2.id)))
|
||||
val browserState = BrowserState(
|
||||
tabs = listOf(mockk(relaxed = true), selectedTab, searchGroupTab1, searchGroupTab1),
|
||||
tabPartitions = mapOf(Pair(SEARCH_TERM_TAB_GROUPS, TabPartition(SEARCH_TERM_TAB_GROUPS, tabGroup))),
|
||||
selectedTabId = selectedTab.id
|
||||
)
|
||||
|
||||
val result = browserState.asRecentTabs()
|
||||
|
||||
assertEquals(2, result.size)
|
||||
assertEquals(selectedTab, (result[0] as RecentTab.Tab).state)
|
||||
assert(result[1] is RecentTab.SearchGroup)
|
||||
assertEquals(searchGroupTab1.historyMetadata?.searchTerm, (result[1] as RecentTab.SearchGroup).searchTerm)
|
||||
assertEquals(searchGroupTab1.id, (result[1] as RecentTab.SearchGroup).tabId)
|
||||
assertEquals(searchGroupTab1.content.url, (result[1] as RecentTab.SearchGroup).url)
|
||||
assertEquals(searchGroupTab1.content.thumbnail, (result[1] as RecentTab.SearchGroup).thumbnail)
|
||||
assertEquals(2, (result[1] as RecentTab.SearchGroup).count)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN only private tabs and a private one selected WHEN lastOpenedNormalTab is called THEN return null`() {
|
||||
val selectedPrivateTab = createTab(url = "url", id = "1", private = true)
|
||||
@ -467,38 +356,4 @@ class BrowserStateTest {
|
||||
assertEquals(2, result.size)
|
||||
assertTrue(result.containsAll(listOf(normalTab1, normalTab3)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN tabs exist with search terms WHEN lastTabGroup is called THEN return the last accessed TabGroup`() {
|
||||
val tab1 = createTab(url = "url1", id = "id1", searchTerms = "test1", lastAccess = 10)
|
||||
val tab2 = createTab(url = "url2", id = "id2", searchTerms = "test1", lastAccess = 11)
|
||||
val tab3 = createTab(url = "url3", id = "id3", searchTerms = "test3", lastAccess = 100)
|
||||
val tab4 = createTab(url = "url4", id = "id4", searchTerms = "test3", lastAccess = 111)
|
||||
val tab5 = createTab(url = "url5", id = "id5", searchTerms = "test5", lastAccess = 1000)
|
||||
val tab6 = createTab(url = "url6", id = "id6", searchTerms = "test5", lastAccess = 1111)
|
||||
val tabGroup1 = TabGroup("test1", "", listOf(tab1.id, tab2.id))
|
||||
val tabGroup2 = TabGroup("test3", "", listOf(tab3.id, tab4.id))
|
||||
val tabGroup3 = TabGroup("test5", "", listOf(tab5.id, tab6.id))
|
||||
|
||||
val browserState = BrowserState(
|
||||
tabs = listOf(tab1, tab2, tab3, tab4, tab5, tab6),
|
||||
tabPartitions = mapOf(Pair(SEARCH_TERM_TAB_GROUPS, TabPartition(SEARCH_TERM_TAB_GROUPS, listOf(tabGroup1, tabGroup2, tabGroup3))))
|
||||
)
|
||||
val expected = TabGroup("test5", "", listOf(tab5.id, tab6.id))
|
||||
|
||||
val result = browserState.lastTabGroup
|
||||
|
||||
assertEquals(expected, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN no tabs exist with search terms WHEN lastTabGroup is called THEN return the last accessed TabGroup`() {
|
||||
val tab1 = createTab(url = "url1", id = "id1", lastAccess = 10)
|
||||
val tab2 = createTab(url = "url2", id = "id2", lastAccess = 11)
|
||||
val browserState = BrowserState(tabs = listOf(tab1, tab2))
|
||||
|
||||
val result = browserState.lastTabGroup
|
||||
|
||||
assertNull(result)
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +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.ext
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.home.recenttabs.RecentTab
|
||||
|
||||
class RecentTabsTest {
|
||||
@Test
|
||||
fun `Test filtering out tab`() {
|
||||
val filteredId = "id"
|
||||
val mockSessionState: TabSessionState = mockk()
|
||||
every { mockSessionState.id } returns filteredId
|
||||
val tab = RecentTab.Tab(mockSessionState)
|
||||
val searchGroup = RecentTab.SearchGroup(
|
||||
tabId = filteredId,
|
||||
searchTerm = "",
|
||||
url = "",
|
||||
thumbnail = null,
|
||||
count = 0
|
||||
)
|
||||
|
||||
val recentTabs = listOf(tab, searchGroup)
|
||||
val result = recentTabs.filterOutTab(tab)
|
||||
|
||||
assertEquals(listOf(searchGroup), result)
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
|
||||
package org.mozilla.fenix.home
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import mozilla.components.browser.state.action.ContentAction.UpdateIconAction
|
||||
@ -13,12 +12,9 @@ import mozilla.components.browser.state.action.MediaSessionAction
|
||||
import mozilla.components.browser.state.action.TabListAction
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.LastMediaAccessState
|
||||
import mozilla.components.browser.state.state.TabGroup
|
||||
import mozilla.components.browser.state.state.TabPartition
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.engine.mediasession.MediaSession
|
||||
import mozilla.components.concept.storage.HistoryMetadataKey
|
||||
import mozilla.components.feature.media.middleware.LastMediaAccessMiddleware
|
||||
import mozilla.components.support.test.ext.joinBlocking
|
||||
import mozilla.components.support.test.libstate.ext.waitUntilIdle
|
||||
@ -38,7 +34,6 @@ import org.mozilla.fenix.components.appstate.AppAction
|
||||
import org.mozilla.fenix.components.appstate.AppState
|
||||
import org.mozilla.fenix.home.recenttabs.RecentTab
|
||||
import org.mozilla.fenix.home.recenttabs.RecentTabsListFeature
|
||||
import org.mozilla.fenix.tabstray.SEARCH_TERM_TAB_GROUPS
|
||||
|
||||
class RecentTabsListFeatureTest {
|
||||
|
||||
@ -388,245 +383,4 @@ class RecentTabsListFeatureTest {
|
||||
assertTrue(appStore.state.recentTabs[0] is RecentTab.Tab)
|
||||
assertEquals(selectedTab, (appStore.state.recentTabs[0] as RecentTab.Tab).state)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN only tabs from a search group WHEN the feature starts THEN dispatch the selected tab group as a recent tab list`() {
|
||||
val tab1 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "1",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "test search term",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
|
||||
val tab2 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "2",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "test search term",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
val tabs = listOf(tab1, tab2)
|
||||
val tabGroup = TabGroup("Test search term", "", listOf(tab1.id, tab2.id))
|
||||
val browserStore = BrowserStore(
|
||||
BrowserState(
|
||||
tabs = tabs,
|
||||
tabPartitions = mapOf(Pair(SEARCH_TERM_TAB_GROUPS, TabPartition(SEARCH_TERM_TAB_GROUPS, listOf(tabGroup)))),
|
||||
selectedTabId = "1"
|
||||
)
|
||||
)
|
||||
val feature = RecentTabsListFeature(
|
||||
browserStore = browserStore,
|
||||
appStore = appStore
|
||||
)
|
||||
|
||||
feature.start()
|
||||
|
||||
appStore.waitUntilIdle()
|
||||
|
||||
assertEquals(1, appStore.state.recentTabs.size)
|
||||
val searchGroup = (appStore.state.recentTabs[0] as RecentTab.SearchGroup)
|
||||
assertEquals(searchGroup.searchTerm, "Test search term")
|
||||
assertEquals(searchGroup.tabId, "1")
|
||||
assertEquals(searchGroup.url, "https://www.mozilla.org")
|
||||
assertEquals(searchGroup.thumbnail, null)
|
||||
assertEquals(searchGroup.count, 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN tabs with different search terms are opened WHEN the feature starts THEN dispatch the last active tab and last active search group as recent tabs list`() {
|
||||
val tab1 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "1",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "Test search term",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
|
||||
val tab2 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "2",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "Test search term",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
val tab3 = createTab(url = "https://www.mozilla.org/firefox", id = "3")
|
||||
val tabs = listOf(tab1, tab2, tab3)
|
||||
val tabGroup = TabGroup("Test search term", "", listOf(tab1.id, tab2.id))
|
||||
val browserStore = BrowserStore(
|
||||
BrowserState(
|
||||
tabs = tabs,
|
||||
tabPartitions = mapOf(Pair(SEARCH_TERM_TAB_GROUPS, TabPartition(SEARCH_TERM_TAB_GROUPS, listOf(tabGroup)))),
|
||||
selectedTabId = "1"
|
||||
)
|
||||
)
|
||||
val feature = RecentTabsListFeature(
|
||||
browserStore = browserStore,
|
||||
appStore = appStore
|
||||
)
|
||||
|
||||
feature.start()
|
||||
|
||||
appStore.waitUntilIdle()
|
||||
|
||||
assertEquals(2, appStore.state.recentTabs.size)
|
||||
assertTrue(appStore.state.recentTabs[0] is RecentTab.Tab)
|
||||
assertEquals(tab3, (appStore.state.recentTabs[0] as RecentTab.Tab).state)
|
||||
val searchGroup = (appStore.state.recentTabs[1] as RecentTab.SearchGroup)
|
||||
assertEquals(searchGroup.searchTerm, "Test search term")
|
||||
assertEquals(searchGroup.tabId, "1")
|
||||
assertEquals(searchGroup.url, "https://www.mozilla.org")
|
||||
assertEquals(searchGroup.thumbnail, null)
|
||||
assertEquals(searchGroup.count, 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN a tab group with one tab and a selected tab WHEN the feature starts THEN dispatch selected tab as a recent tab list`() {
|
||||
val tab1 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "1"
|
||||
)
|
||||
val tab2 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "2",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "test search term",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
val tabs = listOf(tab1, tab2)
|
||||
val browserStore = BrowserStore(
|
||||
BrowserState(
|
||||
tabs = tabs,
|
||||
selectedTabId = "1"
|
||||
)
|
||||
)
|
||||
val feature = RecentTabsListFeature(
|
||||
browserStore = browserStore,
|
||||
appStore = appStore
|
||||
)
|
||||
|
||||
feature.start()
|
||||
|
||||
appStore.waitUntilIdle()
|
||||
|
||||
assertEquals(1, appStore.state.recentTabs.size)
|
||||
assertTrue(appStore.state.recentTabs[0] is RecentTab.Tab)
|
||||
assertEquals(tab1, (appStore.state.recentTabs[0] as RecentTab.Tab).state)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN a tab group with two tabs and a selected tab WHEN the feature starts THEN dispatch both the selected tab and the selected tab group as a recent tab list`() {
|
||||
val tab1 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "1"
|
||||
)
|
||||
val tab2 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "2",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "test search term",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
|
||||
val tab3 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "3",
|
||||
historyMetadata = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "test search term",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
)
|
||||
val tabs = listOf(tab1, tab2, tab3)
|
||||
val tabGroup = TabGroup("test search term", "", listOf(tab2.id, tab3.id))
|
||||
val browserStore = BrowserStore(
|
||||
BrowserState(
|
||||
tabs = tabs,
|
||||
tabPartitions = mapOf(Pair(SEARCH_TERM_TAB_GROUPS, TabPartition(SEARCH_TERM_TAB_GROUPS, listOf(tabGroup)))),
|
||||
selectedTabId = "1"
|
||||
)
|
||||
)
|
||||
val feature = RecentTabsListFeature(
|
||||
browserStore = browserStore,
|
||||
appStore = appStore
|
||||
)
|
||||
|
||||
feature.start()
|
||||
|
||||
appStore.waitUntilIdle()
|
||||
|
||||
assertEquals(2, appStore.state.recentTabs.size)
|
||||
assertTrue(appStore.state.recentTabs[0] is RecentTab.Tab)
|
||||
assertEquals(tab1, (appStore.state.recentTabs[0] as RecentTab.Tab).state)
|
||||
val searchGroup = (appStore.state.recentTabs[1] as RecentTab.SearchGroup)
|
||||
assertEquals(searchGroup.searchTerm, "test search term")
|
||||
assertEquals(searchGroup.tabId, "2")
|
||||
assertEquals(searchGroup.url, "https://www.mozilla.org")
|
||||
assertEquals(searchGroup.thumbnail, null)
|
||||
assertEquals(searchGroup.count, 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN a valid inProgressMediaTabId, selected tab and tab group exists WHEN the feature starts THEN dispatch all as as a recent tabs list`() {
|
||||
val mediaTab = createTab(
|
||||
url = "https://mozilla.com", id = "42",
|
||||
lastMediaAccessState = LastMediaAccessState("https://mozilla.com", 123)
|
||||
)
|
||||
val selectedTab = createTab("https://mozilla.com", id = "43")
|
||||
val historyMetadataKey = HistoryMetadataKey(
|
||||
url = "https://www.mozilla.org",
|
||||
searchTerm = "test search term",
|
||||
referrerUrl = "https://www.mozilla.org"
|
||||
)
|
||||
val thumbnail = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
|
||||
val searchTermTab1 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "44",
|
||||
thumbnail = thumbnail,
|
||||
historyMetadata = historyMetadataKey
|
||||
)
|
||||
val searchTermTab2 = createTab(
|
||||
url = "https://www.mozilla.org",
|
||||
id = "45",
|
||||
thumbnail = thumbnail,
|
||||
historyMetadata = historyMetadataKey
|
||||
)
|
||||
val searchTermTabGroup = TabGroup(historyMetadataKey.searchTerm!!, "", listOf(searchTermTab1.id, searchTermTab2.id))
|
||||
val browserStore = BrowserStore(
|
||||
BrowserState(
|
||||
tabs = listOf(mediaTab, selectedTab, searchTermTab1, searchTermTab2),
|
||||
tabPartitions = mapOf(Pair(SEARCH_TERM_TAB_GROUPS, TabPartition(SEARCH_TERM_TAB_GROUPS, listOf(searchTermTabGroup)))),
|
||||
selectedTabId = "43"
|
||||
)
|
||||
)
|
||||
val feature = RecentTabsListFeature(
|
||||
browserStore = browserStore,
|
||||
appStore = appStore
|
||||
)
|
||||
|
||||
feature.start()
|
||||
appStore.waitUntilIdle()
|
||||
|
||||
assertEquals(2, appStore.state.recentTabs.size)
|
||||
assertTrue(appStore.state.recentTabs[0] is RecentTab.Tab)
|
||||
assertEquals(selectedTab, (appStore.state.recentTabs[0] as RecentTab.Tab).state)
|
||||
val searchGroup = (appStore.state.recentTabs[1] as RecentTab.SearchGroup)
|
||||
assertEquals(searchGroup.searchTerm, "test search term")
|
||||
assertEquals(searchGroup.tabId, "44")
|
||||
assertEquals(searchGroup.url, "https://www.mozilla.org")
|
||||
assertEquals(searchGroup.thumbnail, thumbnail)
|
||||
assertEquals(searchGroup.count, 2)
|
||||
}
|
||||
}
|
||||
|
@ -162,13 +162,6 @@ class SessionControlInteractorTest {
|
||||
verify { recentTabController.handleRecentTabClicked(tabId) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onRecentSearchGroupClicked() {
|
||||
val tabId = "tabId"
|
||||
interactor.onRecentSearchGroupClicked(tabId)
|
||||
verify { recentTabController.handleRecentSearchGroupClicked(tabId) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onRecentTabShowAllClicked() {
|
||||
interactor.onRecentTabShowAllClicked()
|
||||
|
@ -28,7 +28,6 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.GleanMetrics.RecentTabs
|
||||
import org.mozilla.fenix.GleanMetrics.SearchTerms
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.AppStore
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
@ -163,21 +162,4 @@ class RecentTabControllerTest {
|
||||
|
||||
assertNotNull(RecentTabs.showAllClicked.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN handleRecentSearchGroupClicked is called THEN navigate to the tabsTrayFragment and record the correct metric`() {
|
||||
assertNull(SearchTerms.jumpBackInGroupTapped.testGetValue())
|
||||
|
||||
controller.handleRecentSearchGroupClicked("1")
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
match<NavDirections> {
|
||||
it.actionId == R.id.action_global_tabsTrayFragment &&
|
||||
it.arguments["focusGroupTabId"] == "1"
|
||||
}
|
||||
)
|
||||
}
|
||||
assertNotNull(SearchTerms.jumpBackInGroupTapped.testGetValue())
|
||||
}
|
||||
}
|
||||
|
@ -1,104 +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
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import mozilla.components.browser.state.action.BrowserAction
|
||||
import mozilla.components.browser.state.action.HistoryMetadataAction
|
||||
import mozilla.components.browser.state.action.TabGroupAction
|
||||
import mozilla.components.browser.state.action.TabListAction
|
||||
import mozilla.components.browser.state.engine.EngineMiddleware
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.TabGroup
|
||||
import mozilla.components.browser.state.state.TabPartition
|
||||
import mozilla.components.browser.state.state.recover.RecoverableTab
|
||||
import mozilla.components.browser.state.state.recover.TabState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.storage.HistoryMetadataKey
|
||||
import mozilla.components.lib.state.MiddlewareContext
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class SearchTermTabGroupMiddlewareTest {
|
||||
|
||||
private lateinit var store: BrowserStore
|
||||
private lateinit var searchTermTabGroupMiddleware: SearchTermTabGroupMiddleware
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
searchTermTabGroupMiddleware = SearchTermTabGroupMiddleware()
|
||||
store = BrowserStore(
|
||||
middleware = listOf(searchTermTabGroupMiddleware) + EngineMiddleware.create(engine = mockk()),
|
||||
initialState = BrowserState()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN invoking with set history metadata key action THEN dispatch add tab action`() {
|
||||
val context: MiddlewareContext<BrowserState, BrowserAction> = mockk()
|
||||
val next: (BrowserAction) -> Unit = {}
|
||||
|
||||
every { context.dispatch(any()) } returns Unit
|
||||
|
||||
searchTermTabGroupMiddleware.invoke(
|
||||
context,
|
||||
next,
|
||||
HistoryMetadataAction.SetHistoryMetadataKeyAction("tabId", HistoryMetadataKey("url", "search term", "url"))
|
||||
)
|
||||
|
||||
verify { context.dispatch(TabGroupAction.AddTabAction(SEARCH_TERM_TAB_GROUPS, "search term", "tabId")) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN invoking with disband search group action THEN dispatch remove tab group action`() {
|
||||
val context: MiddlewareContext<BrowserState, BrowserAction> = mockk()
|
||||
val next: (BrowserAction) -> Unit = {}
|
||||
val state: BrowserState = mockk()
|
||||
val tabPartitions =
|
||||
mapOf(Pair(SEARCH_TERM_TAB_GROUPS, TabPartition(SEARCH_TERM_TAB_GROUPS, listOf(TabGroup("testId", "search term", listOf("tab1"))))))
|
||||
|
||||
every { context.dispatch(any()) } returns Unit
|
||||
every { context.state } returns state
|
||||
every { state.tabPartitions } returns tabPartitions
|
||||
|
||||
searchTermTabGroupMiddleware.invoke(
|
||||
context,
|
||||
next,
|
||||
HistoryMetadataAction.DisbandSearchGroupAction("search term")
|
||||
)
|
||||
|
||||
verify { context.dispatch(TabGroupAction.RemoveTabGroupAction(SEARCH_TERM_TAB_GROUPS, "testId")) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN invoking with restore action THEN dispatch add tab action`() {
|
||||
val context: MiddlewareContext<BrowserState, BrowserAction> = mockk()
|
||||
val next: (BrowserAction) -> Unit = {}
|
||||
|
||||
every { context.dispatch(any()) } returns Unit
|
||||
|
||||
searchTermTabGroupMiddleware.invoke(
|
||||
context,
|
||||
next,
|
||||
TabListAction.RestoreAction(
|
||||
listOf(
|
||||
RecoverableTab(
|
||||
engineSessionState = null,
|
||||
state = TabState(
|
||||
id = "testId",
|
||||
url = "url",
|
||||
historyMetadata = HistoryMetadataKey("url", "search term", "url")
|
||||
)
|
||||
)
|
||||
),
|
||||
restoreLocation = TabListAction.RestoreAction.RestoreLocation.BEGINNING
|
||||
)
|
||||
)
|
||||
|
||||
verify { context.dispatch(TabGroupAction.AddTabAction(SEARCH_TERM_TAB_GROUPS, "search term", "testId")) }
|
||||
}
|
||||
}
|
@ -10,18 +10,6 @@ import org.junit.Test
|
||||
import org.mozilla.fenix.tabstray.syncedtabs.getFakeSyncedTabList
|
||||
|
||||
class TabsTrayStoreReducerTest {
|
||||
@Test
|
||||
fun `GIVEN focusGroupTabId WHEN ConsumeFocusGroupTabIdAction THEN focusGroupTabId must be consumed`() {
|
||||
val initialState = TabsTrayState(focusGroupTabId = "id")
|
||||
val expectedState = initialState.copy(focusGroupTabId = null)
|
||||
|
||||
val resultState = TabsTrayReducer.reduce(
|
||||
initialState,
|
||||
TabsTrayAction.ConsumeFocusGroupTabId
|
||||
)
|
||||
|
||||
assertEquals(expectedState, resultState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN UpdateInactiveTabs THEN inactive tabs are added`() {
|
||||
|
Loading…
Reference in New Issue
Block a user