From 655d2b8a88eaed45d47c3ca852b4064f0ea8b058 Mon Sep 17 00:00:00 2001 From: ekager Date: Fri, 21 Aug 2020 21:44:51 -0400 Subject: [PATCH] For #12377 - Choice to hide no collections placeholder from homescreen --- .../org/mozilla/fenix/home/HomeFragment.kt | 18 ++-- .../mozilla/fenix/home/HomeFragmentStore.kt | 16 +++- .../sessioncontrol/SessionControlAdapter.kt | 12 ++- .../SessionControlController.kt | 26 +++++- .../SessionControlInteractor.kt | 9 ++ .../home/sessioncontrol/SessionControlView.kt | 91 +++++++++++-------- .../NoCollectionsMessageViewHolder.kt | 36 +++++++- .../java/org/mozilla/fenix/utils/Settings.kt | 5 + .../res/layout/no_collections_message.xml | 55 +++++++---- app/src/main/res/values/dimens.xml | 1 + app/src/main/res/values/preference_keys.xml | 2 + app/src/main/res/values/strings.xml | 6 +- .../DefaultSessionControlControllerTest.kt | 15 ++- .../fenix/home/HomeFragmentStoreTest.kt | 51 +++++++---- .../home/SessionControlInteractorTest.kt | 6 ++ .../NoCollectionsMessageViewHolderTest.kt | 34 ++++++- .../org/mozilla/fenix/utils/SettingsTest.kt | 13 +++ 17 files changed, 298 insertions(+), 98 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index a914d33b1..ace14c198 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -146,8 +146,11 @@ class HomeFragment : Fragment() { private val store: BrowserStore get() = requireComponents.core.store - private val onboarding by lazy { StrictMode.allowThreadDiskReads().resetPoliciesAfter { - FenixOnboarding(requireContext()) } } + private val onboarding by lazy { + StrictMode.allowThreadDiskReads().resetPoliciesAfter { + FenixOnboarding(requireContext()) + } + } private lateinit var homeFragmentStore: HomeFragmentStore private var _sessionControlInteractor: SessionControlInteractor? = null @@ -193,7 +196,8 @@ class HomeFragment : Fragment() { topSites = StrictMode.allowThreadDiskReads().resetPoliciesAfter { components.core.topSiteStorage.cachedTopSites }, - tip = FenixTipManager(listOf(MigrationTipProvider(requireContext()))).getTip() + tip = FenixTipManager(listOf(MigrationTipProvider(requireContext()))).getTip(), + showCollectionPlaceholder = components.settings.showCollectionsPlaceholderOnHome ) ) } @@ -201,6 +205,7 @@ class HomeFragment : Fragment() { _sessionControlInteractor = SessionControlInteractor( DefaultSessionControlController( activity = activity, + settings = components.settings, engine = components.core.engine, metrics = components.analytics.metrics, sessionManager = sessionManager, @@ -220,9 +225,9 @@ class HomeFragment : Fragment() { updateLayout(view) sessionControlView = SessionControlView( view.sessionControlRecyclerView, + viewLifecycleOwner, sessionControlInteractor, - homeViewModel, - requireComponents.core.store.state.normalTabs.isNotEmpty() + homeViewModel ) updateSessionControlView(view) @@ -516,7 +521,8 @@ class HomeFragment : Fragment() { collections = components.core.tabCollectionStorage.cachedTabCollections, mode = currentMode.getCurrentMode(), topSites = components.core.topSiteStorage.cachedTopSites, - tip = FenixTipManager(listOf(MigrationTipProvider(requireContext()))).getTip() + tip = FenixTipManager(listOf(MigrationTipProvider(requireContext()))).getTip(), + showCollectionPlaceholder = components.settings.showCollectionsPlaceholderOnHome ) ) diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragmentStore.kt index bbe46024a..dc6b78d7d 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragmentStore.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragmentStore.kt @@ -41,13 +41,16 @@ data class Tab( * @property mode The state of the [HomeFragment] UI. * @property tabs The list of opened [Tab] in the [HomeFragment]. * @property topSites The list of [TopSite] in the [HomeFragment]. + * @property tip The current [Tip] to show on the [HomeFragment]. + * @property showCollectionPlaceholder If true, shows a placeholder when there are no collections. */ data class HomeFragmentState( val collections: List, val expandedCollections: Set, val mode: Mode, val topSites: List, - val tip: Tip? = null + val tip: Tip? = null, + val showCollectionPlaceholder: Boolean ) : State sealed class HomeFragmentAction : Action { @@ -55,7 +58,8 @@ sealed class HomeFragmentAction : Action { val topSites: List, val mode: Mode, val collections: List, - val tip: Tip? = null + val tip: Tip? = null, + val showCollectionPlaceholder: Boolean ) : HomeFragmentAction() @@ -66,6 +70,7 @@ sealed class HomeFragmentAction : Action { data class ModeChange(val mode: Mode) : HomeFragmentAction() data class TopSitesChange(val topSites: List) : HomeFragmentAction() data class RemoveTip(val tip: Tip) : HomeFragmentAction() + object RemoveCollectionsPlaceholder : HomeFragmentAction() } private fun homeFragmentStateReducer( @@ -93,6 +98,11 @@ private fun homeFragmentStateReducer( is HomeFragmentAction.CollectionsChange -> state.copy(collections = action.collections) is HomeFragmentAction.ModeChange -> state.copy(mode = action.mode) is HomeFragmentAction.TopSitesChange -> state.copy(topSites = action.topSites) - is HomeFragmentAction.RemoveTip -> { state.copy(tip = null) } + is HomeFragmentAction.RemoveTip -> { + state.copy(tip = null) + } + is HomeFragmentAction.RemoveCollectionsPlaceholder -> { + state.copy(showCollectionPlaceholder = false) + } } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt index 6acca7d2e..487d34db2 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt @@ -8,11 +8,13 @@ import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup import androidx.annotation.LayoutRes +import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.top.sites.TopSite +import org.mozilla.fenix.components.Components import org.mozilla.fenix.components.tips.Tip import org.mozilla.fenix.home.OnboardingState import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionHeaderViewHolder @@ -135,7 +137,8 @@ class AdapterItemDiffCallback : DiffUtil.ItemCallback() { class SessionControlAdapter( private val interactor: SessionControlInteractor, - private val hasNormalTabsOpened: Boolean + private val viewLifecycleOwner: LifecycleOwner, + private val components: Components ) : ListAdapter(AdapterItemDiffCallback()) { // This method triggers the ComplexMethod lint error when in fact it's quite simple. @@ -150,7 +153,12 @@ class SessionControlAdapter( interactor ) NoCollectionsMessageViewHolder.LAYOUT_ID -> - NoCollectionsMessageViewHolder(view, interactor, hasNormalTabsOpened) + NoCollectionsMessageViewHolder( + view, + viewLifecycleOwner, + components.core.store, + interactor + ) CollectionHeaderViewHolder.LAYOUT_ID -> CollectionHeaderViewHolder(view) CollectionViewHolder.LAYOUT_ID -> CollectionViewHolder(view, interactor) TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder( diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt index a5b4b7de7..73a32c5a6 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt @@ -37,6 +37,7 @@ import org.mozilla.fenix.home.HomeFragmentAction import org.mozilla.fenix.home.HomeFragmentDirections import org.mozilla.fenix.home.HomeFragmentStore import org.mozilla.fenix.settings.SupportUtils +import org.mozilla.fenix.utils.Settings import mozilla.components.feature.tab.collections.Tab as ComponentTab /** @@ -144,11 +145,17 @@ interface SessionControlController { * @see [CollectionInteractor.onAddTabsToCollectionTapped] */ fun handleCreateCollection() + + /** + * @see [CollectionInteractor.onRemoveCollectionsPlaceholder] + */ + fun handleRemoveCollectionsPlaceholder() } @Suppress("TooManyFunctions", "LargeClass") class DefaultSessionControlController( private val activity: HomeActivity, + private val settings: Settings, private val engine: Engine, private val metrics: MetricController, private val sessionManager: SessionManager, @@ -213,7 +220,11 @@ class DefaultSessionControlController( metrics.track(Event.CollectionAllTabsRestored) } - override fun handleCollectionRemoveTab(collection: TabCollection, tab: ComponentTab, wasSwiped: Boolean) { + override fun handleCollectionRemoveTab( + collection: TabCollection, + tab: ComponentTab, + wasSwiped: Boolean + ) { metrics.track(Event.CollectionTabRemoved) if (collection.tabs.size == 1) { @@ -223,7 +234,13 @@ class DefaultSessionControlController( ) val message = activity.resources.getString(R.string.delete_tab_and_collection_dialog_message) - showDeleteCollectionPrompt(collection, title, message, wasSwiped, handleSwipedItemDeletionCancel) + showDeleteCollectionPrompt( + collection, + title, + message, + wasSwiped, + handleSwipedItemDeletionCancel + ) } else { viewLifecycleScope.launch(Dispatchers.IO) { tabCollectionStorage.removeTabFromCollection(collection, tab) @@ -369,6 +386,11 @@ class DefaultSessionControlController( showTabTrayCollectionCreation() } + override fun handleRemoveCollectionsPlaceholder() { + settings.showCollectionsPlaceholderOnHome = false + fragmentStore.dispatch(HomeFragmentAction.RemoveCollectionsPlaceholder) + } + private fun showShareFragment(shareSubject: String, data: List) { val directions = HomeFragmentDirections.actionGlobalShareFragment( shareSubject = shareSubject, diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt index 644178f38..b33b97699 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt @@ -93,6 +93,11 @@ interface CollectionInteractor { * Opens the collection creator */ fun onAddTabsToCollectionTapped() + + /** + * User has removed the collections placeholder from home. + */ + fun onRemoveCollectionsPlaceholder() } interface ToolbarInteractor { @@ -256,4 +261,8 @@ class SessionControlInteractor( override fun onPaste(clipboardText: String) { controller.handlePaste(clipboardText) } + + override fun onRemoveCollectionsPlaceholder() { + controller.handleRemoveCollectionsPlaceholder() + } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt index c2f363140..73f1585bf 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.home.sessioncontrol import android.view.View +import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -13,6 +14,7 @@ import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.top.sites.TopSite import org.mozilla.fenix.R import org.mozilla.fenix.components.tips.Tip +import org.mozilla.fenix.ext.components import org.mozilla.fenix.home.HomeFragmentState import org.mozilla.fenix.home.HomeScreenViewModel import org.mozilla.fenix.home.Mode @@ -25,7 +27,8 @@ private fun normalModeAdapterItems( topSites: List, collections: List, expandedCollections: Set, - tip: Tip? + tip: Tip?, + showCollectionsPlaceholder: Boolean ): List { val items = mutableListOf() @@ -36,8 +39,9 @@ private fun normalModeAdapterItems( } if (collections.isEmpty()) { - items.add(AdapterItem.CollectionHeader) - items.add(AdapterItem.NoCollectionsMessage) + if (showCollectionsPlaceholder) { + items.add(AdapterItem.NoCollectionsMessage) + } } else { showCollections(collections, expandedCollections, items) } @@ -68,62 +72,77 @@ private fun onboardingAdapterItems(onboardingState: OnboardingState): List = mutableListOf(AdapterItem.OnboardingHeader) // Customize FxA items based on where we are with the account state: - items.addAll(when (onboardingState) { - OnboardingState.SignedOutNoAutoSignIn -> { - listOf( - AdapterItem.OnboardingManualSignIn - ) + items.addAll( + when (onboardingState) { + OnboardingState.SignedOutNoAutoSignIn -> { + listOf( + AdapterItem.OnboardingManualSignIn + ) + } + is OnboardingState.SignedOutCanAutoSignIn -> { + listOf( + AdapterItem.OnboardingAutomaticSignIn(onboardingState) + ) + } + OnboardingState.SignedIn -> listOf() } - is OnboardingState.SignedOutCanAutoSignIn -> { - listOf( - AdapterItem.OnboardingAutomaticSignIn(onboardingState) - ) - } - OnboardingState.SignedIn -> listOf() - }) + ) - items.addAll(listOf( - AdapterItem.OnboardingSectionHeader { - val appName = it.getString(R.string.app_name) - it.getString(R.string.onboarding_feature_section_header, appName) - }, - AdapterItem.OnboardingWhatsNew, - AdapterItem.OnboardingTrackingProtection, - AdapterItem.OnboardingThemePicker, - AdapterItem.OnboardingPrivateBrowsing, - AdapterItem.OnboardingToolbarPositionPicker, - AdapterItem.OnboardingPrivacyNotice, - AdapterItem.OnboardingFinish - )) + items.addAll( + listOf( + AdapterItem.OnboardingSectionHeader { + val appName = it.getString(R.string.app_name) + it.getString(R.string.onboarding_feature_section_header, appName) + }, + AdapterItem.OnboardingWhatsNew, + AdapterItem.OnboardingTrackingProtection, + AdapterItem.OnboardingThemePicker, + AdapterItem.OnboardingPrivateBrowsing, + AdapterItem.OnboardingToolbarPositionPicker, + AdapterItem.OnboardingPrivacyNotice, + AdapterItem.OnboardingFinish + ) + ) return items } private fun HomeFragmentState.toAdapterList(): List = when (mode) { - is Mode.Normal -> normalModeAdapterItems(topSites, collections, expandedCollections, tip) + is Mode.Normal -> normalModeAdapterItems( + topSites, + collections, + expandedCollections, + tip, + showCollectionPlaceholder + ) is Mode.Private -> privateModeAdapterItems() is Mode.Onboarding -> onboardingAdapterItems(mode.state) } -private fun collectionTabItems(collection: TabCollection) = collection.tabs.mapIndexed { index, tab -> +private fun collectionTabItems(collection: TabCollection) = + collection.tabs.mapIndexed { index, tab -> AdapterItem.TabInCollectionItem(collection, tab, index == collection.tabs.lastIndex) -} + } class SessionControlView( - override val containerView: View?, + override val containerView: View, + viewLifecycleOwner: LifecycleOwner, interactor: SessionControlInteractor, - private var homeScreenViewModel: HomeScreenViewModel, - private val hasNormalTabsOpened: Boolean + private var homeScreenViewModel: HomeScreenViewModel ) : LayoutContainer { val view: RecyclerView = containerView as RecyclerView - private val sessionControlAdapter = SessionControlAdapter(interactor, hasNormalTabsOpened) + private val sessionControlAdapter = SessionControlAdapter( + interactor, + viewLifecycleOwner, + containerView.context.components + ) init { view.apply { adapter = sessionControlAdapter - layoutManager = LinearLayoutManager(containerView!!.context) + layoutManager = LinearLayoutManager(containerView.context) val itemTouchHelper = ItemTouchHelper( SwipeToDeleteCallback( diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolder.kt index 00a42acdc..ed3c128d0 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolder.kt @@ -6,22 +6,50 @@ package org.mozilla.fenix.home.sessioncontrol.viewholders import android.view.View import androidx.core.view.isVisible +import androidx.lifecycle.LifecycleOwner import kotlinx.android.synthetic.main.no_collections_message.* +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.map +import mozilla.components.browser.state.selector.normalTabs +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.lib.state.ext.flowScoped +import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged import org.mozilla.fenix.R -import org.mozilla.fenix.utils.view.ViewHolder +import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.home.sessioncontrol.CollectionInteractor +import org.mozilla.fenix.utils.view.ViewHolder +@OptIn(ExperimentalCoroutinesApi::class) open class NoCollectionsMessageViewHolder( view: View, - interactor: CollectionInteractor, - hasNormalTabsOpened: Boolean + viewLifecycleOwner: LifecycleOwner, + store: BrowserStore, + interactor: CollectionInteractor ) : ViewHolder(view) { init { add_tabs_to_collections_button.setOnClickListener { interactor.onAddTabsToCollectionTapped() } - add_tabs_to_collections_button.isVisible = hasNormalTabsOpened + + remove_collection_placeholder.increaseTapArea( + view.resources.getDimensionPixelSize(R.dimen.tap_increase_16) + ) + + remove_collection_placeholder.setOnClickListener { + interactor.onRemoveCollectionsPlaceholder() + } + + add_tabs_to_collections_button.isVisible = store.state.normalTabs.isNotEmpty() + + store.flowScoped(viewLifecycleOwner) { flow -> + flow.map { state -> state.normalTabs.size } + .ifChanged() + .collect { tabs -> + add_tabs_to_collections_button.isVisible = tabs > 0 + } + } } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index 885720d07..3cd3f8399 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -249,6 +249,11 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = false ) + var showCollectionsPlaceholderOnHome by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_show_collections_placeholder_home), + default = true + ) + val isCrashReportingEnabled: Boolean get() = isCrashReportEnabledInBuild && preferences.getBoolean( diff --git a/app/src/main/res/layout/no_collections_message.xml b/app/src/main/res/layout/no_collections_message.xml index a37d36062..472259061 100644 --- a/app/src/main/res/layout/no_collections_message.xml +++ b/app/src/main/res/layout/no_collections_message.xml @@ -2,42 +2,63 @@ - + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:layout_marginBottom="12dp" + android:background="@drawable/empty_session_control_background" + android:orientation="vertical" + android:padding="16dp"> + app:fontFamily="@font/metropolis_semibold" + app:layout_constraintEnd_toStartOf="@id/remove_collection_placeholder" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/no_collections_header" /> - + android:visibility="gone" + app:icon="@drawable/ic_tab_collection" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/no_collections_description" /> + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 47bc4e334..6c01291ef 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -172,4 +172,5 @@ 48dp + 16dp diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 6b0042d96..621b377d7 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -195,4 +195,6 @@ pref_key_default_browser pref_key_login_exceptions + + pref_key_show_collections_home diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1f23516b0..cdcd98611 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -725,10 +725,8 @@ Collections Collection menu - - Collect the things that matter to you - Group together similar searches, sites, and tabs for quick access later. + Collect the things that matter to you.\nGroup together similar searches, sites, and tabs for quick access later. Select Tabs @@ -1467,4 +1465,6 @@ OK, Got It + + Remove diff --git a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt index bf63fcce6..8c0b4c6f8 100644 --- a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt @@ -78,8 +78,10 @@ class DefaultSessionControlControllerTest { collections = emptyList(), expandedCollections = emptySet(), mode = Mode.Normal, - topSites = emptyList() + topSites = emptyList(), + showCollectionPlaceholder = true ) + every { sessionManager.sessions } returns emptyList() every { navController.currentDestination } returns mockk { every { id } returns R.id.homeFragment @@ -94,6 +96,7 @@ class DefaultSessionControlControllerTest { controller = DefaultSessionControlController( activity = activity, + settings = settings, engine = engine, metrics = metrics, sessionManager = sessionManager, @@ -414,4 +417,14 @@ class DefaultSessionControlControllerTest { ) } } + + @Test + fun handleRemoveCollectionsPlaceholder() { + controller.handleRemoveCollectionsPlaceholder() + + verify { + settings.showCollectionsPlaceholderOnHome = false + fragmentStore.dispatch(HomeFragmentAction.RemoveCollectionsPlaceholder) + } + } } diff --git a/app/src/test/java/org/mozilla/fenix/home/HomeFragmentStoreTest.kt b/app/src/test/java/org/mozilla/fenix/home/HomeFragmentStoreTest.kt index ed217152f..87baabbb7 100644 --- a/app/src/test/java/org/mozilla/fenix/home/HomeFragmentStoreTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/HomeFragmentStoreTest.kt @@ -12,6 +12,7 @@ import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.top.sites.TopSite import mozilla.components.service.fxa.manager.FxaAccountManager import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test @@ -53,7 +54,8 @@ class HomeFragmentStoreTest { collections = emptyList(), expandedCollections = emptySet(), mode = currentMode.getCurrentMode(), - topSites = emptyList() + topSites = emptyList(), + showCollectionPlaceholder = true ) homeFragmentStore = HomeFragmentStore(homeFragmentState) @@ -95,6 +97,15 @@ class HomeFragmentStoreTest { assertEquals(topSites, homeFragmentStore.state.topSites) } + @Test + fun `Test changing hiding collections placeholder`() = runBlocking { + assertTrue(homeFragmentStore.state.showCollectionPlaceholder) + + homeFragmentStore.dispatch(HomeFragmentAction.RemoveCollectionsPlaceholder).join() + + assertFalse(homeFragmentStore.state.showCollectionPlaceholder) + } + @Test fun `Test changing the expanded collections in HomeFragmentStore`() = runBlocking { val collection: TabCollection = mockk().apply { @@ -110,25 +121,27 @@ class HomeFragmentStoreTest { } @Test - fun `Test changing the collections, mode and top sites in the HomeFragmentStore`() = runBlocking { - // Verify that the default state of the HomeFragment is correct. - assertEquals(0, homeFragmentStore.state.collections.size) - assertEquals(0, homeFragmentStore.state.topSites.size) - assertEquals(Mode.Normal, homeFragmentStore.state.mode) + fun `Test changing the collections, mode and top sites in the HomeFragmentStore`() = + runBlocking { + // Verify that the default state of the HomeFragment is correct. + assertEquals(0, homeFragmentStore.state.collections.size) + assertEquals(0, homeFragmentStore.state.topSites.size) + assertEquals(Mode.Normal, homeFragmentStore.state.mode) - val collections: List = listOf(mockk()) - val topSites: List = listOf(mockk(), mockk()) + val collections: List = listOf(mockk()) + val topSites: List = listOf(mockk(), mockk()) - homeFragmentStore.dispatch( - HomeFragmentAction.Change( - collections = collections, - mode = Mode.Private, - topSites = topSites - ) - ).join() + homeFragmentStore.dispatch( + HomeFragmentAction.Change( + collections = collections, + mode = Mode.Private, + topSites = topSites, + showCollectionPlaceholder = true + ) + ).join() - assertEquals(1, homeFragmentStore.state.collections.size) - assertEquals(Mode.Private, homeFragmentStore.state.mode) - assertEquals(2, homeFragmentStore.state.topSites.size) - } + assertEquals(1, homeFragmentStore.state.collections.size) + assertEquals(Mode.Private, homeFragmentStore.state.mode) + assertEquals(2, homeFragmentStore.state.topSites.size) + } } diff --git a/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt index 63bc74661..6357cf51f 100644 --- a/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/SessionControlInteractorTest.kt @@ -110,4 +110,10 @@ class SessionControlInteractorTest { interactor.onPasteAndGo("text") verify { controller.handlePasteAndGo("text") } } + + @Test + fun onRemoveCollectionsPlaceholder() { + interactor.onRemoveCollectionsPlaceholder() + verify { controller.handleRemoveCollectionsPlaceholder() } + } } diff --git a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolderTest.kt index 54b50341c..643a1e6fd 100644 --- a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoCollectionsMessageViewHolderTest.kt @@ -8,9 +8,13 @@ import android.view.LayoutInflater import android.view.View import androidx.appcompat.view.ContextThemeWrapper import androidx.core.view.isVisible +import androidx.lifecycle.LifecycleOwner import io.mockk.mockk import io.mockk.verify import kotlinx.android.synthetic.main.no_collections_message.view.* +import mozilla.components.browser.state.state.BrowserState +import mozilla.components.browser.state.state.createTab +import mozilla.components.browser.state.store.BrowserStore import mozilla.components.support.test.robolectric.testContext import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -25,6 +29,14 @@ import org.mozilla.fenix.home.sessioncontrol.CollectionInteractor class NoCollectionsMessageViewHolderTest { private lateinit var view: View + private val store: BrowserStore = BrowserStore( + initialState = BrowserState( + listOf( + createTab("https://www.mozilla.org", id = "reader-inactive-tab") + ) + ) + ) + private lateinit var lifecycleOwner: LifecycleOwner private lateinit var interactor: CollectionInteractor @Before @@ -32,28 +44,40 @@ class NoCollectionsMessageViewHolderTest { val appCompatContext = ContextThemeWrapper(testContext, R.style.NormalTheme) view = LayoutInflater.from(appCompatContext) .inflate(NoCollectionsMessageViewHolder.LAYOUT_ID, null) + lifecycleOwner = mockk(relaxed = true) interactor = mockk(relaxed = true) } @Test - fun `hide button when hasNormalTabsOpened is false`() { - NoCollectionsMessageViewHolder(view, interactor, hasNormalTabsOpened = false) + fun `hide add to collection button when there are no tabs open`() { + val noTabsStore = BrowserStore() + NoCollectionsMessageViewHolder(view, lifecycleOwner, noTabsStore, interactor) assertFalse(view.add_tabs_to_collections_button.isVisible) } @Test - fun `show button when hasNormalTabsOpened is true`() { - NoCollectionsMessageViewHolder(view, interactor, hasNormalTabsOpened = true) + fun `show add to collection button when there are tabs`() { + NoCollectionsMessageViewHolder(view, lifecycleOwner, store, interactor) assertTrue(view.add_tabs_to_collections_button.isVisible) } @Test fun `call interactor on click`() { - NoCollectionsMessageViewHolder(view, interactor, hasNormalTabsOpened = true) + NoCollectionsMessageViewHolder(view, lifecycleOwner, store, interactor) view.add_tabs_to_collections_button.performClick() verify { interactor.onAddTabsToCollectionTapped() } } + + @Test + fun `hide view and change setting on remove placeholder click`() { + NoCollectionsMessageViewHolder(view, lifecycleOwner, store, interactor) + + view.remove_collection_placeholder.performClick() + verify { + interactor.onRemoveCollectionsPlaceholder() + } + } } diff --git a/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt b/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt index 6bb0b26b5..6e1e9a51d 100644 --- a/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt +++ b/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt @@ -289,6 +289,19 @@ class SettingsTest { assertFalse(settings.shouldUseTrackingProtection) } + @Test + fun shouldShowCollectionsPlaceholderOnHome() { + // When + // Then + assertTrue(settings.showCollectionsPlaceholderOnHome) + + // When + settings.showCollectionsPlaceholderOnHome = false + + // Then + assertFalse(settings.showCollectionsPlaceholderOnHome) + } + @Test fun shouldSetOpenInAppOpened() { // When