Skip to content

Visual updates: Omnibar shadows #6171

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2684,18 +2684,26 @@ class BrowserTabFragment :
)
}

private fun checkIfCanScroll() {
val canScrollUp = newBrowserTab.newTabContainerScrollView.canScrollVertically(-1)
val canScrollDown = newBrowserTab.newTabContainerScrollView.canScrollVertically(1)

omnibar.setContentCanScroll(canScrollUp, canScrollDown)
binding.navigationBar.setCanScrollDown(canScrollDown)
}

private fun configureNewTab() {
newBrowserTab.newTabContainerScrollView.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
if (omnibar.isEditing()) {
hideKeyboard()
}

// Check if it can scroll up
val canScrollUp = v.canScrollVertically(-1)
val canScrollDown = v.canScrollVertically(1)
val topOfPage = scrollY == 0
checkIfCanScroll()
}

omnibar.setContentCanScroll(canScrollUp, canScrollDown, topOfPage)
// check if the content can scroll after a delay to allow the view to be fully laid out
view?.postDelayed(SCROLLABILITY_CHECK_STARTUP_DELAY) {
checkIfCanScroll()
}
}

Expand Down Expand Up @@ -3657,6 +3665,10 @@ class BrowserTabFragment :
recreatePopupMenu()
privacyProtectionsPopup.onConfigurationChanged()
viewModel.onConfigurationChanged()

view?.postDelayed(SCROLLABILITY_CHECK_CONFIG_CHANGE_DELAY) {
checkIfCanScroll()
}
}

fun onBackPressed(isCustomTab: Boolean = false): Boolean {
Expand Down Expand Up @@ -3952,6 +3964,9 @@ class BrowserTabFragment :

private const val MAX_PROGRESS = 100
private const val TRACKERS_INI_DELAY = 500L

private const val SCROLLABILITY_CHECK_STARTUP_DELAY = 1000L
private const val SCROLLABILITY_CHECK_CONFIG_CHANGE_DELAY = 500L
private const val TRACKERS_SECONDARY_DELAY = 200L

private const val DEFAULT_CIRCLE_TARGET_TIMES_1_5 = 96
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class BrowserNavigationBarViewIntegration(
onDisabled()
}
navigationBarView.browserNavigationBarObserver = browserNavigationBarObserver
navigationBarView.setOmnibarPosition(omnibar.omnibarPosition)
}

fun configureCustomTab() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import androidx.lifecycle.findViewTreeViewModelStoreOwner
import androidx.lifecycle.lifecycleScope
import com.duckduckgo.anvil.annotations.InjectWith
import com.duckduckgo.app.browser.PulseAnimation
import com.duckduckgo.app.browser.R
import com.duckduckgo.app.browser.databinding.ViewBrowserNavigationBarBinding
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarViewModel.Command
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarViewModel.Command.NotifyAutofillButtonClicked
Expand Down Expand Up @@ -67,16 +66,6 @@ class BrowserNavigationBarView @JvmOverloads constructor(
defStyle: Int = 0,
) : FrameLayout(context, attrs, defStyle), AttachedBehavior {

private var showShadows: Boolean = false

init {
context.theme.obtainStyledAttributes(attrs, R.styleable.BrowserNavigationBarView, defStyle, 0)
.apply {
showShadows = getBoolean(R.styleable.BrowserNavigationBarView_showShadows, true)
recycle()
}
}

override fun setVisibility(visibility: Int) {
val isVisibilityUpdated = this.visibility != visibility

Expand Down Expand Up @@ -126,6 +115,12 @@ class BrowserNavigationBarView @JvmOverloads constructor(
}
}

fun setOmnibarPosition(omnibarPosition: OmnibarPosition) {
doOnAttach {
viewModel.setOmnibarPosition(omnibarPosition)
}
}

fun setViewMode(viewMode: ViewMode) {
doOnAttach {
viewModel.setViewMode(viewMode)
Expand All @@ -138,6 +133,12 @@ class BrowserNavigationBarView @JvmOverloads constructor(
}
}

fun setCanScrollDown(canScrollDown: Boolean) {
doOnAttach {
viewModel.onCanScrollDownChanged(canScrollDown)
}
}

override fun onAttachedToWindow() {
AndroidSupportInjection.inject(this)
super.onAttachedToWindow()
Expand Down Expand Up @@ -196,7 +197,6 @@ class BrowserNavigationBarView @JvmOverloads constructor(
}

private fun renderView(viewState: ViewState) {
binding.shadowView.isVisible = showShadows
binding.root.isVisible = viewState.isVisible

binding.newTabButton.isVisible = viewState.newTabButtonVisible
Expand All @@ -208,6 +208,7 @@ class BrowserNavigationBarView @JvmOverloads constructor(
binding.tabsButton.hasUnread = viewState.hasUnreadTabs

renderFireButtonPulseAnimation(enabled = viewState.fireButtonHighlighted)
binding.shadowView.isVisible = viewState.showShadow
}

private fun processCommands(command: Command) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarViewMo
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarViewModel.Command.NotifyNewTabButtonClicked
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarViewModel.Command.NotifyTabsButtonClicked
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarViewModel.Command.NotifyTabsButtonLongClicked
import com.duckduckgo.app.browser.omnibar.model.OmnibarPosition
import com.duckduckgo.app.pixels.AppPixelName
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.FIRE_BUTTON_STATE
Expand Down Expand Up @@ -124,6 +125,7 @@ class BrowserNavigationBarViewModel @Inject constructor(
autofillButtonVisible = true,
fireButtonVisible = true,
tabsButtonVisible = true,
isNewTab = true,
)
}
}
Expand All @@ -135,6 +137,7 @@ class BrowserNavigationBarViewModel @Inject constructor(
autofillButtonVisible = false,
fireButtonVisible = true,
tabsButtonVisible = true,
isNewTab = false,
)
}
}
Expand All @@ -149,6 +152,22 @@ class BrowserNavigationBarViewModel @Inject constructor(
}
}

