From 7d6c0d1eafbd157fd7ec381ed7e970438460d34c Mon Sep 17 00:00:00 2001 From: sarah541 Date: Wed, 10 Aug 2022 15:52:10 -0400 Subject: [PATCH] [fenix] For https://github.com/mozilla-mobile/fenix/issues/26421 - Extract synced tabs into it's own viewholder --- .../java/org/mozilla/fenix/ext/AppState.kt | 8 +++ .../view/RecentSyncedTabViewHolder.kt | 60 +++++++++++++++++++ .../recenttabs/view/RecentTabViewHolder.kt | 25 -------- .../sessioncontrol/SessionControlAdapter.kt | 12 ++++ .../home/sessioncontrol/SessionControlView.kt | 6 ++ app/src/main/res/values/dimens.xml | 1 + .../sessioncontrol/SessionControlViewTest.kt | 11 +++- 7 files changed, 96 insertions(+), 27 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTabViewHolder.kt diff --git a/app/src/main/java/org/mozilla/fenix/ext/AppState.kt b/app/src/main/java/org/mozilla/fenix/ext/AppState.kt index b2d2824dc7..f4a03e6789 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/AppState.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/AppState.kt @@ -183,3 +183,11 @@ fun AppState.shouldShowRecentTabs(settings: Settings): Boolean { val hasTab = recentTabs.isNotEmpty() || recentSyncedTabState is RecentSyncedTabState.Success return settings.showRecentTabsFeature && hasTab } + +/** + * Determines whether a recent synced tab section should be shown, based on user preference + * and the availability of Synced tabs. + */ +fun AppState.shouldShowRecentSyncedTabs(settings: Settings): Boolean { + return (settings.enableTaskContinuityEnhancements && recentSyncedTabState is RecentSyncedTabState.Success) +} diff --git a/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTabViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTabViewHolder.kt new file mode 100644 index 0000000000..d62ac47e62 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/view/RecentSyncedTabViewHolder.kt @@ -0,0 +1,60 @@ +/* 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.recentsyncedtabs.view + +import android.view.View +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.ComposeView +import androidx.lifecycle.LifecycleOwner +import mozilla.components.lib.state.ext.observeAsComposableState +import org.mozilla.fenix.R +import org.mozilla.fenix.components.components +import org.mozilla.fenix.compose.ComposeViewHolder +import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTabState +import org.mozilla.fenix.home.recentsyncedtabs.interactor.RecentSyncedTabInteractor + +/** + * View holder for a recent synced tab item. + * + * @param composeView [ComposeView] which will be populated with Jetpack Compose UI content. + * @param recentSyncedTabInteractor [RecentSyncedTabInteractor] which will have delegated to all + * recent synced tab user interactions. + */ +class RecentSyncedTabViewHolder( + composeView: ComposeView, + viewLifecycleOwner: LifecycleOwner, + private val recentSyncedTabInteractor: RecentSyncedTabInteractor, +) : ComposeViewHolder(composeView, viewLifecycleOwner) { + + init { + val horizontalPadding = + composeView.resources.getDimensionPixelSize(R.dimen.home_item_horizontal_margin) + val verticalPadding = + composeView.resources.getDimensionPixelSize(R.dimen.home_item_vertical_margin) + composeView.setPadding(horizontalPadding, verticalPadding, horizontalPadding, 0) + } + + companion object { + val LAYOUT_ID = View.generateViewId() + } + + @Composable + override fun Content() { + val recentSyncedTabState = + components.appStore.observeAsComposableState { state -> state.recentSyncedTabState } + recentSyncedTabState.value?.let { + val syncedTab = when (it) { + RecentSyncedTabState.None, + RecentSyncedTabState.Loading -> null + is RecentSyncedTabState.Success -> it.tab + } + RecentSyncedTab( + tab = syncedTab, + onRecentSyncedTabClick = recentSyncedTabInteractor::onRecentSyncedTabClicked, + onSeeAllSyncedTabsButtonClick = recentSyncedTabInteractor::onSyncedTabShowAllClicked, + ) + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/home/recenttabs/view/RecentTabViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/recenttabs/view/RecentTabViewHolder.kt index 030a59731a..3458f71171 100644 --- a/app/src/main/java/org/mozilla/fenix/home/recenttabs/view/RecentTabViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/recenttabs/view/RecentTabViewHolder.kt @@ -6,22 +6,15 @@ package org.mozilla.fenix.home.recenttabs.view import android.view.View import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp import androidx.lifecycle.LifecycleOwner import mozilla.components.lib.state.ext.observeAsComposableState import org.mozilla.fenix.R import org.mozilla.fenix.components.components import org.mozilla.fenix.compose.ComposeViewHolder -import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTabState import org.mozilla.fenix.home.recenttabs.interactor.RecentTabInteractor -import org.mozilla.fenix.home.recentsyncedtabs.interactor.RecentSyncedTabInteractor -import org.mozilla.fenix.home.recentsyncedtabs.view.RecentSyncedTab /** * View holder for a recent tab item. @@ -36,7 +29,6 @@ class RecentTabViewHolder( composeView: ComposeView, viewLifecycleOwner: LifecycleOwner, private val recentTabInteractor: RecentTabInteractor, - private val recentSyncedTabInteractor: RecentSyncedTabInteractor, ) : ComposeViewHolder(composeView, viewLifecycleOwner) { init { @@ -52,7 +44,6 @@ class RecentTabViewHolder( @Composable override fun Content() { val recentTabs = components.appStore.observeAsComposableState { state -> state.recentTabs } - val recentSyncedTabState = components.appStore.observeAsComposableState { state -> state.recentSyncedTabState } Column { RecentTabs( @@ -65,22 +56,6 @@ class RecentTabViewHolder( ) ) ) - - recentSyncedTabState.value?.let { - if (components.settings.enableTaskContinuityEnhancements && it is RecentSyncedTabState.Success) { - Spacer(modifier = Modifier.height(8.dp)) - - RecentSyncedTab( - tab = it.tab, - onRecentSyncedTabClick = { tab -> - recentSyncedTabInteractor.onRecentSyncedTabClicked(tab) - }, - onSeeAllSyncedTabsButtonClick = { - recentSyncedTabInteractor.onSyncedTabShowAllClicked() - }, - ) - } - } } } } 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 f21125ca52..5f5c7edfd2 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 @@ -26,6 +26,7 @@ import org.mozilla.fenix.home.pocket.PocketRecommendationsHeaderViewHolder import org.mozilla.fenix.home.pocket.PocketStoriesViewHolder import org.mozilla.fenix.home.recentbookmarks.view.RecentBookmarksHeaderViewHolder import org.mozilla.fenix.home.recentbookmarks.view.RecentBookmarksViewHolder +import org.mozilla.fenix.home.recentsyncedtabs.view.RecentSyncedTabViewHolder import org.mozilla.fenix.home.recenttabs.view.RecentTabViewHolder import org.mozilla.fenix.home.recenttabs.view.RecentTabsHeaderViewHolder import org.mozilla.fenix.home.recentvisits.view.RecentVisitsHeaderViewHolder @@ -168,6 +169,11 @@ sealed class AdapterItem(@LayoutRes val viewType: Int) { object RecentTabsHeader : AdapterItem(RecentTabsHeaderViewHolder.LAYOUT_ID) object RecentTabItem : AdapterItem(RecentTabViewHolder.LAYOUT_ID) + /** + * Adapter item to hold homescreen synced tabs view. + */ + object RecentSyncedTabItem : AdapterItem(RecentSyncedTabViewHolder.LAYOUT_ID) + object RecentVisitsHeader : AdapterItem(RecentVisitsHeaderViewHolder.LAYOUT_ID) object RecentVisitsItems : AdapterItem(RecentlyVisitedViewHolder.LAYOUT_ID) @@ -256,6 +262,10 @@ class SessionControlAdapter( composeView = ComposeView(parent.context), viewLifecycleOwner = viewLifecycleOwner, recentTabInteractor = interactor, + ) + RecentSyncedTabViewHolder.LAYOUT_ID -> return RecentSyncedTabViewHolder( + composeView = ComposeView(parent.context), + viewLifecycleOwner = viewLifecycleOwner, recentSyncedTabInteractor = interactor, ) RecentlyVisitedViewHolder.LAYOUT_ID -> return RecentlyVisitedViewHolder( @@ -338,6 +348,7 @@ class SessionControlAdapter( is RecentBookmarksViewHolder, is RecentBookmarksHeaderViewHolder, is RecentTabViewHolder, + is RecentSyncedTabViewHolder, is RecentTabsHeaderViewHolder, is PrivateBrowsingDescriptionViewHolder, is PocketCategoriesViewHolder, @@ -417,6 +428,7 @@ class SessionControlAdapter( is RecentlyVisitedViewHolder, is RecentBookmarksViewHolder, is RecentTabViewHolder, + is RecentSyncedTabViewHolder, is PocketStoriesViewHolder -> { // no-op. This ViewHolder receives the HomeStore as argument and will observe that // without the need for us to manually update from here the data to be displayed. 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 6221e1ce7a..baac4a035e 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 @@ -15,6 +15,7 @@ import mozilla.components.service.pocket.PocketStory import org.mozilla.fenix.components.appstate.AppState import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings +import org.mozilla.fenix.ext.shouldShowRecentSyncedTabs import org.mozilla.fenix.ext.shouldShowRecentTabs import org.mozilla.fenix.gleanplumb.Message import org.mozilla.fenix.home.Mode @@ -37,6 +38,7 @@ internal fun normalModeAdapterItems( showCollectionsPlaceholder: Boolean, nimbusMessageCard: Message? = null, showRecentTab: Boolean, + showRecentSyncedTab: Boolean, recentVisits: List, pocketStories: List ): List { @@ -58,6 +60,9 @@ internal fun normalModeAdapterItems( shouldShowCustomizeHome = true items.add(AdapterItem.RecentTabsHeader) items.add(AdapterItem.RecentTabItem) + if (showRecentSyncedTab) { + items.add(AdapterItem.RecentSyncedTabItem) + } } if (settings.showRecentBookmarksFeature && recentBookmarks.isNotEmpty()) { @@ -158,6 +163,7 @@ private fun AppState.toAdapterList(settings: Settings): List = when showCollectionPlaceholder, messaging.messageToShow, shouldShowRecentTabs(settings), + shouldShowRecentSyncedTabs(settings), recentHistory, pocketStories ) diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index b87727ea93..5e3e884d9b 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -77,6 +77,7 @@ 60dp 16dp + 8dp diff --git a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/SessionControlViewTest.kt b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/SessionControlViewTest.kt index 8ed4baf402..c8984005a6 100644 --- a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/SessionControlViewTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/SessionControlViewTest.kt @@ -156,8 +156,9 @@ class SessionControlViewTest { false, null, false, - historyMetadata, - pocketStories + showRecentSyncedTab = false, + recentVisits = historyMetadata, + pocketStories = pocketStories ) assertTrue(results[0] is AdapterItem.TopPlaceholderItem) @@ -192,6 +193,7 @@ class SessionControlViewTest { false, nimbusMessageCard, false, + showRecentSyncedTab = false, historyMetadata, pocketStories ) @@ -224,6 +226,7 @@ class SessionControlViewTest { false, null, true, + showRecentSyncedTab = false, historyMetadata, pocketStories ) @@ -259,6 +262,7 @@ class SessionControlViewTest { false, null, false, + showRecentSyncedTab = false, historyMetadata, pocketStories ) @@ -294,6 +298,7 @@ class SessionControlViewTest { false, null, false, + showRecentSyncedTab = false, historyMetadata, pocketStories ) @@ -330,6 +335,7 @@ class SessionControlViewTest { false, null, false, + showRecentSyncedTab = false, historyMetadata, pocketStories ) @@ -365,6 +371,7 @@ class SessionControlViewTest { false, null, true, + showRecentSyncedTab = true, historyMetadata, pocketStories )