tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 24f55b8044c6eeee335ee5d738a32af57553dab0
parent d2cc7af77543c2e0fc3a80a7b5e9dfe063f7da02
Author: Matthew Tighe <matthewdtighe@gmail.com>
Date:   Wed, 19 Nov 2025 19:34:57 +0000

Bug 1999547 - use wallpaper text color for the homepage header items r=android-reviewers,sfamisa,devota

Differential Revision: https://phabricator.services.mozilla.com/D272166

Diffstat:
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/store/HomepageState.kt | 52+++++++++++++++++++++++++++++++++++++++++++---------
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/ui/Homepage.kt | 47++++++++++++++++++++++++++++++++++++++++++-----
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/ui/HomepageHeader.kt | 32++++++++++++++++++++++++++------
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/ui/MiddleSearchHomepage.kt | 13++++++++++++-
4 files changed, 123 insertions(+), 21 deletions(-)

diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/store/HomepageState.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/store/HomepageState.kt @@ -8,7 +8,9 @@ import android.content.res.Configuration import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.res.colorResource import mozilla.components.feature.top.sites.TopSite +import mozilla.components.ui.icons.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager import org.mozilla.fenix.components.appstate.AppState @@ -25,6 +27,7 @@ import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTabState import org.mozilla.fenix.home.recenttabs.RecentTab import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem import org.mozilla.fenix.home.topsites.TopSiteColors +import org.mozilla.fenix.home.ui.getAttr import org.mozilla.fenix.search.SearchDialogFragment import org.mozilla.fenix.utils.Settings @@ -34,9 +37,9 @@ import org.mozilla.fenix.utils.Settings internal sealed class HomepageState { /** - * Whether to show the homepage header. + * Data related to the header of the homepage. */ - abstract val showHeader: Boolean + abstract val headerState: HeaderState /** * Flag indicating whether the first frame of the homescreen has been drawn. @@ -51,13 +54,13 @@ internal sealed class HomepageState { /** * State type corresponding with private browsing mode. * - * @property showHeader Whether to show the homepage header. + * @property headerState State related to the header of the homepage. * @property firstFrameDrawn Flag indicating whether the first frame of the homescreen has been drawn. * @property isSearchInProgress Whether search is currently active on the homepage. * @property privateModeRedesignEnabled Whether private browsing mode redesign is enabled. */ internal data class Private( - override val showHeader: Boolean, + override val headerState: HeaderState, override val firstFrameDrawn: Boolean = false, override val isSearchInProgress: Boolean, val privateModeRedesignEnabled: Boolean, @@ -81,7 +84,7 @@ internal sealed class HomepageState { * @property showRecentlyVisited Whether to show recent history section. * @property showPocketStories Whether to show the pocket stories section. * @property showCollections Whether to show the collections section. - * @property showHeader Whether to show the homepage header. + * @property headerState State related to the header of the homepage. * @property searchBarVisible Whether the middle search bar should be visible or not. * @property searchBarEnabled Whether the middle search bar is enabled or not. * @property firstFrameDrawn Flag indicating whether the first frame of the homescreen has been drawn. @@ -109,7 +112,7 @@ internal sealed class HomepageState { val showRecentlyVisited: Boolean, val showPocketStories: Boolean, val showCollections: Boolean, - override val showHeader: Boolean, + override val headerState: HeaderState, val searchBarVisible: Boolean, val searchBarEnabled: Boolean, override val firstFrameDrawn: Boolean = false, @@ -136,7 +139,7 @@ internal sealed class HomepageState { internal fun isMinimalLayout(): Boolean { return (this as? Normal)?.run { !showRecentTabs && !showRecentSyncedTab && !showBookmarks && !showRecentlyVisited && - (!showCollections || collectionsState == CollectionsState.Gone) && !showHeader + (!showCollections || collectionsState == CollectionsState.Gone) && !headerState.showHeader } ?: false } @@ -179,12 +182,21 @@ internal sealed class HomepageState { * @param appState State to build the [HomepageState.Private] from. * @param settings [Settings] corresponding to how the homepage should be displayed. */ + @Composable private fun buildPrivateState( appState: AppState, settings: Settings, ) = with(appState) { Private( - showHeader = settings.showHomepageHeader, + headerState = HeaderState( + showHeader = settings.showHomepageHeader, + wordmarkColor = null, + privateBrowsingButtonColor = colorResource( + getAttr( + R.attr.mozac_ic_private_mode_circle_fill_icon_color, + ), + ), + ), firstFrameDrawn = firstFrameDrawn, isSearchInProgress = searchState.isSearchActive, privateModeRedesignEnabled = settings.enablePrivateBrowsingModeRedesign, @@ -231,7 +243,16 @@ internal sealed class HomepageState { showPocketStories = settings.showPocketRecommendationsFeature && recommendationState.pocketStories.isNotEmpty(), showCollections = settings.collections, - showHeader = settings.showHomepageHeader, + headerState = HeaderState( + showHeader = settings.showHomepageHeader, + wordmarkColor = wallpaperState.currentWallpaper.textColor?.let { Color(it) }, + privateBrowsingButtonColor = wallpaperState.currentWallpaper.textColor + ?.let { Color(it) } ?: colorResource( + getAttr( + R.attr.mozac_ic_private_mode_circle_fill_icon_color, + ), + ), + ), searchBarVisible = shouldShowSearchBar(appState = appState), searchBarEnabled = settings.enableHomepageSearchBar && settings.toolbarPosition == ToolbarPosition.TOP && @@ -254,6 +275,19 @@ internal sealed class HomepageState { } /** + * A simple wrapper around state required for the homepage header. + * + * @property showHeader whether the header should be shown + * @property wordmarkColor an optional color for the wordmark text and logo + * @property privateBrowsingButtonColor the color to use for the private browsing button + */ +internal data class HeaderState( + val showHeader: Boolean, + val wordmarkColor: Color?, + val privateBrowsingButtonColor: Color, +) + +/** * Returns whether the search bar should be shown. Only show if the search dialog * [SearchDialogFragment] is not visible, and the user does not have their toolbar set to be on the * bottom, and the screen is not in landscape mode. This is in addition to logic in the view layer diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/ui/Homepage.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/ui/Homepage.kt @@ -23,6 +23,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics @@ -64,6 +65,7 @@ import org.mozilla.fenix.home.recentvisits.view.RecentlyVisited import org.mozilla.fenix.home.sessioncontrol.CollectionInteractor import org.mozilla.fenix.home.sessioncontrol.MessageCardInteractor import org.mozilla.fenix.home.setup.ui.SetupChecklist +import org.mozilla.fenix.home.store.HeaderState import org.mozilla.fenix.home.store.HomepageState import org.mozilla.fenix.home.store.NimbusMessageState import org.mozilla.fenix.home.topsites.TopSiteColors @@ -74,6 +76,7 @@ import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.Theme import org.mozilla.fenix.utils.isLargeScreenSize import org.mozilla.fenix.wallpapers.WallpaperState +import mozilla.components.ui.icons.R as iconsR /** * Top level composable for the homepage. @@ -114,8 +117,10 @@ internal fun Homepage( .verticalScroll(scrollState), horizontalAlignment = Alignment.CenterHorizontally, ) { - if (state.showHeader) { + if (state.headerState.showHeader) { HomepageHeader( + wordmarkColor = state.headerState.wordmarkColor, + privateBrowsingButtonColor = state.headerState.privateBrowsingButtonColor, browsingMode = state.browsingMode, browsingModeChanged = interactor::onPrivateModeButtonClicked, ) @@ -479,7 +484,15 @@ private fun HomepagePreview() { showRecentlyVisited = true, showPocketStories = true, showCollections = true, - showHeader = false, + headerState = HeaderState( + showHeader = false, + wordmarkColor = null, + privateBrowsingButtonColor = colorResource( + getAttr( + iconsR.attr.mozac_ic_private_mode_circle_fill_icon_color, + ), + ), + ), searchBarVisible = true, searchBarEnabled = false, firstFrameDrawn = true, @@ -521,7 +534,15 @@ private fun HomepagePreviewCollections() { showRecentlyVisited = true, showPocketStories = true, showCollections = true, - showHeader = false, + headerState = HeaderState( + showHeader = false, + wordmarkColor = null, + privateBrowsingButtonColor = colorResource( + getAttr( + iconsR.attr.mozac_ic_private_mode_circle_fill_icon_color, + ), + ), + ), searchBarVisible = true, searchBarEnabled = false, firstFrameDrawn = true, @@ -563,7 +584,15 @@ private fun MinimalHomepagePreview() { showRecentlyVisited = false, showPocketStories = true, showCollections = false, - showHeader = false, + HeaderState( + showHeader = false, + wordmarkColor = null, + privateBrowsingButtonColor = colorResource( + getAttr( + iconsR.attr.mozac_ic_private_mode_circle_fill_icon_color, + ), + ), + ), searchBarVisible = false, searchBarEnabled = false, firstFrameDrawn = true, @@ -590,7 +619,15 @@ private fun PrivateHomepagePreview() { FirefoxTheme(theme = Theme.Private) { Homepage( state = HomepageState.Private( - showHeader = false, + headerState = HeaderState( + showHeader = false, + wordmarkColor = null, + privateBrowsingButtonColor = colorResource( + getAttr( + iconsR.attr.mozac_ic_private_mode_circle_fill_icon_color, + ), + ), + ), firstFrameDrawn = true, isSearchInProgress = false, privateModeRedesignEnabled = false, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/ui/HomepageHeader.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/ui/HomepageHeader.kt @@ -20,6 +20,8 @@ import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource @@ -45,6 +47,8 @@ import mozilla.components.ui.icons.R as iconsR */ @Composable fun HomepageHeader( + wordmarkColor: Color?, + privateBrowsingButtonColor: Color, browsingMode: BrowsingMode, browsingModeChanged: (BrowsingMode) -> Unit, ) { @@ -55,13 +59,14 @@ fun HomepageHeader( .padding(start = 16.dp, end = 16.dp, top = 18.dp, bottom = 32.dp), verticalAlignment = Alignment.CenterVertically, ) { - WordmarkLogo() + WordmarkLogo(wordmarkColor) - WordmarkText() + WordmarkText(wordmarkColor) Spacer(modifier = Modifier.weight(1f)) PrivateBrowsingButton( + color = privateBrowsingButtonColor, browsingMode = browsingMode, browsingModeChanged = browsingModeChanged, ) @@ -69,7 +74,7 @@ fun HomepageHeader( } @Composable -private fun WordmarkLogo() { +private fun WordmarkLogo(color: Color?) { Image( modifier = Modifier .height(40.dp) @@ -79,12 +84,13 @@ private fun WordmarkLogo() { } .padding(end = 10.dp), painter = painterResource(getAttr(R.attr.fenixWordmarkLogo)), + colorFilter = color?.let { ColorFilter.tint(it) }, contentDescription = null, ) } @Composable -private fun WordmarkText() { +private fun WordmarkText(color: Color?) { Image( modifier = Modifier .semantics { @@ -93,12 +99,14 @@ private fun WordmarkText() { } .height(dimensionResource(R.dimen.wordmark_text_height)), painter = painterResource(getAttr(R.attr.fenixWordmarkText)), + colorFilter = color?.let { ColorFilter.tint(it) }, contentDescription = stringResource(R.string.app_name), ) } @Composable private fun PrivateBrowsingButton( + color: Color, browsingMode: BrowsingMode, browsingModeChanged: (BrowsingMode) -> Unit, ) { @@ -119,7 +127,7 @@ private fun PrivateBrowsingButton( }, ) { Icon( - tint = colorResource(getAttr(iconsR.attr.mozac_ic_private_mode_circle_fill_icon_color)), + tint = color, painter = painterResource(iconsR.drawable.mozac_ic_private_mode_24), contentDescription = stringResource(R.string.content_description_private_browsing), ) @@ -127,7 +135,7 @@ private fun PrivateBrowsingButton( } @Composable -private fun getAttr(resId: Int): Int { +internal fun getAttr(resId: Int): Int { val typedArray = LocalContext.current.obtainStyledAttributes(intArrayOf(resId)) val newResId = typedArray.getResourceId(0, 0) typedArray.recycle() @@ -141,6 +149,12 @@ private fun HomepageHeaderPreview() { FirefoxTheme { Surface { HomepageHeader( + wordmarkColor = null, + privateBrowsingButtonColor = colorResource( + getAttr( + iconsR.attr.mozac_ic_private_mode_circle_fill_icon_color, + ), + ), browsingMode = BrowsingMode.Normal, browsingModeChanged = {}, ) @@ -154,6 +168,12 @@ private fun PrivateHomepageHeaderPreview() { FirefoxTheme(theme = Theme.Private) { Surface { HomepageHeader( + wordmarkColor = null, + privateBrowsingButtonColor = colorResource( + getAttr( + iconsR.attr.mozac_ic_private_mode_circle_fill_icon_color, + ), + ), browsingMode = BrowsingMode.Private, browsingModeChanged = {}, ) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/ui/MiddleSearchHomepage.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/ui/MiddleSearchHomepage.kt @@ -21,14 +21,17 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.res.colorResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTag import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp +import mozilla.components.ui.icons.R import org.mozilla.fenix.home.fake.FakeHomepagePreview import org.mozilla.fenix.home.interactor.HomepageInteractor import org.mozilla.fenix.home.pocket.ui.PocketSection +import org.mozilla.fenix.home.store.HeaderState import org.mozilla.fenix.home.store.HomepageState import org.mozilla.fenix.home.topsites.TopSiteColors import org.mozilla.fenix.home.ui.HomepageTestTag.HOMEPAGE @@ -174,7 +177,15 @@ private fun MiddleSearchHomepagePreview() { showRecentlyVisited = true, showPocketStories = true, showCollections = true, - showHeader = false, + headerState = HeaderState( + showHeader = false, + wordmarkColor = null, + privateBrowsingButtonColor = colorResource( + getAttr( + R.attr.mozac_ic_private_mode_circle_fill_icon_color, + ), + ), + ), searchBarVisible = true, searchBarEnabled = true, firstFrameDrawn = true,