fun setOmnibarPosition(omnibarPosition: OmnibarPosition) {
_viewState.update {
it.copy(
omnibarPosition = omnibarPosition,
)
}
}

fun onCanScrollDownChanged(canScrollDown: Boolean) {
_viewState.update {
it.copy(
canScrollDown = canScrollDown,
)
}
}

sealed class Command {
data object NotifyFireButtonClicked : Command()
data object NotifyTabsButtonClicked : Command()
Expand All @@ -172,5 +191,11 @@ class BrowserNavigationBarViewModel @Inject constructor(
val tabsButtonVisible: Boolean = true,
val tabsCount: Int = 0,
val hasUnreadTabs: Boolean = false,
)
val isNewTab: Boolean = false,
val canScrollDown: Boolean = false,
val omnibarPosition: OmnibarPosition = OmnibarPosition.BOTTOM,
) {
val showShadow: Boolean
get() = omnibarPosition == OmnibarPosition.TOP && (!isNewTab || canScrollDown)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,8 @@ class Omnibar(
fun setContentCanScroll(
canScrollUp: Boolean,
canScrollDown: Boolean,
topOfPage: Boolean,
) {
newOmnibar.decorate(Decoration.NewTabScrollingState(canScrollUp, canScrollDown, topOfPage))
newOmnibar.decorate(Decoration.NewTabScrollingState(canScrollUp, canScrollDown))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ open class OmnibarLayout @JvmOverloads constructor(
data class NewTabScrollingState(
val canScrollUp: Boolean,
val canScrollDown: Boolean,
val topOfPage: Boolean,
) : Decoration()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ class OmnibarLayoutViewModel @Inject constructor(
val isVisualDesignExperimentEnabled: Boolean = false,
val trackersBlocked: Int = 0,
val previouslyTrackersBlocked: Int = 0,
val showShadows: Boolean = false,
val showTopShadow: Boolean = false,
val showBottomShadow: Boolean = false,
val showClickCatcher: Boolean = false,
) {
fun shouldUpdateOmnibarText(): Boolean {
Expand Down Expand Up @@ -341,7 +342,8 @@ class OmnibarLayoutViewModel @Inject constructor(
showBrowserMenu = true,
showTabsMenu = false,
showFireIcon = false,
showShadows = true,
showTopShadow = true,
showBottomShadow = true,
)
}
}
Expand Down Expand Up @@ -370,7 +372,8 @@ class OmnibarLayoutViewModel @Inject constructor(
hasQueryChanged = false,
urlLoaded = _viewState.value.url,
),
showShadows = false,
showTopShadow = viewMode !is NewTab,
showBottomShadow = viewMode !is NewTab,
)
}
}
Expand Down Expand Up @@ -742,12 +745,13 @@ class OmnibarLayoutViewModel @Inject constructor(

fun onNewTabScrollingStateChanged(scrollingState: Decoration.NewTabScrollingState) {
val viewMode = viewState.value.viewMode
// if (viewMode is NewTab) {
// _viewState.update {
// it.copy(
// showShadows = (scrollingState.canScrollUp || scrollingState.canScrollDown) && !scrollingState.topOfPage,
// )
// }
// }
if (viewMode is NewTab) {
_viewState.update {
it.copy(
showTopShadow = scrollingState.canScrollDown,
showBottomShadow = scrollingState.canScrollUp,
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import com.duckduckgo.common.ui.experiments.visual.store.VisualDesignExperimentD
import com.duckduckgo.common.ui.view.gone
import com.duckduckgo.common.ui.view.hide
import com.duckduckgo.common.ui.view.show
import com.duckduckgo.common.ui.view.toDp
import com.duckduckgo.di.scopes.FragmentScope
import com.duckduckgo.duckchat.impl.ui.SearchInterstitialActivityParams
import com.duckduckgo.mobile.android.R as CommonR
Expand Down Expand Up @@ -76,6 +75,10 @@ class FadeOmnibarLayout @JvmOverloads constructor(
private val backIcon: ImageView by lazy { findViewById(R.id.backIcon) }
private val customTabToolbarContainerWrapper: ViewGroup by lazy { findViewById(R.id.customTabToolbarContainerWrapper) }
private val omniBarClickCatcher: View by lazy { findViewById(R.id.omnibarClickCatcher) }
private val shadowTop: View by lazy { findViewById(R.id.shadowViewTop) }
private val shadowLineBottom: View by lazy { findViewById(R.id.shadowLineViewBottom) }

private val shadowGradientBottom: View by lazy { findViewById(R.id.shadowViewBottom) }

override val findInPage: FindInPage by lazy {
FindInPageImpl(IncludeFadeOmnibarFindInPageBinding.bind(findViewById(R.id.findInPage)))
Expand Down Expand Up @@ -129,12 +132,12 @@ class FadeOmnibarLayout @JvmOverloads constructor(

AndroidSupportInjection.inject(this)

outlineProvider = null

val rootContainer = root.findViewById<LinearLayout>(R.id.rootContainer)
val navBar = rootContainer.findViewById<BrowserNavigationBarView>(R.id.omnibarNavigationBar)
if (omnibarPosition == OmnibarPosition.TOP) {
rootContainer.removeView(navBar)

omnibarCard.elevation = 1f.toDp(context)
} else {
navigationBar = navBar

Expand All @@ -148,8 +151,6 @@ class FadeOmnibarLayout @JvmOverloads constructor(
navBar.findViewById<LinearLayout>(R.id.barView).updatePadding(
top = 0,
)

omnibarCard.elevation = 0.5f.toDp(context)
}
omniBarClickCatcher.setOnClickListener {
globalActivityStarter.start(context, SearchInterstitialActivityParams)
Expand Down Expand Up @@ -192,7 +193,7 @@ class FadeOmnibarLayout @JvmOverloads constructor(
override fun render(viewState: ViewState) {
super.render(viewState)

renderShadows(viewState.showShadows)
renderShadows(viewState.showTopShadow, viewState.showBottomShadow)

if (viewState.hasFocus || isFindInPageVisible) {
animateOmnibarFocusedState(focused = true)
Expand Down Expand Up @@ -363,12 +364,16 @@ class FadeOmnibarLayout @JvmOverloads constructor(
}
}

private fun renderShadows(showShadows: Boolean) {
// outlineProvider = if (showShadows) {
// ViewOutlineProvider.BACKGROUND
// } else {
// null
// }
private fun renderShadows(showTopShadow: Boolean, showBottomShadow: Boolean) {
val isBottomShadowVisible = showBottomShadow && omnibarPosition == OmnibarPosition.TOP
if (viewModel.viewState.value.viewMode == ViewMode.NewTab) {
shadowLineBottom.gone()
shadowGradientBottom.isVisible = isBottomShadowVisible
} else {
shadowLineBottom.isVisible = isBottomShadowVisible
shadowGradientBottom.gone()
}
shadowTop.isVisible = showTopShadow && omnibarPosition == OmnibarPosition.BOTTOM
}

companion object {
Expand Down
23 changes: 23 additions & 0 deletions app/src/main/res/drawable/background_webview_bottom_shadow.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2025 DuckDuckGo
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="90"
android:endColor="?attr/daxColorToolbar"
android:startColor="?attr/daxColorShadow"
android:type="linear" />
</shape>
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
android:shape="rectangle">
<gradient
android:angle="270"
android:endColor="#00000000"
android:startColor="#1A000000"
android:endColor="?attr/daxColorToolbar"
android:startColor="?attr/daxColorShadow"
android:type="linear" />
</shape>
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@
<View
android:id="@+id/shadowView"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/background_navigation_bar_shadow"
android:layout_height="3dp"
android:background="@drawable/background_webview_top_shadow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/layout/fragment_browser_tab.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@
android:id="@+id/navigationBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:showShadows="true"
android:layout_gravity="bottom" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
4 changes: 2 additions & 2 deletions app/src/main/res/layout/view_browser_navigation_bar.xml
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@
<View
android:id="@+id/shadowView"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/background_navigation_bar_shadow"
android:layout_height="3dp"
android:background="@drawable/background_webview_top_shadow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Expand Down
Loading
Loading