Skip to content
This repository has been archived by the owner on Jun 17, 2024. It is now read-only.

Commit

Permalink
Bug 1879370 - Add a ClippingBehavior supporting multiple toolbars
Browse files Browse the repository at this point in the history
  • Loading branch information
mike a committed Mar 12, 2024
1 parent 0bbdec6 commit f0510fd
Show file tree
Hide file tree
Showing 13 changed files with 558 additions and 47 deletions.
1 change: 1 addition & 0 deletions fenix/.buildconfig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ projects:
- support-rusthttp
- support-rustlog
- support-test
- support-test-fakes
- support-test-libstate
- support-utils
- support-webextensions
Expand Down
1 change: 1 addition & 0 deletions fenix/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ dependencies {
implementation project(':lib-push-firebase')
implementation project(':lib-state')
implementation project(':lib-dataprotect')
testImplementation project(':support-test-fakes')

debugImplementation ComponentsDependencies.leakcanary
debugImplementation ComponentsDependencies.androidx_compose_ui_tooling
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ abstract class AddonPopupBaseFragment : Fragment(), EngineSession.Observer, User
tryAgain = downloadsFeature.get()!!::tryAgain,
onCannotOpenFile = onCannotOpenFile,
binding = getDownloadDialogLayoutBinding(),
toolbarHeight = 0,
bottomToolbarHeight = 0,
) {}.show()
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ import mozilla.components.support.ktx.android.view.hideKeyboard
import mozilla.components.support.ktx.kotlin.getOrigin
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
import mozilla.components.support.locale.ActivityContextWrapper
import mozilla.components.ui.widgets.behavior.EngineViewClippingBehavior
import mozilla.components.ui.widgets.withCenterAlignedButtons
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.FeatureFlags
Expand All @@ -138,9 +137,12 @@ 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.ToolbarPosition
import org.mozilla.fenix.components.toolbar.getBottomToolbarHeight
import org.mozilla.fenix.components.toolbar.getTopToolbarHeight
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.EngineViewClippingBehavior
import org.mozilla.fenix.components.toolbar.navbar.NavbarIntegration
import org.mozilla.fenix.crashes.CrashContentIntegration
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
Expand Down Expand Up @@ -175,7 +177,6 @@ import org.mozilla.fenix.utils.allowUndo
import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration
import java.lang.ref.WeakReference
import kotlin.coroutines.cancellation.CancellationException
import mozilla.components.ui.widgets.behavior.ToolbarPosition as MozacToolbarPosition

