Bug 1878827 - Add nav buttons click handling

fenix/125.0
mike a 2 months ago committed by mergify[bot]
parent f56de3bb73
commit f03a6a7215

@ -21,6 +21,8 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.CallSuper
import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AlertDialog
import androidx.compose.foundation.layout.Column
import androidx.compose.ui.viewinterop.AndroidView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
@ -137,11 +139,14 @@ import org.mozilla.fenix.components.toolbar.DefaultBrowserToolbarController
import org.mozilla.fenix.components.toolbar.DefaultBrowserToolbarMenuController
import org.mozilla.fenix.components.toolbar.IncompleteRedesignToolbarFeature
import org.mozilla.fenix.components.toolbar.ToolbarIntegration
import org.mozilla.fenix.components.toolbar.ToolbarMenu
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.components.toolbar.interactor.BrowserToolbarInteractor
import org.mozilla.fenix.components.toolbar.interactor.DefaultBrowserToolbarInteractor
import org.mozilla.fenix.components.toolbar.navbar.BottomToolbarContainerView
import org.mozilla.fenix.components.toolbar.navbar.BrowserNavBar
import org.mozilla.fenix.components.toolbar.navbar.NavbarIntegration
import org.mozilla.fenix.compose.Divider
import org.mozilla.fenix.crashes.CrashContentIntegration
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
import org.mozilla.fenix.databinding.FragmentBrowserBinding
@ -170,6 +175,7 @@ import org.mozilla.fenix.settings.SupportUtils
import org.mozilla.fenix.settings.biometric.BiometricPromptFeature
import org.mozilla.fenix.tabstray.Page
import org.mozilla.fenix.tabstray.ext.toDisplayTitle
import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.allowUndo
import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration
@ -461,6 +467,7 @@ abstract class BaseBrowserFragment :
// We need a second menu button, but we could reuse the existing builder.
val menuButton = MenuButton(requireContext()).apply {
menuBuilder = browserToolbarView.menuToolbar.menuBuilder
// We have to set colorFilter manually as the button isn't being managed by a [BrowserToolbarView].
setColorFilter(
ContextCompat.getColor(
context,
@ -472,9 +479,63 @@ abstract class BaseBrowserFragment :
_bottomToolbarContainerView = BottomToolbarContainerView(
context = context,
parent = binding.browserLayout,
androidToolbarView = if (isToolbarAtBottom) browserToolbar else null,
menuButton = menuButton,
isPrivateMode = activity.browsingModeManager.mode.isPrivate,
composableContent = {
FirefoxTheme {
Column {
if (isToolbarAtBottom) {
AndroidView(factory = { _ -> browserToolbar })
} else {
Divider()
}
BrowserNavBar(
isPrivateMode = activity.browsingModeManager.mode.isPrivate,
browserStore = context.components.core.store,
onBackButtonClick = {
browserToolbarInteractor.onBrowserToolbarMenuItemTapped(
ToolbarMenu.Item.Back(viewHistory = false),
)
},
onBackButtonLongPress = {
browserToolbarInteractor.onBrowserToolbarMenuItemTapped(
ToolbarMenu.Item.Back(viewHistory = true),
)
},
onForwardButtonClick = {
browserToolbarInteractor.onBrowserToolbarMenuItemTapped(
ToolbarMenu.Item.Forward(viewHistory = false),
)
},
onForwardButtonLongPress = {
browserToolbarInteractor.onBrowserToolbarMenuItemTapped(
ToolbarMenu.Item.Forward(viewHistory = true),
)
},
onHomeButtonClick = {
Events.browserToolbarHomeTapped.record(NoExtras())
browserAnimator.captureEngineViewAndDrawStatically {
findNavController().navigate(
BrowserFragmentDirections.actionGlobalHome(),
)
}
},
menuButton = menuButton,
onTabsButtonClick = {
thumbnailsFeature.get()?.requestScreenshot()
findNavController().nav(
R.id.browserFragment,
BrowserFragmentDirections.actionGlobalTabsTrayFragment(
page = when (activity.browsingModeManager.mode) {
BrowsingMode.Normal -> Page.NormalTabs
BrowsingMode.Private -> Page.PrivateTabs
},
),
)
},
)
}
}
},
)
navbarIntegration.set(

@ -10,6 +10,8 @@ import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.content.res.AppCompatResources
import androidx.compose.foundation.layout.Column
import androidx.compose.ui.viewinterop.AndroidView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.doOnNextLayout
import androidx.core.view.isVisible
@ -23,9 +25,12 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.components.toolbar.IncompleteRedesignToolbarFeature
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.components.toolbar.navbar.BottomToolbarContainerView
import org.mozilla.fenix.components.toolbar.navbar.BrowserNavBar
import org.mozilla.fenix.compose.Divider
import org.mozilla.fenix.databinding.TabPreviewBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.theme.ThemeManager
import kotlin.math.min
@ -61,12 +66,47 @@ class TabPreview @JvmOverloads constructor(
binding.menuButton.isVisible = !isNavBarEnabled
if (isNavBarEnabled) {
val browserStore = context.components.core.store
BottomToolbarContainerView(
context = context,
parent = this,
androidToolbarView = if (!isToolbarAtTop) binding.fakeToolbar else null,
menuButton = MenuButton(context),
composableContent = {
FirefoxTheme {
Column {
if (!isToolbarAtTop) {
AndroidView(factory = { _ -> binding.fakeToolbar })
} else {
Divider()
}
BrowserNavBar(
isPrivateMode = browserStore.state.selectedTab?.content?.private ?: false,
browserStore = browserStore,
onBackButtonClick = {
// no-op
},
onBackButtonLongPress = {
// no-op
},
onForwardButtonClick = {
// no-op
},
onForwardButtonLongPress = {
// no-op
},
onHomeButtonClick = {
// no-op
},
menuButton = MenuButton(context),
onTabsButtonClick = {
// no-op
},
)
}
}
},
)
removeView(binding.fakeToolbar)
}

@ -7,44 +7,26 @@ package org.mozilla.fenix.components.toolbar.navbar
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.viewinterop.AndroidView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import mozilla.components.browser.menu.view.MenuButton
import mozilla.components.browser.state.selector.normalTabs
import mozilla.components.browser.state.selector.privateTabs
import mozilla.components.concept.toolbar.ScrollableToolbar
import mozilla.components.lib.state.ext.observeAsState
import mozilla.components.ui.widgets.behavior.EngineViewScrollingBehavior
import mozilla.components.ui.widgets.behavior.ViewPosition
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.compose.Divider
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.theme.FirefoxTheme
/**
* A helper class to add NavigationBar composable to a [ViewGroup].
*
* @param context The Context the view is running in.
* @param parent The ViewGroup into which the NavigationBar composable will be added.
* @param navigationItems A list of [ActionItem] objects representing the items to be displayed in the navigation bar.
* @param androidToolbarView An option toolbar view that will be added atop of the navigation bar.
* @param menuButton A [MenuButton] to be used for [ItemType.MENU].
* @param isPrivateMode If browsing in [BrowsingMode.Private].
*
* Defaults to [NavigationItems.defaultItems] which provides a standard set of navigation items.
* @param composableContent
*/
class BottomToolbarContainerView(
context: Context,
parent: ViewGroup,
navigationItems: List<ActionItem> = NavigationItems.defaultItems,
androidToolbarView: View? = null,
menuButton: MenuButton,
isPrivateMode: Boolean = false,
composableContent: @Composable () -> Unit,
) {
val toolbarContainerView = ToolbarContainerView(context)
@ -53,29 +35,7 @@ class BottomToolbarContainerView(
init {
composeView = ComposeView(context).apply {
setContent {
val tabCount = context.components.core.store.observeAsState(initialValue = 0) { browserState ->
if (isPrivateMode) {
browserState.privateTabs.size
} else {
browserState.normalTabs.size
}
}.value
FirefoxTheme {
Column {
if (androidToolbarView != null) {
AndroidView(factory = { _ -> androidToolbarView })
} else {
Divider()
}
NavigationBar(
actionItems = navigationItems,
tabCount = tabCount,
menuButton = menuButton,
)
}
}
composableContent()
}
toolbarContainerView.addView(this)

@ -6,8 +6,8 @@ package org.mozilla.fenix.components.toolbar.navbar
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@ -17,166 +17,337 @@ import androidx.compose.material.IconButton
import androidx.compose.material.LocalContentColor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import mozilla.components.browser.menu.view.MenuButton
import mozilla.components.browser.state.selector.normalTabs
import mozilla.components.browser.state.selector.privateTabs
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.lib.state.ext.observeAsState
import org.mozilla.fenix.R
import org.mozilla.fenix.components.toolbar.navbar.ItemType.STANDARD
import org.mozilla.fenix.components.toolbar.navbar.ItemType.TAB_COUNTER
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.compose.LongPressIconButton
import org.mozilla.fenix.compose.TabCounter
import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.search.SearchDialogFragment
import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.theme.Theme
import org.mozilla.fenix.theme.ThemeManager
/**
* Top-level UI for displaying the navigation bar.
*
* @param actionItems A list of [ActionItem] used to populate the bar.
* @param tabCount The number of opened tabs.
* @param menuButton A [MenuButton] to be used for [ItemType.MENU].
* @param isPrivateMode If browsing in [BrowsingMode.Private].
* @param browserStore The [BrowserStore] instance used to observe tabs state.
* @param menuButton A [MenuButton] to be used as an [AndroidView]. The view implementation
* contains the builder for the menu, so for the time being we are not implementing it as a composable.
* @param onBackButtonClick Invoked when the user clicks the back button in the nav bar.
* @param onBackButtonLongPress Invoked when the user long-presses the back button in the nav bar.
* @param onForwardButtonClick Invoked when the user clicks the forward button in the nav bar.
* @param onForwardButtonLongPress Invoked when the user long-presses the forward button in the nav bar.
* @param onHomeButtonClick Invoked when the user clicks the home button in the nav bar.
* @param onTabsButtonClick Invoked when the user clicks the tabs button in the nav bar.
*/
@Suppress("LongParameterList")
@Composable
fun NavigationBar(
actionItems: List<ActionItem>,
tabCount: Int,
menuButton: MenuButton? = null,
fun BrowserNavBar(
isPrivateMode: Boolean,
browserStore: BrowserStore,
menuButton: MenuButton,
onBackButtonClick: () -> Unit,
onBackButtonLongPress: () -> Unit,
onForwardButtonClick: () -> Unit,
onForwardButtonLongPress: () -> Unit,
onHomeButtonClick: () -> Unit,
onTabsButtonClick: () -> Unit,
) {
Box(
modifier = Modifier
.background(FirefoxTheme.colors.layer1)
.height(48.dp)
.fillMaxWidth(),
) {
Row(
modifier = Modifier
.align(Alignment.Center)
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
) {
actionItems.forEach {
when (it.type) {
ItemType.STANDARD -> {
IconButton(onClick = {}) {
Icon(
painter = painterResource(it.iconId),
stringResource(id = it.descriptionResourceId),
tint = FirefoxTheme.colors.iconPrimary,
)
}
}
ItemType.TAB_COUNTER -> {
CompositionLocalProvider(LocalContentColor provides FirefoxTheme.colors.iconPrimary) {
IconButton(onClick = {}) {
TabCounter(tabCount = tabCount)
}
}
}
ItemType.MENU -> {
// [ActionItem] will be refactored here:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1878827
if (menuButton != null) {
AndroidView(
modifier = Modifier.size(48.dp),
factory = { _ -> menuButton },
)
} else {
IconButton(onClick = {}) {
Icon(
painter = painterResource(it.iconId),
stringResource(id = it.descriptionResourceId),
tint = FirefoxTheme.colors.iconPrimary,
)
}
}
}
}
}
val tabCount = browserStore.observeAsState(initialValue = 0) { browserState ->
if (isPrivateMode) {
browserState.privateTabs.size
} else {
browserState.normalTabs.size
}
}.value
NavBar {
BackButton(
onBackButtonClick = onBackButtonClick,
onBackButtonLongPress = onBackButtonLongPress,
)
ForwardButton(
onForwardButtonClick = onForwardButtonClick,
onForwardButtonLongPress = onForwardButtonLongPress,
)
HomeButton(
onHomeButtonClick = onHomeButtonClick,
)
TabsButton(
onTabsButtonClick = onTabsButtonClick,
tabCount = tabCount,
)
MenuButton(menuButton = menuButton)
}
}
/**
* Represents a navigation bar element.
* Top-level UI for displaying the navigation bar.
*
* @property iconId Resource ID of the icon that item should display.
* @property descriptionResourceId Text used as a content description by accessibility services.
* @property type Type of the item, defaults to [ItemType.STANDARD].
* @param isPrivateMode If browsing in [BrowsingMode.Private].
* @param browserStore The [BrowserStore] instance used to observe tabs state.
* @param menuButton A [MenuButton] to be used as an [AndroidView]. The view implementation
* contains the builder for the menu, so for the time being we are not implementing it as a composable.
* @param onSearchButtonClick Invoked when the user clicks the search button in the nav bar. The button
* is visible only on home screen and activates [SearchDialogFragment].
* @param onTabsButtonClick Invoked when the user clicks the tabs button in the nav bar.
*/
data class ActionItem(
val iconId: Int,
val descriptionResourceId: Int,
val type: ItemType = ItemType.STANDARD,
)
@Composable
fun HomeNavBar(
isPrivateMode: Boolean,
browserStore: BrowserStore,
menuButton: MenuButton,
onSearchButtonClick: () -> Unit,
onTabsButtonClick: () -> Unit,
) {
val tabCount = browserStore.observeAsState(initialValue = 0) { browserState ->
if (isPrivateMode) {
browserState.privateTabs.size
} else {
browserState.normalTabs.size
}
}.value
/**
* Enumerates the types of items that can be used in a navigation bar.
*
* [STANDARD] - Represents a regular navigation item. Used for most navigation actions.
* [TAB_COUNTER] - Represents a specialized item used to display a count, such as the number of open tabs in a browser.
*/
enum class ItemType {
STANDARD, TAB_COUNTER, MENU
NavBar {
BackButton(
onBackButtonClick = {
// no-op
},
onBackButtonLongPress = {
// no-op
},
)
ForwardButton(
onForwardButtonClick = {
// no-op
},
onForwardButtonLongPress = {
// no-op
},
)
SearchWebButton(
onSearchButtonClick = onSearchButtonClick,
)
TabsButton(
onTabsButtonClick = onTabsButtonClick,
tabCount = tabCount,
)
MenuButton(menuButton = menuButton)
}
}
/**
* Provides a collection of navigation items used in the application's navigation bar.
*/
object NavigationItems {
val home = ActionItem(
iconId = R.drawable.mozac_ic_home_24,
descriptionResourceId = R.string.browser_toolbar_home,
@Composable
private fun NavBar(
content: @Composable RowScope.() -> Unit,
) {
Row(
modifier = Modifier
.background(FirefoxTheme.colors.layer1)
.height(48.dp)
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
content = content,
)
}
val menu = ActionItem(
iconId = R.drawable.mozac_ic_ellipsis_vertical_24,
descriptionResourceId = R.string.mozac_browser_menu_button,
type = ItemType.MENU,
)
@Composable
private fun BackButton(
onBackButtonClick: () -> Unit,
onBackButtonLongPress: () -> Unit,
) {
LongPressIconButton(
onClick = onBackButtonClick,
onLongClick = onBackButtonLongPress,
) {
Icon(
painter = painterResource(R.drawable.mozac_ic_back_24),
stringResource(id = R.string.browser_menu_back),
tint = FirefoxTheme.colors.iconPrimary,
)
}
}
@Composable
private fun ForwardButton(
onForwardButtonClick: () -> Unit,
onForwardButtonLongPress: () -> Unit,
) {
LongPressIconButton(
onClick = onForwardButtonClick,
onLongClick = onForwardButtonLongPress,
) {
Icon(
painter = painterResource(R.drawable.mozac_ic_forward_24),
stringResource(id = R.string.browser_menu_forward),
tint = FirefoxTheme.colors.iconPrimary,
)
}
}
val back = ActionItem(
iconId = R.drawable.mozac_ic_back_24,
descriptionResourceId = R.string.browser_menu_back,
@Composable
private fun HomeButton(
onHomeButtonClick: () -> Unit,
) {
IconButton(
onClick = onHomeButtonClick,
) {
Icon(
painter = painterResource(R.drawable.mozac_ic_home_24),
stringResource(id = R.string.browser_toolbar_home),
tint = FirefoxTheme.colors.iconPrimary,
)
}
}
@Composable
private fun SearchWebButton(
onSearchButtonClick: () -> Unit,
) {
IconButton(
onClick = onSearchButtonClick,
) {
Icon(
painter = painterResource(R.drawable.mozac_ic_search_24),
stringResource(id = R.string.search_hint),
tint = FirefoxTheme.colors.iconPrimary,
)
}
}
@Composable
private fun MenuButton(
menuButton: MenuButton,
) {
// Should refactor it to be a simple IconButton with a click listener
// once the redesigned menu is implemented.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1884049
AndroidView(
modifier = Modifier.size(48.dp),
factory = { _ -> menuButton },
)
}
@Composable
private fun TabsButton(
onTabsButtonClick: () -> Unit,
tabCount: Int,
) {
CompositionLocalProvider(LocalContentColor provides FirefoxTheme.colors.iconPrimary) {
IconButton(onClick = { onTabsButtonClick() }) {
TabCounter(tabCount = tabCount)
}
}
}
val forward = ActionItem(
iconId = R.drawable.mozac_ic_forward_24,
descriptionResourceId = R.string.browser_menu_forward,
@Composable
private fun HomeNavBarPreviewRoot(isPrivateMode: Boolean) {
val context = LocalContext.current
val colorId = if (isPrivateMode) {
// private mode preview keeps using black colour as textPrimary
ThemeManager.resolveAttribute(R.attr.textOnColorPrimary, context)
} else {
ThemeManager.resolveAttribute(R.attr.textPrimary, context)
}
val menuButton = MenuButton(context).apply {
setColorFilter(
ContextCompat.getColor(
context,
colorId,
),
)
}
HomeNavBar(
onSearchButtonClick = {},
menuButton = menuButton,
onTabsButtonClick = {},
isPrivateMode = false,
browserStore = BrowserStore(),
)
}
val tabs = ActionItem(
iconId = R.drawable.mozac_ui_tabcounter_box,
descriptionResourceId = R.string.mozac_tab_counter_content_description,
type = TAB_COUNTER,
@Composable
private fun OpenTabNavBarNavBarPreviewRoot(isPrivateMode: Boolean) {
val context = LocalContext.current
val colorId = if (isPrivateMode) {
// private mode preview keeps using black colour as textPrimary
ThemeManager.resolveAttribute(R.attr.textOnColorPrimary, context)
} else {
ThemeManager.resolveAttribute(R.attr.textPrimary, context)
}
val menuButton = MenuButton(context).apply {
setColorFilter(
ContextCompat.getColor(
context,
colorId,
),
)
}
BrowserNavBar(
onBackButtonClick = {},
onBackButtonLongPress = {},
onForwardButtonClick = {},
onForwardButtonLongPress = {},
onHomeButtonClick = {},
menuButton = menuButton,
onTabsButtonClick = {},
isPrivateMode = false,
browserStore = BrowserStore(),
)
}
val defaultItems = listOf(back, forward, home, tabs, menu)
@LightDarkPreview
@Composable
private fun HomeNavBarPreview() {
FirefoxTheme {
HomeNavBarPreviewRoot(isPrivateMode = false)
}
}
@Preview
@Composable
private fun HomeNavBarPrivatePreview() {
FirefoxTheme(theme = Theme.Private) {
HomeNavBarPreviewRoot(isPrivateMode = true)
}
}
@LightDarkPreview
@Composable
private fun NavigationBarPreview() {
private fun OpenTabNavBarPreview() {
FirefoxTheme {
NavigationBar(
actionItems = NavigationItems.defaultItems,
tabCount = 0,
)
OpenTabNavBarNavBarPreviewRoot(isPrivateMode = false)
}
}
@Preview
@Composable
private fun NavigationBarPrivatePreview() {
private fun OpenTabNavBarPrivatePreview() {
FirefoxTheme(theme = Theme.Private) {
NavigationBar(
actionItems = NavigationItems.defaultItems,
tabCount = 0,
)
OpenTabNavBarNavBarPreviewRoot(isPrivateMode = true)
}
}

@ -0,0 +1,56 @@
/* 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
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.material.ContentAlpha
import androidx.compose.material.IconButton
import androidx.compose.material.LocalContentAlpha
import androidx.compose.material.minimumInteractiveComponentSize
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp
/**
* An [IconButton] that supports a long press gesture.
*/
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun LongPressIconButton(
onClick: () -> Unit,
onLongClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable () -> Unit,
) {
Box(
modifier = modifier
.minimumInteractiveComponentSize()
.combinedClickable(
onClick = onClick,
onLongClick = onLongClick,
enabled = enabled,
role = Role.Button,
interactionSource = interactionSource,
indication = rememberRipple(bounded = false, radius = RippleRadius),
),
contentAlignment = Alignment.Center,
) {
val contentAlpha = if (enabled) LocalContentAlpha.current else ContentAlpha.disabled
CompositionLocalProvider(LocalContentAlpha provides contentAlpha, content = content)
}
}
private val RippleRadius = 24.dp

@ -14,6 +14,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
@ -29,6 +30,7 @@ import androidx.compose.ui.semantics.testTag
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getColor
@ -81,12 +83,16 @@ import mozilla.components.service.glean.private.NoExtras
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import mozilla.components.ui.colors.PhotonColors
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.GleanMetrics.Events
import org.mozilla.fenix.GleanMetrics.HomeScreen
import org.mozilla.fenix.GleanMetrics.Homepage
import org.mozilla.fenix.GleanMetrics.PrivateBrowsingShortcutCfr
import org.mozilla.fenix.GleanMetrics.StartOnHome
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
import org.mozilla.fenix.addons.showSnackBar
import org.mozilla.fenix.browser.BrowserAnimator
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.tabstrip.TabStrip
import org.mozilla.fenix.components.FenixSnackbar
@ -96,7 +102,9 @@ import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.toolbar.IncompleteRedesignToolbarFeature
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.components.toolbar.navbar.BottomToolbarContainerView
import org.mozilla.fenix.components.toolbar.navbar.HomeNavBar
import org.mozilla.fenix.components.toolbar.navbar.NavbarIntegration
import org.mozilla.fenix.compose.Divider
import org.mozilla.fenix.databinding.FragmentHomeBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.containsQueryParameters
@ -131,6 +139,7 @@ import org.mozilla.fenix.nimbus.FxNimbus
import org.mozilla.fenix.perf.MarkersFragmentLifecycleCallbacks
import org.mozilla.fenix.search.toolbar.DefaultSearchSelectorController
import org.mozilla.fenix.search.toolbar.SearchSelectorMenu
import org.mozilla.fenix.tabstray.Page
import org.mozilla.fenix.tabstray.TabsTrayAccessPoint
import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD
@ -466,9 +475,49 @@ class HomeFragment : Fragment() {
_bottomToolbarContainerView = BottomToolbarContainerView(
context = requireContext(),
parent = binding.homeLayout,
androidToolbarView = if (isToolbarAtBottom) binding.toolbarLayout else null,
menuButton = menuButton,
isPrivateMode = activity.browsingModeManager.mode.isPrivate,
composableContent = {
FirefoxTheme {
Column {
if (isToolbarAtBottom) {
AndroidView(factory = { _ -> binding.toolbarLayout })
} else {
Divider()
}
HomeNavBar(
isPrivateMode = activity.browsingModeManager.mode.isPrivate,
browserStore = requireContext().components.core.store,
onSearchButtonClick = {
val directions =
NavGraphDirections.actionGlobalSearchDialog(
sessionId = null,
)
findNavController().nav(
findNavController().currentDestination?.id,
directions,
BrowserAnimator.getToolbarNavOptions(activity),
)
Events.searchBarTapped.record(Events.SearchBarTappedExtra("HOME"))
},
menuButton = menuButton,
onTabsButtonClick = {
StartOnHome.openTabsTray.record(NoExtras())
findNavController().nav(
findNavController().currentDestination?.id,
NavGraphDirections.actionGlobalTabsTrayFragment(
page = when (browsingModeManager.mode) {
BrowsingMode.Normal -> Page.NormalTabs
BrowsingMode.Private -> Page.PrivateTabs
},
),
)
},
)
}
}
},
)
navbarIntegration.set(

Loading…
Cancel
Save