tor-browser

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

commit 7cc59907a56b04393954b3d34a0a8e3d93dab6e0
parent 2ec8b521c73952dd4031eb36369db7ae601936af
Author: rmalicdem <rmalicdem@mozilla.com>
Date:   Tue, 11 Nov 2025 21:29:23 +0000

Bug 1998549 - Support tab previews with simple toolbar customization r=android-reviewers,Roger

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

Diffstat:
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt | 95++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Context.kt | 29+++++++++++++++++++++++++++++
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Fragment.kt | 23++++-------------------
3 files changed, 105 insertions(+), 42 deletions(-)

diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt @@ -48,10 +48,12 @@ import org.mozilla.fenix.components.appstate.OrientationMode import org.mozilla.fenix.components.toolbar.ToolbarPosition import org.mozilla.fenix.databinding.TabPreviewBinding import org.mozilla.fenix.ext.components -import org.mozilla.fenix.ext.isLargeWindow +import org.mozilla.fenix.ext.isTallWindow +import org.mozilla.fenix.ext.isWideWindow import org.mozilla.fenix.ext.settings import org.mozilla.fenix.home.toolbar.BrowserSimpleToolbar import org.mozilla.fenix.search.BrowserToolbarSearchMiddleware +import org.mozilla.fenix.settings.ShortcutType import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.ThemeManager import kotlin.math.min @@ -88,6 +90,8 @@ class TabPreview @JvmOverloads constructor( Bookmark, EditBookmark, Share, + Translate, + Homepage, } private data class ToolbarActionConfig( @@ -215,6 +219,23 @@ class TabPreview @JvmOverloads constructor( ) } } + + ToolbarAction.Translate -> ActionButtonRes( + drawableResId = iconsR.drawable.mozac_ic_translate_24, + contentDescription = R.string.browser_toolbar_translate, + state = if (tab?.translationsState?.isTranslated == true) { + ActionButton.State.ACTIVE + } else { + ActionButton.State.DEFAULT + }, + onClick = object : BrowserToolbarEvent {}, + ) + + ToolbarAction.Homepage -> ActionButtonRes( + drawableResId = iconsR.drawable.mozac_ic_home_24, + contentDescription = R.string.browser_menu_homepage, + onClick = object : BrowserToolbarEvent {}, + ) } } private fun buildSearchEngineSelector(selectedSearchEngine: SearchEngine?): List<Action> { @@ -463,13 +484,13 @@ class TabPreview @JvmOverloads constructor( } private fun buildComposableToolbarPageEndActions(tab: TabSessionState?): List<Action> { - val isLargeWindowOrLandscape = context?.isLargeWindow() == true || - context.components.appStore.state.orientation == OrientationMode.Landscape + val settings = context.settings() + val isWideScreen = context.isWideWindow() + val tabStripEnabled = settings.isTabStripEnabled return listOf( ToolbarActionConfig(ToolbarAction.Share) { - isLargeWindowOrLandscape && !context.settings().isTabStripEnabled && - !context.settings().shouldUseExpandedToolbar + isWideScreen && !tabStripEnabled }, ).filter { config -> config.isVisible() @@ -479,15 +500,12 @@ class TabPreview @JvmOverloads constructor( } private fun buildComposableToolbarBrowserStartActions(tab: TabSessionState?): List<Action> { - val isLargeWindow = context.isLargeWindow() - val isLandscape = context.components.appStore.state.orientation == OrientationMode.Landscape - val shouldNavigationButtonBeVisible = isLargeWindow || - (context.settings().shouldUseExpandedToolbar && isLandscape) + val isWideScreen = context.isWideWindow() return listOf( - ToolbarActionConfig(ToolbarAction.Back) { shouldNavigationButtonBeVisible }, - ToolbarActionConfig(ToolbarAction.Forward) { shouldNavigationButtonBeVisible }, - ToolbarActionConfig(ToolbarAction.RefreshOrStop) { shouldNavigationButtonBeVisible }, + ToolbarActionConfig(ToolbarAction.Back) { isWideScreen }, + ToolbarActionConfig(ToolbarAction.Forward) { isWideScreen }, + ToolbarActionConfig(ToolbarAction.RefreshOrStop) { isWideScreen }, ).filter { config -> config.isVisible() }.map { config -> @@ -495,25 +513,38 @@ class TabPreview @JvmOverloads constructor( } } - private fun buildComposableToolbarBrowserEndActions(tab: TabSessionState?): List<Action> { - val isLargeWindowOrLandscape = context.isLargeWindow() || - context.components.appStore.state.orientation == OrientationMode.Landscape - val isExpandedAndPortrait = context.settings().shouldUseExpandedToolbar && - context.components.appStore.state.orientation == OrientationMode.Portrait + private suspend fun buildComposableToolbarBrowserEndActions(tab: TabSessionState?): List<Action> { + val isBookmarked = tab?.content?.url?.let { url -> + context.components.core.bookmarksStorage + .getBookmarksWithUrl(url) + .getOrDefault(emptyList()) + .isNotEmpty() + } ?: false + + val settings = context.settings() + val isWideWindow = context.isWideWindow() + val isTallWindow = context.isTallWindow() + val tabStripEnabled = settings.isTabStripEnabled + val shouldUseExpandedToolbar = settings.shouldUseExpandedToolbar + + val useCustomPrimary = settings.shouldShowToolbarCustomization && !shouldUseExpandedToolbar + val primarySlotAction = mapShortcutToAction(settings.toolbarSimpleShortcutKey, isBookmarked) + .takeIf { useCustomPrimary } ?: ToolbarAction.NewTab return listOf( - ToolbarActionConfig(ToolbarAction.NewTab) { - !context.settings().isTabStripEnabled && !isExpandedAndPortrait && + ToolbarActionConfig(primarySlotAction) { + !tabStripEnabled && (!shouldUseExpandedToolbar || !isTallWindow || isWideWindow) && tab?.content?.url != ABOUT_HOME_URL }, ToolbarActionConfig(ToolbarAction.TabCounter) { - !context.settings().isTabStripEnabled && !isExpandedAndPortrait + !tabStripEnabled && (!shouldUseExpandedToolbar || !isTallWindow || isWideWindow) }, ToolbarActionConfig(ToolbarAction.Share) { - isLargeWindowOrLandscape && context.settings().isTabStripEnabled && - !context.settings().shouldUseExpandedToolbar + tabStripEnabled && isWideWindow && (!shouldUseExpandedToolbar || !isTallWindow) + }, + ToolbarActionConfig(ToolbarAction.Menu) { + !shouldUseExpandedToolbar || !isTallWindow || isWideWindow }, - ToolbarActionConfig(ToolbarAction.Menu) { !isExpandedAndPortrait }, ).filter { config -> config.isVisible() }.map { config -> @@ -577,4 +608,22 @@ class TabPreview @JvmOverloads constructor( true -> new() false -> old() } + + companion object { + private fun mapShortcutToAction( + key: String, + isBookmarked: Boolean = false, + ): ToolbarAction = when (key) { + ShortcutType.NEW_TAB -> ToolbarAction.NewTab + ShortcutType.SHARE -> ToolbarAction.Share + ShortcutType.BOOKMARK -> when (isBookmarked) { + true -> ToolbarAction.EditBookmark + false -> ToolbarAction.Bookmark + } + ShortcutType.TRANSLATE -> ToolbarAction.Translate + ShortcutType.HOMEPAGE -> ToolbarAction.Homepage + ShortcutType.BACK -> ToolbarAction.Back + else -> ToolbarAction.NewTab + } + } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Context.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Context.kt @@ -167,6 +167,35 @@ fun Context.tabsClosedUndoMessage(private: Boolean): String = */ fun Context.isLargeWindow(): Boolean = AcornWindowSize.isLargeWindow(this) +internal const val TALL_SCREEN_HEIGHT_DP = 480 +internal const val WIDE_SCREEN_WIDTH_DP = 600 + +/** + * Helper function to determine whether the app's current window height + * is at least more than [TALL_SCREEN_HEIGHT_DP]. + * + * This is useful when navigation bar should only be enabled on + * taller screens (e.g., to avoid crowding content vertically). + * + * @return true if the window height size is more than [TALL_SCREEN_HEIGHT_DP]. + */ +fun Context.isTallWindow(): Boolean { + return resources.configuration.screenHeightDp > TALL_SCREEN_HEIGHT_DP +} + +/** + * Helper function to determine whether the app's current window width + * is at least more than [WIDE_SCREEN_WIDTH_DP]. + * + * This is useful when navigation bar should only be enabled on + * wider screens (e.g., to avoid crowding content horizontally). + * + * @return true if the window width size is more than [WIDE_SCREEN_WIDTH_DP]. + */ +fun Context.isWideWindow(): Boolean { + return resources.configuration.screenWidthDp > WIDE_SCREEN_WIDTH_DP +} + /** * This will record an event in the Nimbus internal event store. Used for behavioral targeting. */ diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Fragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/ext/Fragment.kt @@ -233,33 +233,18 @@ fun Fragment.isLargeScreenSize(): Boolean { return requireContext().isLargeScreenSize() } -internal const val TALL_SCREEN_HEIGHT_DP = 480 -internal const val WIDE_SCREEN_WIDTH_DP = 600 - /** - * Helper function to determine whether the app's current window height - * is at least more than [TALL_SCREEN_HEIGHT_DP]. - * - * This is useful when navigation bar should only be enabled on - * taller screens (e.g., to avoid crowding content vertically). - * - * @return true if the window height size is more than [TALL_SCREEN_HEIGHT_DP]. + * Checks whether the app's current window height is at least more than [TALL_SCREEN_HEIGHT_DP]. */ fun Fragment.isTallWindow(): Boolean { - return resources.configuration.screenHeightDp > TALL_SCREEN_HEIGHT_DP + return requireContext().isTallWindow() } /** - * Helper function to determine whether the app's current window width - * is at least more than [WIDE_SCREEN_WIDTH_DP]. - * - * This is useful when navigation bar should only be enabled on - * wider screens (e.g., to avoid crowding content horizontally). - * - * @return true if the window width size is more than [WIDE_SCREEN_WIDTH_DP]. + * Checks whether the app's current window width is at least more than [WIDE_SCREEN_WIDTH_DP]. */ fun Fragment.isWideWindow(): Boolean { - return resources.configuration.screenWidthDp > WIDE_SCREEN_WIDTH_DP + return requireContext().isWideWindow() } /**