commit bdd147ba6aa33bfbccd1e47ababfaeee943ca86a
parent 29ea9091ad03f3a0dd2227729952a313f30f355a
Author: rmalicdem <rmalicdem@mozilla.com>
Date: Tue, 28 Oct 2025 19:58:16 +0000
Bug 1969066 - Add 'Add bookmark' to simple shortcut toolbar customization r=android-reviewers,android-l10n-reviewers,delphine,Roger
Differential Revision: https://phabricator.services.mozilla.com/D270003
Diffstat:
4 files changed, 115 insertions(+), 10 deletions(-)
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddleware.kt
@@ -239,7 +239,9 @@ class BrowserToolbarMiddleware(
updateStartBrowserActions(context)
updateCurrentPageOrigin(context)
- updateEndBrowserActions(context)
+ environment?.fragment?.viewLifecycleOwner?.lifecycleScope?.launch {
+ updateEndBrowserActions(context)
+ }
updateEndPageActions(context)
environment?.fragment?.viewLifecycleOwner?.lifecycleScope?.launch {
updateNavigationActions(context)
@@ -669,12 +671,22 @@ class BrowserToolbarMiddleware(
),
)
- private fun updateEndBrowserActions(context: MiddlewareContext<BrowserToolbarState, BrowserToolbarAction>) =
+ private suspend fun updateEndBrowserActions(context: MiddlewareContext<BrowserToolbarState, BrowserToolbarAction>) {
+ val url = browserStore.state.selectedTab?.content?.url
+ val isBookmarked = if (url != null) {
+ withContext(ioDispatcher) {
+ bookmarksStorage.getBookmarksWithUrl(url).getOrDefault(listOf()).isNotEmpty()
+ }
+ } else {
+ false
+ }
+
context.dispatch(
BrowserActionsEndUpdated(
- buildEndBrowserActions(),
+ buildEndBrowserActions(isBookmarked),
),
- )
+ )
+ }
private fun buildStartPageActions(): List<Action> {
return listOf(
@@ -738,14 +750,16 @@ class BrowserToolbarMiddleware(
}
}
- private fun buildEndBrowserActions(): List<Action> {
+ private fun buildEndBrowserActions(isBookmarked: Boolean): List<Action> {
val isWideWindow = environment?.fragment?.isWideWindow() == true
val isTallWindow = environment?.fragment?.isTallWindow() == true
val tabStripEnabled = settings.isTabStripEnabled
val shouldUseExpandedToolbar = settings.shouldUseExpandedToolbar
val useCustomPrimary = settings.shouldShowToolbarCustomization && !shouldUseExpandedToolbar
- val primarySlotAction = mapShortcutToAction(settings.toolbarShortcutKey)
- .takeIf { useCustomPrimary } ?: ToolbarAction.NewTab
+ val primarySlotAction = mapShortcutToAction(
+ settings.toolbarShortcutKey,
+ isBookmarked,
+ ).takeIf { useCustomPrimary } ?: ToolbarAction.NewTab
val configs = listOf(
ToolbarActionConfig(primarySlotAction) {
@@ -1032,6 +1046,7 @@ class BrowserToolbarMiddleware(
it.snackbarState is SnackbarState.BookmarkAdded ||
it.snackbarState is SnackbarState.BookmarkDeleted
}.collect { isBookmarked ->
+ updateEndBrowserActions(context)
updateNavigationActions(context)
}
}
@@ -1249,9 +1264,16 @@ class BrowserToolbarMiddleware(
companion object {
@VisibleForTesting
@JvmStatic
- internal fun mapShortcutToAction(key: String): ToolbarAction = when (key) {
+ internal fun mapShortcutToAction(
+ key: String,
+ isBookmarked: Boolean = false,
+ ): ToolbarAction = when (key) {
ToolbarShortcutPreference.Keys.NEW_TAB -> ToolbarAction.NewTab
ToolbarShortcutPreference.Keys.SHARE -> ToolbarAction.Share
+ ToolbarShortcutPreference.Keys.BOOKMARK -> when (isBookmarked) {
+ true -> ToolbarAction.EditBookmark
+ false -> ToolbarAction.Bookmark
+ }
else -> ToolbarAction.NewTab
}
}
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarShortcutPreference.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/ToolbarShortcutPreference.kt
@@ -39,8 +39,21 @@ class ToolbarShortcutPreference @JvmOverloads constructor(
private val options: List<Option> by lazy {
listOf(
- Option(Keys.NEW_TAB, iconsR.drawable.mozac_ic_plus_24, R.string.home_screen_shortcut_open_new_tab_2),
- Option(Keys.SHARE, iconsR.drawable.mozac_ic_share_android_24, R.string.browser_menu_share),
+ Option(
+ Keys.NEW_TAB,
+ iconsR.drawable.mozac_ic_plus_24,
+ R.string.toolbar_customize_shortcut_new_tab,
+ ),
+ Option(
+ Keys.SHARE,
+ iconsR.drawable.mozac_ic_share_android_24,
+ R.string.toolbar_customize_shortcut_share,
+ ),
+ Option(
+ Keys.BOOKMARK,
+ iconsR.drawable.mozac_ic_bookmark_24,
+ R.string.toolbar_customize_shortcut_add_bookmark,
+ ),
)
}
@@ -171,5 +184,6 @@ class ToolbarShortcutPreference @JvmOverloads constructor(
object Keys {
const val NEW_TAB = "new_tab"
const val SHARE = "share"
+ const val BOOKMARK = "bookmark"
}
}
diff --git a/mobile/android/fenix/app/src/main/res/values/strings.xml b/mobile/android/fenix/app/src/main/res/values/strings.xml
@@ -1138,6 +1138,13 @@
<!-- Preference description indicating the toolbar location preference is disabled when the tab strip is enabled -->
<string name="preference_toolbar_pref_disabled_explanation">Address bar must be on top when tab bar is shown.</string>
+ <!-- New tab shortcut in toolbar customization -->
+ <string name="toolbar_customize_shortcut_new_tab">Open a new tab</string>
+ <!-- Share shortcut in toolbar customization -->
+ <string name="toolbar_customize_shortcut_share">Share</string>
+ <!-- Add bookmark shortcut in toolbar customization -->
+ <string name="toolbar_customize_shortcut_add_bookmark">Add bookmark</string>
+
<!-- App icon Preferences -->
<!-- Title for the preference that lets the user pick a new app icon -->
<string name="preference_select_app_icon_title">Select App Icon</string>
diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddlewareTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMiddlewareTest.kt
@@ -943,6 +943,8 @@ class BrowserToolbarMiddlewareTest {
navController = navController,
browsingModeManager = browsingModeManager,
)
+ mainLooperRule.idle()
+
val tabCounterButton = toolbarStore.state.displayState.browserActionsEnd[1] as TabCounterAction
assertEqualsTabCounterButton(expectedTabCounterButton(2, true), tabCounterButton)
val tabCounterMenuItems = (tabCounterButton.onLongClick as CombinedEventAndMenu).menu.items()
@@ -979,6 +981,8 @@ class BrowserToolbarMiddlewareTest {
navController = navController,
browsingModeManager = browsingModeManager,
)
+ mainLooperRule.idle()
+
val tabCounterButton = toolbarStore.state.displayState.browserActionsEnd[1] as TabCounterAction
assertEqualsTabCounterButton(expectedTabCounterButton(1, false), tabCounterButton)
val tabCounterMenuItems = (tabCounterButton.onLongClick as CombinedEventAndMenu).menu.items()
@@ -1021,6 +1025,8 @@ class BrowserToolbarMiddlewareTest {
navController = navController,
browsingModeManager = browsingModeManager,
)
+ mainLooperRule.idle()
+
val tabCounterButton = toolbarStore.state.displayState.browserActionsEnd[1] as TabCounterAction
assertEqualsTabCounterButton(expectedTabCounterButton(1, true), tabCounterButton)
val tabCounterMenuItems = (tabCounterButton.onLongClick as CombinedEventAndMenu).menu.items()
@@ -1067,6 +1073,8 @@ class BrowserToolbarMiddlewareTest {
navController = navController,
browsingModeManager = browsingModeManager,
)
+ mainLooperRule.idle()
+
val tabCounterButton = toolbarStore.state.displayState.browserActionsEnd[1] as TabCounterAction
assertEqualsTabCounterButton(expectedTabCounterButton(1, true), tabCounterButton)
val tabCounterMenuItems = (tabCounterButton.onLongClick as CombinedEventAndMenu).menu.items()
@@ -1119,6 +1127,8 @@ class BrowserToolbarMiddlewareTest {
navController = navController,
browsingModeManager = browsingModeManager,
)
+ mainLooperRule.idle()
+
val tabCounterButton = toolbarStore.state.displayState.browserActionsEnd[1] as TabCounterAction
assertEqualsTabCounterButton(expectedTabCounterButton(1, true), tabCounterButton)
val tabCounterMenuItems = (tabCounterButton.onLongClick as CombinedEventAndMenu).menu.items()
@@ -1460,6 +1470,7 @@ class BrowserToolbarMiddlewareTest {
browsingModeManager = browsingModeManager,
navController = navController,
)
+ mainLooperRule.idle()
val shareButton = toolbarStore.state.displayState.browserActionsEnd[0] as ActionButtonRes
assertEquals(expectedShareButton(), shareButton)
@@ -1497,6 +1508,7 @@ class BrowserToolbarMiddlewareTest {
browsingModeManager = browsingModeManager,
navController = navController,
)
+ mainLooperRule.idle()
val shareButton = toolbarStore.state.displayState.browserActionsEnd[0] as ActionButtonRes
assertEquals(expectedShareButton(), shareButton)
@@ -2737,6 +2749,45 @@ class BrowserToolbarMiddlewareTest {
}
@Test
+ fun `GIVEN simple toolbar use add bookmark shortcut AND the current page is not bookmarked WHEN initializing toolbar THEN show Bookmark in end browser actions`() = runTest {
+ every { settings.shouldShowToolbarCustomization } returns true
+ every { settings.toolbarShortcutKey } returns ToolbarShortcutPreference.Keys.BOOKMARK
+ val toolbarStore = buildStore()
+
+ val bookmarkButton = toolbarStore.state.displayState.browserActionsEnd[0] as ActionButtonRes
+ assertEquals(expectedBookmarkButton(Source.AddressBar), bookmarkButton)
+ }
+
+ @Test
+ fun `GIVEN simple toolbar use add bookmark shortcut AND the current page is bookmarked WHEN initializing toolbar THEN show ACTIVE EditBookmark in end browser actions`() = runTest {
+ every { settings.shouldShowToolbarCustomization } returns true
+ every { settings.toolbarShortcutKey } returns ToolbarShortcutPreference.Keys.BOOKMARK
+
+ val tab = createTab("https://example.com")
+ val browserStore = BrowserStore(
+ BrowserState(
+ tabs = listOf(tab),
+ selectedTabId = tab.id,
+ ),
+ )
+
+ coEvery { bookmarksStorage.getBookmarksWithUrl(tab.content.url) } returns Result.success(
+ listOf(mockk(relaxed = true)),
+ )
+
+ val middleware = buildMiddleware(
+ browserStore = browserStore,
+ bookmarksStorage = bookmarksStorage,
+ )
+
+ val toolbarStore = buildStore(middleware)
+ mainLooperRule.idle()
+
+ val editButton = toolbarStore.state.displayState.browserActionsEnd [0] as ActionButtonRes
+ assertEquals(expectedEditBookmarkButton(Source.AddressBar), editButton)
+ }
+
+ @Test
fun `mapShortcutToAction maps keys to actions and falls back to NewTab`() {
assertEquals(
ToolbarAction.NewTab,
@@ -2747,6 +2798,17 @@ class BrowserToolbarMiddlewareTest {
BrowserToolbarMiddleware.mapShortcutToAction(ToolbarShortcutPreference.Keys.SHARE),
)
assertEquals(
+ ToolbarAction.Bookmark,
+ BrowserToolbarMiddleware.mapShortcutToAction(ToolbarShortcutPreference.Keys.BOOKMARK),
+ )
+ assertEquals(
+ ToolbarAction.EditBookmark,
+ BrowserToolbarMiddleware.mapShortcutToAction(
+ ToolbarShortcutPreference.Keys.BOOKMARK,
+ true,
+ ),
+ )
+ assertEquals(
ToolbarAction.NewTab,
BrowserToolbarMiddleware.mapShortcutToAction("does_not_exist"),
)