/**
* Base fragment extended by [BrowserFragment].
Expand Down Expand Up @@ -357,8 +358,6 @@ abstract class BaseBrowserFragment :
val store = context.components.core.store
val activity = requireActivity() as HomeActivity

val toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height)

browserAnimator = BrowserAnimator(
fragment = WeakReference(this),
engineView = WeakReference(binding.engineView),
Expand Down Expand Up @@ -469,12 +468,15 @@ abstract class BaseBrowserFragment :
)
}

val shouldHideOnScroll =
!context.settings().shouldUseFixedTopToolbar && context.settings().isDynamicToolbarEnabled
_bottomToolbarContainerView = BottomToolbarContainerView(
context = context,
parent = binding.browserLayout,
androidToolbarView = if (isToolbarAtBottom) browserToolbar else null,
menuButton = menuButton,
isPrivateMode = activity.browsingModeManager.mode.isPrivate,
hideOnScroll = shouldHideOnScroll,
)

navbarIntegration.set(
Expand Down Expand Up @@ -637,6 +639,8 @@ abstract class BaseBrowserFragment :
},
)

val bottomToolbarHeight = context.getBottomToolbarHeight()

downloadFeature.onDownloadStopped = { downloadState, _, downloadJobStatus ->
val onCannotOpenFile: (DownloadState) -> Unit = {
FenixSnackbar.make(
Expand Down Expand Up @@ -671,7 +675,7 @@ abstract class BaseBrowserFragment :
tryAgain = downloadFeature::tryAgain,
onCannotOpenFile = onCannotOpenFile,
binding = binding.viewDynamicDownloadDialog,
toolbarHeight = toolbarHeight,
bottomToolbarHeight = bottomToolbarHeight,
) {
sharedViewModel.downloadDialogState.remove(downloadState.sessionId)
}.show()
Expand All @@ -684,7 +688,7 @@ abstract class BaseBrowserFragment :
getCurrentTab()?.id,
store,
context,
toolbarHeight,
bottomToolbarHeight,
)

shareDownloadsFeature.set(
Expand Down Expand Up @@ -1017,7 +1021,11 @@ abstract class BaseBrowserFragment :
owner = this,
view = view,
)
initializeEngineView(toolbarHeight)

initializeEngineView(
topToolbarHeight = context.getTopToolbarHeight(),
bottomToolbarHeight = bottomToolbarHeight,
)
}

protected fun showUndoSnackbar(message: String) {
Expand Down Expand Up @@ -1153,7 +1161,7 @@ abstract class BaseBrowserFragment :
sessionId: String?,
store: BrowserStore,
context: Context,
toolbarHeight: Int,
bottomToolbarHeight: Int,
) {
val savedDownloadState =
sharedViewModel.downloadDialogState[sessionId]
Expand Down Expand Up @@ -1191,7 +1199,7 @@ abstract class BaseBrowserFragment :
.show()
},
binding = binding.viewDynamicDownloadDialog,
toolbarHeight = toolbarHeight,
bottomToolbarHeight = bottomToolbarHeight,
onDismiss = onDismiss,
).show()

Expand All @@ -1206,36 +1214,31 @@ abstract class BaseBrowserFragment :
}

@VisibleForTesting
internal fun initializeEngineView(toolbarHeight: Int) {
internal fun initializeEngineView(
topToolbarHeight: Int,
bottomToolbarHeight: Int,
) {
val context = requireContext()

if (!context.settings().shouldUseFixedTopToolbar && context.settings().isDynamicToolbarEnabled) {
getEngineView().setDynamicToolbarMaxHeight(toolbarHeight)
getEngineView().setDynamicToolbarMaxHeight(topToolbarHeight + bottomToolbarHeight)

val toolbarPosition = when (context.settings().toolbarPosition) {
ToolbarPosition.BOTTOM -> MozacToolbarPosition.BOTTOM
ToolbarPosition.TOP -> MozacToolbarPosition.TOP
}
(getSwipeRefreshLayout().layoutParams as CoordinatorLayout.LayoutParams).behavior =
EngineViewClippingBehavior(
context,
null,
getSwipeRefreshLayout(),
toolbarHeight,
toolbarPosition,
context = context,
attrs = null,
engineViewParent = getSwipeRefreshLayout(),
topToolbarHeight = topToolbarHeight,
hasTopToolbar = !requireComponents.settings.shouldUseBottomToolbar,
)
} else {
// Ensure webpage's bottom elements are aligned to the very bottom of the engineView.
getEngineView().setDynamicToolbarMaxHeight(0)

// Effectively place the engineView on top/below of the toolbar if that is not dynamic.
val swipeRefreshParams =
getSwipeRefreshLayout().layoutParams as CoordinatorLayout.LayoutParams
if (context.settings().toolbarPosition == ToolbarPosition.TOP) {
swipeRefreshParams.topMargin = toolbarHeight
} else {
swipeRefreshParams.bottomMargin = toolbarHeight
}
// Effectively place the engineView on top/below of the toolbars if that is not dynamic.
val swipeRefreshParams = getSwipeRefreshLayout().layoutParams as CoordinatorLayout.LayoutParams
swipeRefreshParams.topMargin = topToolbarHeight
swipeRefreshParams.bottomMargin = bottomToolbarHeight
}
}

Expand Down Expand Up @@ -1313,9 +1316,9 @@ abstract class BaseBrowserFragment :
fullScreenChanged(false)
browserToolbarView.expand()

val toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height)
val context = requireContext()
resumeDownloadDialogState(selectedTab.id, context.components.core.store, context, toolbarHeight)
val bottomToolbarHeight = context.getBottomToolbarHeight()
resumeDownloadDialogState(selectedTab.id, context.components.core.store, context, bottomToolbarHeight)
it.announceForAccessibility(selectedTab.toDisplayTitle())
}
} else {
Expand Down Expand Up @@ -1638,8 +1641,10 @@ abstract class BaseBrowserFragment :
}
if (webAppToolbarShouldBeVisible) {
browserToolbarView.view.isVisible = true
val toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height)
initializeEngineView(toolbarHeight)
initializeEngineView(
topToolbarHeight = requireContext().getTopToolbarHeight(),
bottomToolbarHeight = requireContext().getBottomToolbarHeight(),
)
browserToolbarView.expand()
}
if (customTabSessionId == null && requireContext().settings().isTabletAndTabStripEnabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

package org.mozilla.fenix.components.toolbar

import android.content.Context
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.utils.Settings

/**
Expand Down Expand Up @@ -40,3 +43,37 @@ class IncompleteRedesignToolbarFeature(
override val isEnabled: Boolean
get() = settings.enableIncompleteToolbarRedesign
}

/**
* Returns the height of the bottom toolbar.
*
* The bottom toolbar can consist of a navigation bar,
* a combination of a navigation and address bar, or be absent.
*/
fun Context.getBottomToolbarHeight(): Int {
val isNavBarEnabled = IncompleteRedesignToolbarFeature(settings()).isEnabled
val isToolbarAtBottom = settings().shouldUseBottomToolbar
val toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height)
val navbarHeight = resources.getDimensionPixelSize(R.dimen.browser_navbar_height)

return when {
isNavBarEnabled && isToolbarAtBottom -> toolbarHeight + navbarHeight
isNavBarEnabled -> navbarHeight
isToolbarAtBottom -> toolbarHeight
else -> 0
}
}

/**
* Returns the height of the top toolbar.
*/
fun Context.getTopToolbarHeight(): Int {
val isToolbarAtTop = !settings().shouldUseBottomToolbar
val toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height)

return if (isToolbarAtTop) {
toolbarHeight
} else {
0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.mozilla.fenix.theme.FirefoxTheme
* @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].
* @param hideOnScroll If the container should react to the [EngineView] content being scrolled.
*
* Defaults to [NavigationItems.defaultItems] which provides a standard set of navigation items.
*/
Expand All @@ -45,6 +46,7 @@ class BottomToolbarContainerView(
androidToolbarView: View? = null,
menuButton: MenuButton,
isPrivateMode: Boolean = false,
hideOnScroll: Boolean = false,
) {

val toolbarContainerView = ToolbarContainerView(context)
Expand Down Expand Up @@ -86,7 +88,9 @@ class BottomToolbarContainerView(
CoordinatorLayout.LayoutParams.WRAP_CONTENT,
).apply {
gravity = Gravity.BOTTOM
behavior = EngineViewScrollingBehavior(parent.context, null, ViewPosition.BOTTOM)
if (hideOnScroll) {
behavior = EngineViewScrollingBehavior(parent.context, null, ViewPosition.BOTTOM)
}
}

parent.addView(toolbarContainerView)
Expand Down
Loading

0 comments on commit f0510fd

Please sign in to comment.