mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-19 09:25:34 +00:00
[fenix] For https://github.com/mozilla-mobile/fenix/issues/21095 add customize home button on the home screen.
This commit is contained in:
parent
b057d6a76f
commit
5ce4a31be5
@ -31,6 +31,7 @@ import org.mozilla.fenix.home.recenttabs.view.RecentTabViewHolder
|
||||
import org.mozilla.fenix.home.recenttabs.view.RecentTabsHeaderViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionHeaderViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.CustomizeHomeButtonViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.NoCollectionsMessageViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.PrivateBrowsingDescriptionViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.TabInCollectionViewHolder
|
||||
@ -163,6 +164,8 @@ sealed class AdapterItem(@LayoutRes val viewType: Int) {
|
||||
|
||||
object OnboardingWhatsNew : AdapterItem(OnboardingWhatsNewViewHolder.LAYOUT_ID)
|
||||
|
||||
object CustomizeHomeButton : AdapterItem(CustomizeHomeButtonViewHolder.LAYOUT_ID)
|
||||
|
||||
object RecentTabsHeader : AdapterItem(RecentTabsHeaderViewHolder.LAYOUT_ID)
|
||||
object RecentTabItem : AdapterItem(RecentTabViewHolder.LAYOUT_ID)
|
||||
|
||||
@ -250,7 +253,7 @@ class SessionControlAdapter(
|
||||
) : ListAdapter<AdapterItem, RecyclerView.ViewHolder>(AdapterItemDiffCallback()) {
|
||||
|
||||
// This method triggers the ComplexMethod lint error when in fact it's quite simple.
|
||||
@SuppressWarnings("ComplexMethod")
|
||||
@SuppressWarnings("ComplexMethod", "LongMethod")
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
when (viewType) {
|
||||
PocketStoriesViewHolder.LAYOUT_ID -> return PocketStoriesViewHolder(
|
||||
@ -304,6 +307,7 @@ class SessionControlAdapter(
|
||||
view,
|
||||
interactor
|
||||
)
|
||||
CustomizeHomeButtonViewHolder.LAYOUT_ID -> CustomizeHomeButtonViewHolder(view, interactor)
|
||||
OnboardingFinishViewHolder.LAYOUT_ID -> OnboardingFinishViewHolder(view, interactor)
|
||||
OnboardingWhatsNewViewHolder.LAYOUT_ID -> OnboardingWhatsNewViewHolder(view, interactor)
|
||||
OnboardingToolbarPositionPickerViewHolder.LAYOUT_ID -> OnboardingToolbarPositionPickerViewHolder(
|
||||
|
@ -187,6 +187,11 @@ interface SessionControlController {
|
||||
* @see [TabSessionInteractor.onPrivateModeButtonClicked]
|
||||
*/
|
||||
fun handlePrivateModeButtonClicked(newMode: BrowsingMode, userHasBeenOnboarded: Boolean)
|
||||
|
||||
/**
|
||||
* @see [CustomizeHomeIteractor.openCustomizeHomePage]
|
||||
*/
|
||||
fun handleCustomizeHomeTapped()
|
||||
}
|
||||
|
||||
@Suppress("TooManyFunctions", "LargeClass")
|
||||
@ -452,6 +457,11 @@ class DefaultSessionControlController(
|
||||
navController.nav(R.id.homeFragment, directions)
|
||||
}
|
||||
|
||||
override fun handleCustomizeHomeTapped() {
|
||||
val directions = HomeFragmentDirections.actionGlobalCustomizationFragment()
|
||||
navController.nav(R.id.homeFragment, directions)
|
||||
}
|
||||
|
||||
override fun handleWhatsNewGetAnswersClicked() {
|
||||
activity.openToBrowserAndLoad(
|
||||
searchTermOrURL = SupportUtils.getWhatsNewUrl(activity),
|
||||
|
@ -165,6 +165,13 @@ interface TipInteractor {
|
||||
fun onCloseTip(tip: Tip)
|
||||
}
|
||||
|
||||
interface CustomizeHomeIteractor {
|
||||
/**
|
||||
* Opens the customize home settings page.
|
||||
*/
|
||||
fun openCustomizeHomePage()
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for top site related actions in the [SessionControlInteractor].
|
||||
*/
|
||||
@ -237,7 +244,8 @@ class SessionControlInteractor(
|
||||
ExperimentCardInteractor,
|
||||
RecentTabInteractor,
|
||||
RecentBookmarksInteractor,
|
||||
HistoryMetadataInteractor {
|
||||
HistoryMetadataInteractor,
|
||||
CustomizeHomeIteractor {
|
||||
|
||||
override fun onCollectionAddTabTapped(collection: TabCollection) {
|
||||
controller.handleCollectionAddTabTapped(collection)
|
||||
@ -376,4 +384,8 @@ class SessionControlInteractor(
|
||||
historyMetadataGroup
|
||||
)
|
||||
}
|
||||
|
||||
override fun openCustomizeHomePage() {
|
||||
controller.handleCustomizeHomeTapped()
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ package org.mozilla.fenix.home.sessioncontrol
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@ -28,7 +29,8 @@ import org.mozilla.fenix.home.OnboardingState
|
||||
// This method got a little complex with the addition of the tab tray feature flag
|
||||
// When we remove the tabs from the home screen this will get much simpler again.
|
||||
@Suppress("ComplexMethod", "LongParameterList")
|
||||
private fun normalModeAdapterItems(
|
||||
@VisibleForTesting
|
||||
internal fun normalModeAdapterItems(
|
||||
context: Context,
|
||||
topSites: List<TopSite>,
|
||||
collections: List<TabCollection>,
|
||||
@ -42,6 +44,7 @@ private fun normalModeAdapterItems(
|
||||
pocketArticles: List<PocketRecommendedStory>
|
||||
): List<AdapterItem> {
|
||||
val items = mutableListOf<AdapterItem>()
|
||||
var shouldShowCustomizeHome = false
|
||||
|
||||
tip?.let { items.add(AdapterItem.TipItem(it)) }
|
||||
|
||||
@ -54,15 +57,18 @@ private fun normalModeAdapterItems(
|
||||
}
|
||||
|
||||
if (recentTabs.isNotEmpty()) {
|
||||
shouldShowCustomizeHome = true
|
||||
items.add(AdapterItem.RecentTabsHeader)
|
||||
items.add(AdapterItem.RecentTabItem)
|
||||
}
|
||||
|
||||
if (recentBookmarks.isNotEmpty()) {
|
||||
shouldShowCustomizeHome = true
|
||||
items.add(AdapterItem.RecentBookmarks(recentBookmarks))
|
||||
}
|
||||
|
||||
if (historyMetadata.isNotEmpty()) {
|
||||
shouldShowCustomizeHome = true
|
||||
showHistoryMetadata(historyMetadata, items)
|
||||
}
|
||||
|
||||
@ -75,9 +81,14 @@ private fun normalModeAdapterItems(
|
||||
}
|
||||
|
||||
if (context.settings().pocketRecommendations && pocketArticles.isNotEmpty()) {
|
||||
shouldShowCustomizeHome = true
|
||||
items.add(AdapterItem.PocketStoriesItem)
|
||||
}
|
||||
|
||||
if (shouldShowCustomizeHome) {
|
||||
items.add(AdapterItem.CustomizeHomeButton)
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
/* 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.home.sessioncontrol.viewholders
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.databinding.CustomizeHomeListItemBinding
|
||||
import org.mozilla.fenix.home.sessioncontrol.CustomizeHomeIteractor
|
||||
|
||||
class CustomizeHomeButtonViewHolder(
|
||||
view: View,
|
||||
private val interactor: CustomizeHomeIteractor
|
||||
) : RecyclerView.ViewHolder(view) {
|
||||
|
||||
init {
|
||||
val binding = CustomizeHomeListItemBinding.bind(view)
|
||||
|
||||
binding.customizeHome.setOnClickListener {
|
||||
interactor.openCustomizeHomePage()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val LAYOUT_ID = R.layout.customize_home_list_item
|
||||
}
|
||||
}
|
26
app/src/main/res/layout/customize_home_list_item.xml
Normal file
26
app/src/main/res/layout/customize_home_list_item.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/about_list_item_height"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<Button
|
||||
android:id="@+id/customize_home"
|
||||
style="@style/NeutralOnboardingButton"
|
||||
android:layout_height="36dp"
|
||||
android:background="@drawable/rounded_button_background"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:text="@string/browser_menu_customize_home"
|
||||
android:gravity="center"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -162,6 +162,20 @@ class DefaultSessionControlControllerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleCustomizeHomeTapped() {
|
||||
createController().handleCustomizeHomeTapped()
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
match<NavDirections> {
|
||||
it.actionId == R.id.action_global_customizationFragment
|
||||
},
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `handleCollectionOpenTabClicked onFailure`() {
|
||||
val tab = mockk<ComponentTab> {
|
||||
|
@ -223,6 +223,12 @@ class SessionControlInteractorTest {
|
||||
verify { recentBookmarksController.handleBookmarkClicked(bookmark) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN tapping on the customize home button THEN openCustomizeHomePage`() {
|
||||
interactor.openCustomizeHomePage()
|
||||
verify { controller.handleCustomizeHomeTapped() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN Show All recently saved bookmarks button is clicked THEN the click is handled`() {
|
||||
interactor.onShowAllBookmarksClicked()
|
||||
|
@ -0,0 +1,40 @@
|
||||
/* 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.home.sessioncontrol
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.databinding.CustomizeHomeListItemBinding
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.CustomizeHomeButtonViewHolder
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class CustomizeHomeButtonViewHolderTest {
|
||||
|
||||
private lateinit var binding: CustomizeHomeListItemBinding
|
||||
private lateinit var interactor: CustomizeHomeIteractor
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
binding = CustomizeHomeListItemBinding.inflate(LayoutInflater.from(testContext))
|
||||
interactor = mockk(relaxed = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `hide view and change setting on remove placeholder click`() {
|
||||
CustomizeHomeButtonViewHolder(binding.root, interactor)
|
||||
|
||||
binding.customizeHome.performClick()
|
||||
|
||||
verify {
|
||||
interactor.openCustomizeHomePage()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
/* 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.home.sessioncontrol
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.spyk
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.concept.storage.BookmarkNode
|
||||
import mozilla.components.concept.storage.BookmarkNodeType
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.service.pocket.PocketRecommendedStory
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.historymetadata.HistoryMetadataGroup
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class SessionControlViewTest {
|
||||
@Test
|
||||
fun `GIVEN recent Bookmarks WHEN normalModeAdapterItems is called THEN add a customize home button`() {
|
||||
val topSites = emptyList<TopSite>()
|
||||
val collections = emptyList<TabCollection>()
|
||||
val expandedCollections = emptySet<Long>()
|
||||
val recentBookmarks =
|
||||
listOf(BookmarkNode(BookmarkNodeType.ITEM, "guid", null, null, null, null, 0, null))
|
||||
val recentTabs = emptyList<TabSessionState>()
|
||||
val historyMetadata = emptyList<HistoryMetadataGroup>()
|
||||
val pocketArticles = emptyList<PocketRecommendedStory>()
|
||||
|
||||
val results = normalModeAdapterItems(
|
||||
testContext,
|
||||
topSites,
|
||||
collections,
|
||||
expandedCollections,
|
||||
null,
|
||||
recentBookmarks,
|
||||
false,
|
||||
false,
|
||||
recentTabs,
|
||||
historyMetadata,
|
||||
pocketArticles
|
||||
)
|
||||
|
||||
assertTrue(results[0] is AdapterItem.RecentBookmarks)
|
||||
assertTrue(results[1] is AdapterItem.CustomizeHomeButton)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN recent tabs WHEN normalModeAdapterItems is called THEN add a customize home button`() {
|
||||
val topSites = emptyList<TopSite>()
|
||||
val collections = emptyList<TabCollection>()
|
||||
val expandedCollections = emptySet<Long>()
|
||||
val recentBookmarks = listOf<BookmarkNode>()
|
||||
val recentTabs = listOf<TabSessionState>(mockk())
|
||||
val historyMetadata = emptyList<HistoryMetadataGroup>()
|
||||
val pocketArticles = emptyList<PocketRecommendedStory>()
|
||||
|
||||
val results = normalModeAdapterItems(
|
||||
testContext,
|
||||
topSites,
|
||||
collections,
|
||||
expandedCollections,
|
||||
null,
|
||||
recentBookmarks,
|
||||
false,
|
||||
false,
|
||||
recentTabs,
|
||||
historyMetadata,
|
||||
pocketArticles
|
||||
)
|
||||
|
||||
assertTrue(results[0] is AdapterItem.RecentTabsHeader)
|
||||
assertTrue(results[1] is AdapterItem.RecentTabItem)
|
||||
assertTrue(results[2] is AdapterItem.CustomizeHomeButton)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN history metadata WHEN normalModeAdapterItems is called THEN add a customize home button`() {
|
||||
val topSites = emptyList<TopSite>()
|
||||
val collections = emptyList<TabCollection>()
|
||||
val expandedCollections = emptySet<Long>()
|
||||
val recentBookmarks = listOf<BookmarkNode>()
|
||||
val recentTabs = emptyList<TabSessionState>()
|
||||
val historyMetadata = listOf(HistoryMetadataGroup("title", emptyList(), false))
|
||||
val pocketArticles = emptyList<PocketRecommendedStory>()
|
||||
|
||||
val results = normalModeAdapterItems(
|
||||
testContext,
|
||||
topSites,
|
||||
collections,
|
||||
expandedCollections,
|
||||
null,
|
||||
recentBookmarks,
|
||||
false,
|
||||
false,
|
||||
recentTabs,
|
||||
historyMetadata,
|
||||
pocketArticles
|
||||
)
|
||||
|
||||
assertTrue(results[0] is AdapterItem.HistoryMetadataHeader)
|
||||
assertTrue(results[1] is AdapterItem.HistoryMetadataGroup)
|
||||
assertTrue(results[2] is AdapterItem.CustomizeHomeButton)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN pocket articles WHEN normalModeAdapterItems is called THEN add a customize home button`() {
|
||||
val topSites = emptyList<TopSite>()
|
||||
val collections = emptyList<TabCollection>()
|
||||
val expandedCollections = emptySet<Long>()
|
||||
val recentBookmarks = listOf<BookmarkNode>()
|
||||
val recentTabs = emptyList<TabSessionState>()
|
||||
val historyMetadata = emptyList<HistoryMetadataGroup>()
|
||||
val pocketArticles = listOf(PocketRecommendedStory("", "", "", "", 0, ""))
|
||||
val context = spyk(testContext)
|
||||
|
||||
val settings: Settings = mockk()
|
||||
every { settings.pocketRecommendations } returns true
|
||||
every { context.settings() } returns settings
|
||||
|
||||
val results = normalModeAdapterItems(
|
||||
context,
|
||||
topSites,
|
||||
collections,
|
||||
expandedCollections,
|
||||
null,
|
||||
recentBookmarks,
|
||||
false,
|
||||
false,
|
||||
recentTabs,
|
||||
historyMetadata,
|
||||
pocketArticles
|
||||
)
|
||||
|
||||
assertTrue(results[0] is AdapterItem.PocketStoriesItem)
|
||||
assertTrue(results[1] is AdapterItem.CustomizeHomeButton)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN none recentBookmarks,recentTabs, historyMetadata or pocketArticles WHEN normalModeAdapterItems is called THEN the customize home button is not added`() {
|
||||
val topSites = emptyList<TopSite>()
|
||||
val collections = emptyList<TabCollection>()
|
||||
val expandedCollections = emptySet<Long>()
|
||||
val recentBookmarks = listOf<BookmarkNode>()
|
||||
val recentTabs = emptyList<TabSessionState>()
|
||||
val historyMetadata = emptyList<HistoryMetadataGroup>()
|
||||
val pocketArticles = emptyList<PocketRecommendedStory>()
|
||||
val context = spyk(testContext)
|
||||
|
||||
val settings: Settings = mockk()
|
||||
every { settings.pocketRecommendations } returns true
|
||||
every { context.settings() } returns settings
|
||||
|
||||
val results = normalModeAdapterItems(
|
||||
context,
|
||||
topSites,
|
||||
collections,
|
||||
expandedCollections,
|
||||
null,
|
||||
recentBookmarks,
|
||||
false,
|
||||
false,
|
||||
recentTabs,
|
||||
historyMetadata,
|
||||
pocketArticles
|
||||
)
|
||||
assertTrue(results.isEmpty())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user