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:
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()
}
/**