From 2040233814de67244e93ca3498ef15da6c51943b Mon Sep 17 00:00:00 2001 From: sarah541 Date: Fri, 25 Mar 2022 12:25:23 -0400 Subject: [PATCH] [fenix] For https://github.com/mozilla-mobile/fenix/issues/23970 - Migrate homescreen recent visits header to compose --- .experimenter.json | 24 +++--- .../fenix/compose/list/HomeSectionHeader.kt | 73 +++++++++++++++++++ .../view/RecentVisitsHeaderViewHolder.kt | 42 +++++++++-- .../sessioncontrol/SessionControlAdapter.kt | 10 ++- .../main/res/layout/recent_visits_header.xml | 43 ----------- .../view/RecentVisitsHeaderViewHolderTest.kt | 38 ---------- 6 files changed, 125 insertions(+), 105 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/compose/list/HomeSectionHeader.kt delete mode 100644 app/src/main/res/layout/recent_visits_header.xml delete mode 100644 app/src/test/java/org/mozilla/fenix/home/recentvisits/view/RecentVisitsHeaderViewHolderTest.kt diff --git a/.experimenter.json b/.experimenter.json index 9321f9c7a..9cf56a058 100644 --- a/.experimenter.json +++ b/.experimenter.json @@ -5,8 +5,8 @@ "exposureDescription": "", "variables": { "message-location": { - "type": "string", - "description": "Where is the message to be put." + "description": "Where is the message to be put.", + "type": "string" } } }, @@ -16,8 +16,8 @@ "exposureDescription": "", "variables": { "sections-enabled": { - "type": "json", - "description": "This property provides a lookup table of whether or not the given section should be enabled. If the section is enabled, it should be toggleable in the settings screen, and on by default." + "description": "This property provides a lookup table of whether or not the given section should be enabled. If the section is enabled, it should be toggleable in the settings screen, and on by default.", + "type": "json" } } }, @@ -54,16 +54,16 @@ "exposureDescription": "", "variables": { "settings-icon": { - "type": "string", - "description": "The drawable displayed in the app menu for Settings" + "description": "The drawable displayed in the app menu for Settings", + "type": "string" }, "settings-punctuation": { - "type": "string", - "description": "The emoji displayed in the Settings screen title." + "description": "The emoji displayed in the Settings screen title.", + "type": "string" }, "settings-title": { - "type": "string", - "description": "The title of displayed in the Settings screen and app menu." + "description": "The title of displayed in the Settings screen and app menu.", + "type": "string" } } }, @@ -73,8 +73,8 @@ "exposureDescription": "", "variables": { "enabled": { - "type": "boolean", - "description": "If true, the feature shows up on the homescreen and on the new tab screen." + "description": "If true, the feature shows up on the homescreen and on the new tab screen.", + "type": "boolean" } } } diff --git a/app/src/main/java/org/mozilla/fenix/compose/list/HomeSectionHeader.kt b/app/src/main/java/org/mozilla/fenix/compose/list/HomeSectionHeader.kt new file mode 100644 index 000000000..540cbc01d --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/compose/list/HomeSectionHeader.kt @@ -0,0 +1,73 @@ +/* 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.compose.home + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.text.ClickableText +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.sp +import org.mozilla.fenix.R +import org.mozilla.fenix.compose.SectionHeader +import org.mozilla.fenix.theme.FirefoxTheme + +/** + * Homepage header. + * + * @param text The header string. + * @param description The description for click action + * @param onShowAllButtonClick Invoked when "Show all" button is clicked. + */ +@Composable +fun HomeSectionHeader( + text: String, + description: String, + onShowAllClick: () -> Unit = {} +) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + SectionHeader( + text = text, + modifier = Modifier + .weight(1f) + .wrapContentHeight(align = Alignment.Top) + ) + + ClickableText( + text = AnnotatedString(text = stringResource(id = R.string.recent_tabs_show_all)), + modifier = Modifier.semantics { + contentDescription = description + }, + style = TextStyle( + color = FirefoxTheme.colors.textAccent, + fontSize = 14.sp + ), + onClick = { onShowAllClick() } + ) + } +} + +@Composable +@Preview +private fun HomeSectionsHeaderPreview() { + FirefoxTheme { + HomeSectionHeader( + stringResource(R.string.recent_bookmarks_title), + stringResource(id = R.string.recently_saved_show_all_content_description_2), + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/mozilla/fenix/home/recentvisits/view/RecentVisitsHeaderViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/recentvisits/view/RecentVisitsHeaderViewHolder.kt index 67b536d68..1595690bd 100644 --- a/app/src/main/java/org/mozilla/fenix/home/recentvisits/view/RecentVisitsHeaderViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/recentvisits/view/RecentVisitsHeaderViewHolder.kt @@ -5,10 +5,21 @@ package org.mozilla.fenix.home.recentvisits.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.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.lifecycle.LifecycleOwner import org.mozilla.fenix.R -import org.mozilla.fenix.databinding.RecentVisitsHeaderBinding +import org.mozilla.fenix.compose.ComposeViewHolder +import org.mozilla.fenix.compose.home.HomeSectionHeader import org.mozilla.fenix.home.recentvisits.interactor.RecentVisitsInteractor -import org.mozilla.fenix.utils.view.ViewHolder +import org.mozilla.fenix.theme.FirefoxTheme /** * View holder for the "Recent visits" section header with the "Show all" button. @@ -17,18 +28,33 @@ import org.mozilla.fenix.utils.view.ViewHolder * interactions. */ class RecentVisitsHeaderViewHolder( - view: View, + composeView: ComposeView, + viewLifecycleOwner: LifecycleOwner, private val interactor: RecentVisitsInteractor -) : ViewHolder(view) { +) : ComposeViewHolder(composeView, viewLifecycleOwner) { init { - val binding = RecentVisitsHeaderBinding.bind(view) - binding.showAllButton.setOnClickListener { - interactor.onHistoryShowAllClicked() + val horizontalPadding = + composeView.resources.getDimensionPixelSize(R.dimen.home_item_horizontal_margin) + composeView.setPadding(horizontalPadding, 0, horizontalPadding, 0) + } + + @Composable + override fun Content() { + Column { + Spacer(modifier = Modifier.height(40.dp)) + + HomeSectionHeader( + text = stringResource(R.string.history_metadata_header_2), + description = stringResource(R.string.past_explorations_show_all_content_description_2), + onShowAllClick = interactor::onHistoryShowAllClicked, + ) + + Spacer(Modifier.height(16.dp)) } } companion object { - const val LAYOUT_ID = R.layout.recent_visits_header + val LAYOUT_ID = View.generateViewId() } } 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 8740fa007..dde0f7a56 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 @@ -251,6 +251,11 @@ class SessionControlAdapter( interactor = interactor, metrics = components.analytics.metrics ) + RecentVisitsHeaderViewHolder.LAYOUT_ID -> return RecentVisitsHeaderViewHolder( + composeView = ComposeView(parent.context), + viewLifecycleOwner, + interactor + ) } val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false) @@ -292,10 +297,6 @@ class SessionControlAdapter( MessageCardViewHolder.LAYOUT_ID -> MessageCardViewHolder(view, interactor) RecentTabsHeaderViewHolder.LAYOUT_ID -> RecentTabsHeaderViewHolder(view, interactor) RecentBookmarksHeaderViewHolder.LAYOUT_ID -> RecentBookmarksHeaderViewHolder(view, interactor) - RecentVisitsHeaderViewHolder.LAYOUT_ID -> RecentVisitsHeaderViewHolder( - view, - interactor - ) BottomSpacerViewHolder.LAYOUT_ID -> BottomSpacerViewHolder(view) else -> throw IllegalStateException() } @@ -305,6 +306,7 @@ class SessionControlAdapter( when (holder) { is CustomizeHomeButtonViewHolder, is RecentlyVisitedViewHolder, + is RecentVisitsHeaderViewHolder, is RecentBookmarksViewHolder, is RecentTabViewHolder, is PocketCategoriesViewHolder, diff --git a/app/src/main/res/layout/recent_visits_header.xml b/app/src/main/res/layout/recent_visits_header.xml deleted file mode 100644 index bfb02ee53..000000000 --- a/app/src/main/res/layout/recent_visits_header.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - diff --git a/app/src/test/java/org/mozilla/fenix/home/recentvisits/view/RecentVisitsHeaderViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/home/recentvisits/view/RecentVisitsHeaderViewHolderTest.kt deleted file mode 100644 index 669f5658c..000000000 --- a/app/src/test/java/org/mozilla/fenix/home/recentvisits/view/RecentVisitsHeaderViewHolderTest.kt +++ /dev/null @@ -1,38 +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.home.recentvisits.view - -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.RecentVisitsHeaderBinding -import org.mozilla.fenix.helpers.FenixRobolectricTestRunner -import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor - -@RunWith(FenixRobolectricTestRunner::class) -class RecentVisitsHeaderViewHolderTest { - - private lateinit var binding: RecentVisitsHeaderBinding - private lateinit var interactor: SessionControlInteractor - - @Before - fun setup() { - binding = RecentVisitsHeaderBinding.inflate(LayoutInflater.from(testContext)) - interactor = mockk(relaxed = true) - } - - @Test - fun `WHEN show all button is clicked THEN interactor is called`() { - RecentVisitsHeaderViewHolder(binding.root, interactor) - - binding.showAllButton.performClick() - - verify { interactor.onHistoryShowAllClicked() } - } -}