1
0
Fork 0
fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt

263 lines
10 KiB
Kotlin
Raw Normal View History

/* 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.components.toolbar
import android.view.HapticFeedbackConstants
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
2020-07-23 04:23:38 +02:00
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.LifecycleOwner
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
import com.google.android.material.appbar.AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.component_browser_top_toolbar.*
import kotlinx.android.synthetic.main.component_browser_top_toolbar.view.*
import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider
import mozilla.components.browser.session.Session
import mozilla.components.browser.toolbar.BrowserToolbar
import mozilla.components.browser.toolbar.behavior.BrowserToolbarBottomBehavior
2019-10-15 17:54:04 +02:00
import mozilla.components.browser.toolbar.display.DisplayToolbar
import mozilla.components.support.ktx.android.util.dpToFloat
2020-03-20 21:48:54 +01:00
import mozilla.components.support.utils.URLStringUtils
import org.mozilla.fenix.R
import org.mozilla.fenix.customtabs.CustomTabToolbarIntegration
import org.mozilla.fenix.customtabs.CustomTabToolbarMenu
4281 remove qab (#6310) * For #4281: small ToolbarMenu refactor This makes it easier to see how items are ordered in the menuItems list * For 4281: add QAB buttons to menu * For 4281: removed menu back button per mocks I double checked with UX, and we'll be relying on the hardware back button for its functionality * For 4281: add content descriptions for bookmarking * For 4281: updated BrowserToolbarController for new functionality * For 4281: provided simple dependencies to browser controller More complex changes will be in a following commit, for review readability * For 4281: move toolbar controller dependencies up to BaseBrowserFragment The functionality they control is being moved into the toolbar menu, which is shared by both normal tabs and custom ones * For 4281: removed (now unused) code related to QAB * For 4281: fix test compilation after QAB removal Tests still need to be expanded to include added functionality * For 4281: updated menu to show if url is bookmarked This sloppy workaround is required because TwoStateButton requires that `isInPrimaryState` be a synchronous call, and checking whether or not the current site is bookmarked is quite slow (10-50 MS, in my tests). After days of work and many attempted solutions, this was the least abhorrent among them. https://github.com/mozilla-mobile/android-components/issues/4915 was opened against AC to evaluate potentially supporting async `isInPrimaryState` functions. https://github.com/mozilla-mobile/fenix/issues/6370 was opened against Fenix to investigate the unexpectedly slow call to `BookmarkStorage`. * For 4281: update reader mode switch * For 4281: selectively show/hide menu items * For 4281: add reader mode appearance * For 4281: update bookmark button when it is clicked * For 4281: removed unused QAB code * For 4281: removed QAB robot, updated UI tests * For 4281: removed QuickActionSheet metrics Since this behavior now lives in the toolbar, it is tracked via Event.BrowserMenuItemTapped * For 4281: fixed lint errors * For 4281: add new strings for buttons added to menu This is necessary because the location change (from QAB to toolbar menu) could affect the grammar in some languages * For 4281: remove outdated TODOs * For 4281: removed QAB container * For 4281: removed back button reference from UI test This button no longer exists * For 4821: Fixes a visual defect (extra padding on top of toolbar) * For 4281: update copy on reader mode * For 4281: fixed review nits
2019-11-12 02:10:14 +01:00
import org.mozilla.fenix.ext.bookmarkStorage
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.ToolbarPopupWindow
import java.lang.ref.WeakReference
interface BrowserToolbarViewInteractor {
fun onBrowserToolbarPaste(text: String)
fun onBrowserToolbarPasteAndGo(text: String)
fun onBrowserToolbarClicked()
fun onBrowserToolbarMenuItemTapped(item: ToolbarMenu.Item)
fun onTabCounterClicked()
fun onTabCounterMenuItemTapped(item: TabCounterMenuItem)
fun onScrolled(offset: Int)
2020-06-04 22:21:20 +02:00
fun onReaderModePressed(enabled: Boolean)
}
@SuppressWarnings("LargeClass")
class BrowserToolbarView(
private val container: ViewGroup,
2020-07-23 04:23:38 +02:00
private val toolbarPosition: ToolbarPosition,
private val interactor: BrowserToolbarViewInteractor,
private val customTabSession: Session?,
private val lifecycleOwner: LifecycleOwner
) : LayoutContainer {
override val containerView: View?
get() = container
private val settings = container.context.settings()
@LayoutRes
2020-07-23 04:23:38 +02:00
private val toolbarLayout = when (settings.toolbarPosition) {
ToolbarPosition.BOTTOM -> R.layout.component_bottom_browser_toolbar
ToolbarPosition.TOP -> R.layout.component_browser_top_toolbar
}
private val layout = LayoutInflater.from(container.context)
.inflate(toolbarLayout, container, true)
val view: BrowserToolbar = layout
.findViewById(R.id.toolbar)
val toolbarIntegration: ToolbarIntegration
init {
val isCustomTabSession = customTabSession != null
2019-10-15 17:54:04 +02:00
view.display.setOnUrlLongClickListener {
ToolbarPopupWindow.show(
WeakReference(view),
customTabSession,
interactor::onBrowserToolbarPasteAndGo,
interactor::onBrowserToolbarPaste
2019-09-06 23:11:03 +02:00
)
true
}
with(container.context) {
val sessionManager = components.core.sessionManager
2020-07-23 04:23:38 +02:00
if (toolbarPosition == ToolbarPosition.TOP) {
val offsetChangedListener =
AppBarLayout.OnOffsetChangedListener { _: AppBarLayout?, verticalOffset: Int ->
interactor.onScrolled(verticalOffset)
}
app_bar.addOnOffsetChangedListener(offsetChangedListener)
}
view.apply {
setScrollFlags()
elevation = TOOLBAR_ELEVATION.dpToFloat(resources.displayMetrics)
2019-10-15 17:54:04 +02:00
if (!isCustomTabSession) {
display.setUrlBackground(getDrawable(R.drawable.search_url_background))
}
display.onUrlClicked = {
interactor.onBrowserToolbarClicked()
false
}
2020-07-23 04:23:38 +02:00
display.progressGravity = when (toolbarPosition) {
ToolbarPosition.BOTTOM -> DisplayToolbar.Gravity.TOP
ToolbarPosition.TOP -> DisplayToolbar.Gravity.BOTTOM
2019-10-15 17:54:04 +02:00
}
2019-10-15 17:54:04 +02:00
val primaryTextColor = ContextCompat.getColor(
container.context,
ThemeManager.resolveAttribute(R.attr.primaryText, container.context)
)
2019-10-15 17:54:04 +02:00
val secondaryTextColor = ContextCompat.getColor(
container.context,
ThemeManager.resolveAttribute(R.attr.secondaryText, container.context)
)
2019-10-15 17:54:04 +02:00
val separatorColor = ContextCompat.getColor(
container.context,
ThemeManager.resolveAttribute(R.attr.toolbarDivider, container.context)
)
2020-03-20 21:48:54 +01:00
display.urlFormatter = { url -> URLStringUtils.toDisplayUrl(url) }
2019-10-15 17:54:04 +02:00
display.colors = display.colors.copy(
text = primaryTextColor,
securityIconSecure = primaryTextColor,
securityIconInsecure = primaryTextColor,
menu = primaryTextColor,
hint = secondaryTextColor,
separator = separatorColor,
trackingProtection = primaryTextColor
)
display.hint = context.getString(R.string.search_hint)
}
val menuToolbar: ToolbarMenu
if (isCustomTabSession) {
menuToolbar = CustomTabToolbarMenu(
this,
sessionManager,
customTabSession?.id,
2020-07-23 04:23:38 +02:00
shouldReverseItems = toolbarPosition == ToolbarPosition.TOP,
onItemTapped = {
it.performHapticIfNeeded(view)
interactor.onBrowserToolbarMenuItemTapped(it)
}
)
} else {
menuToolbar = DefaultToolbarMenu(
4281 remove qab (#6310) * For #4281: small ToolbarMenu refactor This makes it easier to see how items are ordered in the menuItems list * For 4281: add QAB buttons to menu * For 4281: removed menu back button per mocks I double checked with UX, and we'll be relying on the hardware back button for its functionality * For 4281: add content descriptions for bookmarking * For 4281: updated BrowserToolbarController for new functionality * For 4281: provided simple dependencies to browser controller More complex changes will be in a following commit, for review readability * For 4281: move toolbar controller dependencies up to BaseBrowserFragment The functionality they control is being moved into the toolbar menu, which is shared by both normal tabs and custom ones * For 4281: removed (now unused) code related to QAB * For 4281: fix test compilation after QAB removal Tests still need to be expanded to include added functionality * For 4281: updated menu to show if url is bookmarked This sloppy workaround is required because TwoStateButton requires that `isInPrimaryState` be a synchronous call, and checking whether or not the current site is bookmarked is quite slow (10-50 MS, in my tests). After days of work and many attempted solutions, this was the least abhorrent among them. https://github.com/mozilla-mobile/android-components/issues/4915 was opened against AC to evaluate potentially supporting async `isInPrimaryState` functions. https://github.com/mozilla-mobile/fenix/issues/6370 was opened against Fenix to investigate the unexpectedly slow call to `BookmarkStorage`. * For 4281: update reader mode switch * For 4281: selectively show/hide menu items * For 4281: add reader mode appearance * For 4281: update bookmark button when it is clicked * For 4281: removed unused QAB code * For 4281: removed QAB robot, updated UI tests * For 4281: removed QuickActionSheet metrics Since this behavior now lives in the toolbar, it is tracked via Event.BrowserMenuItemTapped * For 4281: fixed lint errors * For 4281: add new strings for buttons added to menu This is necessary because the location change (from QAB to toolbar menu) could affect the grammar in some languages * For 4281: remove outdated TODOs * For 4281: removed QAB container * For 4281: removed back button reference from UI test This button no longer exists * For 4821: Fixes a visual defect (extra padding on top of toolbar) * For 4281: update copy on reader mode * For 4281: fixed review nits
2019-11-12 02:10:14 +01:00
context = this,
hasAccountProblem = components.backgroundServices.accountManager.accountNeedsReauth(),
2020-07-23 04:23:38 +02:00
shouldReverseItems = toolbarPosition == ToolbarPosition.TOP,
onItemTapped = {
it.performHapticIfNeeded(view)
interactor.onBrowserToolbarMenuItemTapped(it)
},
lifecycleOwner = lifecycleOwner,
4281 remove qab (#6310) * For #4281: small ToolbarMenu refactor This makes it easier to see how items are ordered in the menuItems list * For 4281: add QAB buttons to menu * For 4281: removed menu back button per mocks I double checked with UX, and we'll be relying on the hardware back button for its functionality * For 4281: add content descriptions for bookmarking * For 4281: updated BrowserToolbarController for new functionality * For 4281: provided simple dependencies to browser controller More complex changes will be in a following commit, for review readability * For 4281: move toolbar controller dependencies up to BaseBrowserFragment The functionality they control is being moved into the toolbar menu, which is shared by both normal tabs and custom ones * For 4281: removed (now unused) code related to QAB * For 4281: fix test compilation after QAB removal Tests still need to be expanded to include added functionality * For 4281: updated menu to show if url is bookmarked This sloppy workaround is required because TwoStateButton requires that `isInPrimaryState` be a synchronous call, and checking whether or not the current site is bookmarked is quite slow (10-50 MS, in my tests). After days of work and many attempted solutions, this was the least abhorrent among them. https://github.com/mozilla-mobile/android-components/issues/4915 was opened against AC to evaluate potentially supporting async `isInPrimaryState` functions. https://github.com/mozilla-mobile/fenix/issues/6370 was opened against Fenix to investigate the unexpectedly slow call to `BookmarkStorage`. * For 4281: update reader mode switch * For 4281: selectively show/hide menu items * For 4281: add reader mode appearance * For 4281: update bookmark button when it is clicked * For 4281: removed unused QAB code * For 4281: removed QAB robot, updated UI tests * For 4281: removed QuickActionSheet metrics Since this behavior now lives in the toolbar, it is tracked via Event.BrowserMenuItemTapped * For 4281: fixed lint errors * For 4281: add new strings for buttons added to menu This is necessary because the location change (from QAB to toolbar menu) could affect the grammar in some languages * For 4281: remove outdated TODOs * For 4281: removed QAB container * For 4281: removed back button reference from UI test This button no longer exists * For 4821: Fixes a visual defect (extra padding on top of toolbar) * For 4281: update copy on reader mode * For 4281: fixed review nits
2019-11-12 02:10:14 +01:00
sessionManager = sessionManager,
store = components.core.store,
4281 remove qab (#6310) * For #4281: small ToolbarMenu refactor This makes it easier to see how items are ordered in the menuItems list * For 4281: add QAB buttons to menu * For 4281: removed menu back button per mocks I double checked with UX, and we'll be relying on the hardware back button for its functionality * For 4281: add content descriptions for bookmarking * For 4281: updated BrowserToolbarController for new functionality * For 4281: provided simple dependencies to browser controller More complex changes will be in a following commit, for review readability * For 4281: move toolbar controller dependencies up to BaseBrowserFragment The functionality they control is being moved into the toolbar menu, which is shared by both normal tabs and custom ones * For 4281: removed (now unused) code related to QAB * For 4281: fix test compilation after QAB removal Tests still need to be expanded to include added functionality * For 4281: updated menu to show if url is bookmarked This sloppy workaround is required because TwoStateButton requires that `isInPrimaryState` be a synchronous call, and checking whether or not the current site is bookmarked is quite slow (10-50 MS, in my tests). After days of work and many attempted solutions, this was the least abhorrent among them. https://github.com/mozilla-mobile/android-components/issues/4915 was opened against AC to evaluate potentially supporting async `isInPrimaryState` functions. https://github.com/mozilla-mobile/fenix/issues/6370 was opened against Fenix to investigate the unexpectedly slow call to `BookmarkStorage`. * For 4281: update reader mode switch * For 4281: selectively show/hide menu items * For 4281: add reader mode appearance * For 4281: update bookmark button when it is clicked * For 4281: removed unused QAB code * For 4281: removed QAB robot, updated UI tests * For 4281: removed QuickActionSheet metrics Since this behavior now lives in the toolbar, it is tracked via Event.BrowserMenuItemTapped * For 4281: fixed lint errors * For 4281: add new strings for buttons added to menu This is necessary because the location change (from QAB to toolbar menu) could affect the grammar in some languages * For 4281: remove outdated TODOs * For 4281: removed QAB container * For 4281: removed back button reference from UI test This button no longer exists * For 4821: Fixes a visual defect (extra padding on top of toolbar) * For 4281: update copy on reader mode * For 4281: fixed review nits
2019-11-12 02:10:14 +01:00
bookmarksStorage = bookmarkStorage
)
view.display.setMenuDismissAction {
view.invalidateActions()
}
}
toolbarIntegration = if (customTabSession != null) {
CustomTabToolbarIntegration(
this,
view,
menuToolbar,
customTabSession.id,
isPrivate = customTabSession.private
)
} else {
DefaultToolbarIntegration(
this,
view,
menuToolbar,
ShippedDomainsProvider().also { it.initialize(this) },
components.core.historyStorage,
lifecycleOwner,
sessionId = null,
isPrivate = sessionManager.selectedSession?.private ?: false,
interactor = interactor,
engine = components.core.engine
)
}
}
}
fun expand() {
2020-07-23 04:23:38 +02:00
when (settings.toolbarPosition) {
ToolbarPosition.BOTTOM -> {
(view.layoutParams as CoordinatorLayout.LayoutParams).apply {
(behavior as BrowserToolbarBottomBehavior).forceExpand(view)
}
}
ToolbarPosition.TOP -> {
layout.app_bar?.setExpanded(true)
}
}
}
/**
* Dynamically sets scroll flags for the toolbar when the user does not have a screen reader enabled
* Note that the bottom toolbar has a feature flag for being dynamic, so it may not get flags set.
*/
fun setScrollFlags(shouldDisableScroll: Boolean = false) {
2020-07-23 04:23:38 +02:00
when (settings.toolbarPosition) {
ToolbarPosition.BOTTOM -> {
(view.layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
behavior = BrowserToolbarBottomBehavior(view.context, null)
}
}
2020-07-23 04:23:38 +02:00
ToolbarPosition.TOP -> {
view.updateLayoutParams<AppBarLayout.LayoutParams> {
scrollFlags = if (settings.shouldUseFixedTopToolbar || shouldDisableScroll) {
// Force expand the toolbar so the user is not stuck with a hidden toolbar
expand()
0
} else {
SCROLL_FLAG_SCROLL or
SCROLL_FLAG_ENTER_ALWAYS or
SCROLL_FLAG_SNAP or
SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
2020-07-23 04:23:38 +02:00
}
}
}
}
}
companion object {
private const val TOOLBAR_ELEVATION = 16
}
@Suppress("ComplexCondition")
private fun ToolbarMenu.Item.performHapticIfNeeded(view: View) {
if (this is ToolbarMenu.Item.Reload && this.bypassCache ||
2020-08-11 00:31:10 +02:00
this is ToolbarMenu.Item.Back && this.viewHistory ||
this is ToolbarMenu.Item.Forward && this.viewHistory
) {
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
}
}
}