mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-15 18:12:54 +00:00
For #23431 - Display the order of Contile Top Sites correctly
This commit is contained in:
parent
6c59fd424b
commit
37a0edceb6
@ -36,6 +36,7 @@ import mozilla.components.feature.addons.update.GlobalAddonDependencyProvider
|
|||||||
import mozilla.components.feature.autofill.AutofillUseCases
|
import mozilla.components.feature.autofill.AutofillUseCases
|
||||||
import mozilla.components.feature.search.ext.buildSearchUrl
|
import mozilla.components.feature.search.ext.buildSearchUrl
|
||||||
import mozilla.components.feature.search.ext.waitForSelectedOrDefaultSearchEngine
|
import mozilla.components.feature.search.ext.waitForSelectedOrDefaultSearchEngine
|
||||||
|
import mozilla.components.feature.top.sites.TopSitesProviderConfig
|
||||||
import mozilla.components.lib.crash.CrashReporter
|
import mozilla.components.lib.crash.CrashReporter
|
||||||
import mozilla.components.service.fxa.manager.SyncEnginesStorage
|
import mozilla.components.service.fxa.manager.SyncEnginesStorage
|
||||||
import mozilla.components.service.glean.Glean
|
import mozilla.components.service.glean.Glean
|
||||||
@ -82,6 +83,7 @@ import org.mozilla.fenix.session.VisibilityLifecycleCallback
|
|||||||
import org.mozilla.fenix.telemetry.TelemetryLifecycleObserver
|
import org.mozilla.fenix.telemetry.TelemetryLifecycleObserver
|
||||||
import org.mozilla.fenix.utils.BrowsersCache
|
import org.mozilla.fenix.utils.BrowsersCache
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -258,11 +260,14 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
|
|||||||
// we can prevent with this.
|
// we can prevent with this.
|
||||||
components.core.topSitesStorage.getTopSites(
|
components.core.topSitesStorage.getTopSites(
|
||||||
totalSites = components.settings.topSitesMaxLimit,
|
totalSites = components.settings.topSitesMaxLimit,
|
||||||
fetchProvidedTopSites = components.settings.showContileFeature,
|
|
||||||
frecencyConfig = if (components.settings.showTopFrecentSites)
|
frecencyConfig = if (components.settings.showTopFrecentSites)
|
||||||
FrecencyThresholdOption.SKIP_ONE_TIME_PAGES
|
FrecencyThresholdOption.SKIP_ONE_TIME_PAGES
|
||||||
else
|
else
|
||||||
null
|
null,
|
||||||
|
providerConfig = TopSitesProviderConfig(
|
||||||
|
showProviderTopSites = components.settings.showContileFeature,
|
||||||
|
maxThreshold = TOP_SITES_PROVIDER_MAX_THRESHOLD
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This service uses `historyStorage`, and so we can only touch it when we know
|
// This service uses `historyStorage`, and so we can only touch it when we know
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package org.mozilla.fenix.ext
|
package org.mozilla.fenix.ext
|
||||||
|
|
||||||
import mozilla.components.feature.top.sites.TopSite
|
import mozilla.components.feature.top.sites.TopSite
|
||||||
|
import org.mozilla.fenix.settings.SupportUtils
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type name of the [TopSite].
|
* Returns the type name of the [TopSite].
|
||||||
@ -15,3 +16,22 @@ fun TopSite.name(): String = when (this) {
|
|||||||
is TopSite.Pinned -> "PINNED"
|
is TopSite.Pinned -> "PINNED"
|
||||||
is TopSite.Provided -> "PROVIDED"
|
is TopSite.Provided -> "PROVIDED"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a sorted list of [TopSite] with the default Google top site always appearing
|
||||||
|
* as the first item.
|
||||||
|
*/
|
||||||
|
fun List<TopSite>.sort(): List<TopSite> {
|
||||||
|
val defaultGoogleTopSiteIndex = this.indexOfFirst {
|
||||||
|
it is TopSite.Default && it.url == SupportUtils.GOOGLE_URL
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (defaultGoogleTopSiteIndex == -1) {
|
||||||
|
this
|
||||||
|
} else {
|
||||||
|
val result = this.toMutableList()
|
||||||
|
result.removeAt(defaultGoogleTopSiteIndex)
|
||||||
|
result.add(0, this[defaultGoogleTopSiteIndex])
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -66,6 +66,7 @@ import mozilla.components.concept.sync.OAuthAccount
|
|||||||
import mozilla.components.feature.tab.collections.TabCollection
|
import mozilla.components.feature.tab.collections.TabCollection
|
||||||
import mozilla.components.feature.top.sites.TopSitesConfig
|
import mozilla.components.feature.top.sites.TopSitesConfig
|
||||||
import mozilla.components.feature.top.sites.TopSitesFeature
|
import mozilla.components.feature.top.sites.TopSitesFeature
|
||||||
|
import mozilla.components.feature.top.sites.TopSitesProviderConfig
|
||||||
import mozilla.components.lib.state.ext.consumeFlow
|
import mozilla.components.lib.state.ext.consumeFlow
|
||||||
import mozilla.components.lib.state.ext.consumeFrom
|
import mozilla.components.lib.state.ext.consumeFrom
|
||||||
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
|
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
|
||||||
@ -102,6 +103,7 @@ import org.mozilla.fenix.ext.nav
|
|||||||
import org.mozilla.fenix.ext.requireComponents
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
import org.mozilla.fenix.ext.runIfFragmentIsAttached
|
import org.mozilla.fenix.ext.runIfFragmentIsAttached
|
||||||
import org.mozilla.fenix.ext.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
|
import org.mozilla.fenix.ext.sort
|
||||||
import org.mozilla.fenix.home.mozonline.showPrivacyPopWindow
|
import org.mozilla.fenix.home.mozonline.showPrivacyPopWindow
|
||||||
import org.mozilla.fenix.home.pocket.DefaultPocketStoriesController
|
import org.mozilla.fenix.home.pocket.DefaultPocketStoriesController
|
||||||
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory
|
import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory
|
||||||
@ -124,6 +126,7 @@ import org.mozilla.fenix.settings.SupportUtils
|
|||||||
import org.mozilla.fenix.settings.SupportUtils.SumoTopic.HELP
|
import org.mozilla.fenix.settings.SupportUtils.SumoTopic.HELP
|
||||||
import org.mozilla.fenix.settings.deletebrowsingdata.deleteAndQuit
|
import org.mozilla.fenix.settings.deletebrowsingdata.deleteAndQuit
|
||||||
import org.mozilla.fenix.theme.ThemeManager
|
import org.mozilla.fenix.theme.ThemeManager
|
||||||
|
import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD
|
||||||
import org.mozilla.fenix.utils.ToolbarPopupWindow
|
import org.mozilla.fenix.utils.ToolbarPopupWindow
|
||||||
import org.mozilla.fenix.utils.allowUndo
|
import org.mozilla.fenix.utils.allowUndo
|
||||||
import org.mozilla.fenix.wallpapers.WallpaperManager
|
import org.mozilla.fenix.wallpapers.WallpaperManager
|
||||||
@ -237,7 +240,7 @@ class HomeFragment : Fragment() {
|
|||||||
collections = components.core.tabCollectionStorage.cachedTabCollections,
|
collections = components.core.tabCollectionStorage.cachedTabCollections,
|
||||||
expandedCollections = emptySet(),
|
expandedCollections = emptySet(),
|
||||||
mode = currentMode.getCurrentMode(),
|
mode = currentMode.getCurrentMode(),
|
||||||
topSites = components.core.topSitesStorage.cachedTopSites,
|
topSites = components.core.topSitesStorage.cachedTopSites.sort(),
|
||||||
tip = components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) {
|
tip = components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) {
|
||||||
FenixTipManager(
|
FenixTipManager(
|
||||||
listOf(
|
listOf(
|
||||||
@ -282,7 +285,10 @@ class HomeFragment : Fragment() {
|
|||||||
|
|
||||||
topSitesFeature.set(
|
topSitesFeature.set(
|
||||||
feature = TopSitesFeature(
|
feature = TopSitesFeature(
|
||||||
view = DefaultTopSitesView(homeFragmentStore),
|
view = DefaultTopSitesView(
|
||||||
|
store = homeFragmentStore,
|
||||||
|
settings = components.settings
|
||||||
|
),
|
||||||
storage = components.core.topSitesStorage,
|
storage = components.core.topSitesStorage,
|
||||||
config = ::getTopSitesConfig
|
config = ::getTopSitesConfig
|
||||||
),
|
),
|
||||||
@ -421,8 +427,11 @@ class HomeFragment : Fragment() {
|
|||||||
val settings = requireContext().settings()
|
val settings = requireContext().settings()
|
||||||
return TopSitesConfig(
|
return TopSitesConfig(
|
||||||
totalSites = settings.topSitesMaxLimit,
|
totalSites = settings.topSitesMaxLimit,
|
||||||
fetchProvidedTopSites = settings.showContileFeature,
|
frecencyConfig = if (settings.showTopFrecentSites) FrecencyThresholdOption.SKIP_ONE_TIME_PAGES else null,
|
||||||
frecencyConfig = if (settings.showTopFrecentSites) FrecencyThresholdOption.SKIP_ONE_TIME_PAGES else null
|
providerConfig = TopSitesProviderConfig(
|
||||||
|
showProviderTopSites = settings.showContileFeature,
|
||||||
|
maxThreshold = TOP_SITES_PROVIDER_MAX_THRESHOLD
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,7 +699,7 @@ class HomeFragment : Fragment() {
|
|||||||
HomeFragmentAction.Change(
|
HomeFragmentAction.Change(
|
||||||
collections = components.core.tabCollectionStorage.cachedTabCollections,
|
collections = components.core.tabCollectionStorage.cachedTabCollections,
|
||||||
mode = currentMode.getCurrentMode(),
|
mode = currentMode.getCurrentMode(),
|
||||||
topSites = components.core.topSitesStorage.cachedTopSites,
|
topSites = components.core.topSitesStorage.cachedTopSites.sort(),
|
||||||
tip = components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) {
|
tip = components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) {
|
||||||
FenixTipManager(
|
FenixTipManager(
|
||||||
listOf(
|
listOf(
|
||||||
|
@ -6,14 +6,25 @@ package org.mozilla.fenix.home.topsites
|
|||||||
|
|
||||||
import mozilla.components.feature.top.sites.TopSite
|
import mozilla.components.feature.top.sites.TopSite
|
||||||
import mozilla.components.feature.top.sites.view.TopSitesView
|
import mozilla.components.feature.top.sites.view.TopSitesView
|
||||||
|
import org.mozilla.fenix.ext.sort
|
||||||
import org.mozilla.fenix.home.HomeFragmentAction
|
import org.mozilla.fenix.home.HomeFragmentAction
|
||||||
import org.mozilla.fenix.home.HomeFragmentStore
|
import org.mozilla.fenix.home.HomeFragmentStore
|
||||||
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
class DefaultTopSitesView(
|
class DefaultTopSitesView(
|
||||||
val store: HomeFragmentStore
|
val store: HomeFragmentStore,
|
||||||
|
val settings: Settings
|
||||||
) : TopSitesView {
|
) : TopSitesView {
|
||||||
|
|
||||||
override fun displayTopSites(topSites: List<TopSite>) {
|
override fun displayTopSites(topSites: List<TopSite>) {
|
||||||
store.dispatch(HomeFragmentAction.TopSitesChange(topSites))
|
store.dispatch(
|
||||||
|
HomeFragmentAction.TopSitesChange(
|
||||||
|
if (!settings.showContileFeature) {
|
||||||
|
topSites
|
||||||
|
} else {
|
||||||
|
topSites.sort()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import androidx.lifecycle.LifecycleOwner
|
|||||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action
|
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules.AutoplayAction
|
import mozilla.components.feature.sitepermissions.SitePermissionsRules.AutoplayAction
|
||||||
|
import mozilla.components.service.contile.ContileTopSitesProvider
|
||||||
import mozilla.components.support.ktx.android.content.PreferencesHolder
|
import mozilla.components.support.ktx.android.content.PreferencesHolder
|
||||||
import mozilla.components.support.ktx.android.content.booleanPreference
|
import mozilla.components.support.ktx.android.content.booleanPreference
|
||||||
import mozilla.components.support.ktx.android.content.floatPreference
|
import mozilla.components.support.ktx.android.content.floatPreference
|
||||||
@ -61,7 +62,6 @@ private const val AUTOPLAY_USER_SETTING = "AUTOPLAY_USER_SETTING"
|
|||||||
class Settings(private val appContext: Context) : PreferencesHolder {
|
class Settings(private val appContext: Context) : PreferencesHolder {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val topSitesMaxCount = 16
|
|
||||||
const val FENIX_PREFERENCES = "fenix_preferences"
|
const val FENIX_PREFERENCES = "fenix_preferences"
|
||||||
|
|
||||||
private const val BLOCKED_INT = 0
|
private const val BLOCKED_INT = 0
|
||||||
@ -84,6 +84,14 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
|||||||
*/
|
*/
|
||||||
const val SEARCH_GROUP_MINIMUM_SITES: Int = 2
|
const val SEARCH_GROUP_MINIMUM_SITES: Int = 2
|
||||||
|
|
||||||
|
// The maximum number of top sites to display.
|
||||||
|
const val TOP_SITES_MAX_COUNT = 16
|
||||||
|
/**
|
||||||
|
* Only fetch top sites from the [ContileTopSitesProvider] when the number of default and
|
||||||
|
* pinned sites are below this maximum threshold.
|
||||||
|
*/
|
||||||
|
const val TOP_SITES_PROVIDER_MAX_THRESHOLD = 8
|
||||||
|
|
||||||
private fun Action.toInt() = when (this) {
|
private fun Action.toInt() = when (this) {
|
||||||
Action.BLOCKED -> BLOCKED_INT
|
Action.BLOCKED -> BLOCKED_INT
|
||||||
Action.ASK_TO_ALLOW -> ASK_TO_ALLOW_INT
|
Action.ASK_TO_ALLOW -> ASK_TO_ALLOW_INT
|
||||||
@ -1122,7 +1130,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
|||||||
|
|
||||||
val topSitesMaxLimit by intPreference(
|
val topSitesMaxLimit by intPreference(
|
||||||
appContext.getPreferenceKey(R.string.pref_key_top_sites_max_limit),
|
appContext.getPreferenceKey(R.string.pref_key_top_sites_max_limit),
|
||||||
default = topSitesMaxCount
|
default = TOP_SITES_MAX_COUNT
|
||||||
)
|
)
|
||||||
|
|
||||||
var openTabsCount by intPreference(
|
var openTabsCount by intPreference(
|
||||||
|
117
app/src/test/java/org/mozilla/fenix/ext/TopSiteTest.kt
Normal file
117
app/src/test/java/org/mozilla/fenix/ext/TopSiteTest.kt
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/* 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 mozilla.components.feature.top.sites.TopSite
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
import org.mozilla.fenix.settings.SupportUtils
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class TopSiteTest {
|
||||||
|
|
||||||
|
val defaultGoogleTopSite = TopSite.Default(
|
||||||
|
id = 1L,
|
||||||
|
title = "Google",
|
||||||
|
url = SupportUtils.GOOGLE_URL,
|
||||||
|
createdAt = 0
|
||||||
|
)
|
||||||
|
val providedSite1 = TopSite.Provided(
|
||||||
|
id = 3,
|
||||||
|
title = "Mozilla",
|
||||||
|
url = "https://mozilla.com",
|
||||||
|
clickUrl = "https://mozilla.com/click",
|
||||||
|
imageUrl = "https://test.com/image2.jpg",
|
||||||
|
impressionUrl = "https://example.com",
|
||||||
|
createdAt = 3
|
||||||
|
)
|
||||||
|
val providedSite2 = TopSite.Provided(
|
||||||
|
id = 3,
|
||||||
|
title = "Firefox",
|
||||||
|
url = "https://firefox.com",
|
||||||
|
clickUrl = "https://firefox.com/click",
|
||||||
|
imageUrl = "https://test.com/image2.jpg",
|
||||||
|
impressionUrl = "https://example.com",
|
||||||
|
createdAt = 3
|
||||||
|
)
|
||||||
|
val pinnedSite1 = TopSite.Pinned(
|
||||||
|
id = 1L,
|
||||||
|
title = "DuckDuckGo",
|
||||||
|
url = "https://duckduckgo.com",
|
||||||
|
createdAt = 0
|
||||||
|
)
|
||||||
|
val pinnedSite2 = TopSite.Pinned(
|
||||||
|
id = 1L,
|
||||||
|
title = "Mozilla",
|
||||||
|
url = "mozilla.org",
|
||||||
|
createdAt = 0
|
||||||
|
)
|
||||||
|
val frecentSite = TopSite.Frecent(
|
||||||
|
id = 1L,
|
||||||
|
title = "Mozilla",
|
||||||
|
url = "mozilla.org",
|
||||||
|
createdAt = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN the default Google top site is the first item WHEN the list of top sites is sorted THEN the order doesn't change`() {
|
||||||
|
val topSites = listOf(
|
||||||
|
defaultGoogleTopSite,
|
||||||
|
providedSite1,
|
||||||
|
providedSite2,
|
||||||
|
pinnedSite1,
|
||||||
|
pinnedSite2,
|
||||||
|
frecentSite
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(topSites.sort(), topSites)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN the default Google top site is after the provided top sites WHEN the list of top sites is sorted THEN the default Google top site should be first`() {
|
||||||
|
val topSites = listOf(
|
||||||
|
providedSite1,
|
||||||
|
providedSite2,
|
||||||
|
defaultGoogleTopSite,
|
||||||
|
pinnedSite1,
|
||||||
|
pinnedSite2,
|
||||||
|
frecentSite
|
||||||
|
)
|
||||||
|
val expected = listOf(
|
||||||
|
defaultGoogleTopSite,
|
||||||
|
providedSite1,
|
||||||
|
providedSite2,
|
||||||
|
pinnedSite1,
|
||||||
|
pinnedSite2,
|
||||||
|
frecentSite
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(topSites.sort(), expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN the default Google top site is the last item WHEN the list of top sites is sorted THEN the default Google top site should be first`() {
|
||||||
|
val topSites = listOf(
|
||||||
|
providedSite1,
|
||||||
|
providedSite2,
|
||||||
|
pinnedSite1,
|
||||||
|
pinnedSite2,
|
||||||
|
frecentSite,
|
||||||
|
defaultGoogleTopSite
|
||||||
|
)
|
||||||
|
val expected = listOf(
|
||||||
|
defaultGoogleTopSite,
|
||||||
|
providedSite1,
|
||||||
|
providedSite2,
|
||||||
|
pinnedSite1,
|
||||||
|
pinnedSite2,
|
||||||
|
frecentSite
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(topSites.sort(), expected)
|
||||||
|
}
|
||||||
|
}
|
@ -3,5 +3,5 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
object AndroidComponents {
|
object AndroidComponents {
|
||||||
const val VERSION = "99.0.20220209143350"
|
const val VERSION = "99.0.20220209170927"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user