diff --git a/android-design-system/design-system/src/main/res/layout/include_tab_switcher_toolbar_top.xml b/android-design-system/design-system/src/main/res/layout/include_tab_switcher_toolbar_top.xml
index d292bf01e56d..ddf4645da3b1 100644
--- a/android-design-system/design-system/src/main/res/layout/include_tab_switcher_toolbar_top.xml
+++ b/android-design-system/design-system/src/main/res/layout/include_tab_switcher_toolbar_top.xml
@@ -34,9 +34,4 @@
app:buttonGravity="center_vertical"
app:popupTheme="@style/Widget.DuckDuckGo.PopUpOverflowMenu" />
-
-
\ No newline at end of file
diff --git a/android-design-system/design-system/src/main/res/values/design-system-dimensions.xml b/android-design-system/design-system/src/main/res/values/design-system-dimensions.xml
index 1298c7add800..73b49e00336d 100644
--- a/android-design-system/design-system/src/main/res/values/design-system-dimensions.xml
+++ b/android-design-system/design-system/src/main/res/values/design-system-dimensions.xml
@@ -46,8 +46,8 @@
60dp
- 12dp
- 8dp
+ 8dp
+ 4dp
18dp
24dp
diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt
index 45a28c322a6b..96de0b8ec038 100644
--- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt
+++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt
@@ -573,7 +573,6 @@ class BrowserTabViewModel @Inject constructor(
@VisibleForTesting
internal val autoCompleteStateFlow = MutableStateFlow("")
private val fireproofWebsiteState: LiveData> = fireproofWebsiteRepository.getFireproofWebsites()
- private var alreadyShownKeyboard = false
@ExperimentalCoroutinesApi
@FlowPreview
@@ -603,6 +602,7 @@ class BrowserTabViewModel @Inject constructor(
private var isLinkOpenedInNewTab = false
private var allowlistRefreshTriggerJob: Job? = null
private var isCustomTabScreen: Boolean = false
+ private var alreadyShownKeyboard: Boolean = false
private val fireproofWebsitesObserver =
Observer> {
diff --git a/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/BrowserNavigationBarViewIntegration.kt b/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/BrowserNavigationBarViewIntegration.kt
index 306f50380954..d719132d2b0c 100644
--- a/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/BrowserNavigationBarViewIntegration.kt
+++ b/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/BrowserNavigationBarViewIntegration.kt
@@ -21,6 +21,7 @@ import com.duckduckgo.app.browser.databinding.FragmentBrowserTabBinding
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarObserver
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView.ViewMode.Browser
+import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView.ViewMode.CustomTab
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView.ViewMode.NewTab
import com.duckduckgo.app.browser.omnibar.Omnibar
import com.duckduckgo.common.ui.view.gone
@@ -61,7 +62,7 @@ class BrowserNavigationBarViewIntegration(
}
fun configureCustomTab() {
- navigationBarView.setCustomTab(isCustomTab = true)
+ navigationBarView.setViewMode(CustomTab)
}
fun configureBrowserViewMode() {
diff --git a/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarView.kt b/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarView.kt
index d6a6ccd448f3..6d02ab487185 100644
--- a/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarView.kt
+++ b/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarView.kt
@@ -110,12 +110,6 @@ class BrowserNavigationBarView @JvmOverloads constructor(
var browserNavigationBarObserver: BrowserNavigationBarObserver? = null
- fun setCustomTab(isCustomTab: Boolean) {
- doOnAttach {
- viewModel.setCustomTab(isCustomTab)
- }
- }
-
fun setViewMode(viewMode: ViewMode) {
doOnAttach {
viewModel.setViewMode(viewMode)
@@ -195,7 +189,8 @@ class BrowserNavigationBarView @JvmOverloads constructor(
binding.tabsButton.isVisible = viewState.tabsButtonVisible
binding.tabsButton.count = viewState.tabsCount
binding.tabsButton.hasUnread = viewState.hasUnreadTabs
- binding.browserMenuHighlight?.isVisible = viewState.showBrowserMenuHighlight
+ binding.browserMenuHighlight.isVisible = viewState.showBrowserMenuHighlight
+ binding.shadowView.isVisible = viewState.showShadow
renderFireButtonPulseAnimation(enabled = viewState.fireButtonHighlighted)
}
@@ -225,6 +220,7 @@ class BrowserNavigationBarView @JvmOverloads constructor(
}
enum class ViewMode {
+ CustomTab,
NewTab,
Browser,
TabManager,
diff --git a/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarViewModel.kt b/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarViewModel.kt
index afafb56ce181..090f4fa9fe1e 100644
--- a/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarViewModel.kt
+++ b/app/src/main/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarViewModel.kt
@@ -24,7 +24,9 @@ import com.duckduckgo.anvil.annotations.ContributesViewModel
import com.duckduckgo.app.browser.defaultbrowsing.prompts.AdditionalDefaultBrowserPrompts
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView.ViewMode
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView.ViewMode.Browser
+import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView.ViewMode.CustomTab
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView.ViewMode.NewTab
+import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarView.ViewMode.TabManager
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarViewModel.Command.NotifyAutofillButtonClicked
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarViewModel.Command.NotifyBookmarksButtonClicked
import com.duckduckgo.app.browser.navigation.bar.view.BrowserNavigationBarViewModel.Command.NotifyFireButtonClicked
@@ -61,16 +63,13 @@ class BrowserNavigationBarViewModel @Inject constructor(
private val _commands = Channel(capacity = Channel.CONFLATED)
val commands: Flow = _commands.receiveAsFlow()
- private val isCustomTab = MutableStateFlow(false)
private val _viewState = MutableStateFlow(ViewState())
val viewState = combine(
_viewState.asStateFlow(),
- isCustomTab,
tabRepository.flowTabs,
additionalDefaultBrowserPrompts.highlightPopupMenu,
- ) { state, isCustomTab, tabs, highlightOverflowMenu ->
+ ) { state, tabs, highlightOverflowMenu ->
state.copy(
- isVisible = !isCustomTab,
tabsCount = tabs.size,
hasUnreadTabs = tabs.firstOrNull { !it.viewed } != null,
showBrowserMenuHighlight = highlightOverflowMenu,
@@ -115,10 +114,6 @@ class BrowserNavigationBarViewModel @Inject constructor(
_commands.trySend(NotifyBookmarksButtonClicked)
}
- fun setCustomTab(customTab: Boolean) {
- isCustomTab.update { customTab }
- }
-
fun setViewMode(viewMode: ViewMode) {
when (viewMode) {
NewTab -> {
@@ -139,13 +134,21 @@ class BrowserNavigationBarViewModel @Inject constructor(
}
}
- ViewMode.TabManager -> {
+ TabManager -> {
_viewState.update {
it.copy(
newTabButtonVisible = true,
autofillButtonVisible = false,
tabsButtonVisible = false,
bookmarksButtonVisible = false,
+ showShadow = false,
+ )
+ }
+ }
+ CustomTab -> {
+ _viewState.update {
+ it.copy(
+ isVisible = false,
)
}
}
@@ -181,5 +184,6 @@ class BrowserNavigationBarViewModel @Inject constructor(
val tabsCount: Int = 0,
val hasUnreadTabs: Boolean = false,
val showBrowserMenuHighlight: Boolean = false,
+ val showShadow: Boolean = true,
)
}
diff --git a/app/src/main/java/com/duckduckgo/app/pixels/remoteconfig/AndroidBrowserConfigFeature.kt b/app/src/main/java/com/duckduckgo/app/pixels/remoteconfig/AndroidBrowserConfigFeature.kt
index c42e4503952c..441e66225000 100644
--- a/app/src/main/java/com/duckduckgo/app/pixels/remoteconfig/AndroidBrowserConfigFeature.kt
+++ b/app/src/main/java/com/duckduckgo/app/pixels/remoteconfig/AndroidBrowserConfigFeature.kt
@@ -193,6 +193,7 @@ interface AndroidBrowserConfigFeature {
* If the remote feature is not present defaults to `false`
*/
@Toggle.DefaultValue(DefaultFeatureValue.FALSE)
+ @Toggle.InternalAlwaysEnabled
fun splitOmnibar(): Toggle
/**
diff --git a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt
index ca23378d3d2d..bbbb34658884 100644
--- a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt
+++ b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt
@@ -39,6 +39,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import com.duckduckgo.anvil.annotations.InjectWith
import com.duckduckgo.app.browser.R
+import com.duckduckgo.app.browser.api.OmnibarRepository
import com.duckduckgo.app.browser.databinding.ActivityTabSwitcherBinding
import com.duckduckgo.app.browser.databinding.PopupTabsMenuBinding
import com.duckduckgo.app.browser.favicon.FaviconManager
@@ -165,6 +166,9 @@ class TabSwitcherActivity :
@Inject
lateinit var onboardingExperimentFireAnimationHelper: OnboardingExperimentFireAnimationHelper
+ @Inject
+ lateinit var omnibarRepository: OmnibarRepository
+
private val viewModel: TabSwitcherViewModel by bindViewModel()
private val tabsAdapter: TabSwitcherAdapter by lazy {
@@ -253,21 +257,26 @@ class TabSwitcherActivity :
}
private fun configureNavigationBar() {
- binding.navigationBar.browserNavigationBarObserver =
- object : BrowserNavigationBarObserver {
- override fun onMenuButtonClicked() {
- showPopupMenu(binding.navigationBar.popupMenuAnchor.id)
- }
+ if (omnibarRepository.omnibarType == OmnibarType.SPLIT) {
+ binding.navigationBar.browserNavigationBarObserver =
+ object : BrowserNavigationBarObserver {
+ override fun onMenuButtonClicked() {
+ showPopupMenu(binding.navigationBar.popupMenuAnchor.id)
+ }
- override fun onNewTabButtonClicked() {
- viewModel.onNewTabRequested()
- }
+ override fun onNewTabButtonClicked() {
+ viewModel.onNewTabRequested()
+ }
- override fun onFireButtonClicked() {
- viewModel.onFireButtonTapped()
+ override fun onFireButtonClicked() {
+ viewModel.onFireButtonTapped()
+ }
}
- }
- binding.navigationBar.setViewMode(BrowserNavigationBarView.ViewMode.TabManager)
+ binding.navigationBar.setViewMode(BrowserNavigationBarView.ViewMode.TabManager)
+ binding.navigationBar.show()
+ } else {
+ binding.navigationBar.gone()
+ }
}
override fun onSaveInstanceState(outState: Bundle) {
diff --git a/app/src/main/res/layout-w600dp/view_browser_navigation_bar.xml b/app/src/main/res/layout-w600dp/view_browser_navigation_bar.xml
deleted file mode 100644
index 728887f3a06f..000000000000
--- a/app/src/main/res/layout-w600dp/view_browser_navigation_bar.xml
+++ /dev/null
@@ -1,184 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout-w600dp/view_browser_navigation_bar_mockup.xml b/app/src/main/res/layout-w600dp/view_browser_navigation_bar_mockup.xml
deleted file mode 100644
index 33a0b6bee3ca..000000000000
--- a/app/src/main/res/layout-w600dp/view_browser_navigation_bar_mockup.xml
+++ /dev/null
@@ -1,158 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_appearance.xml b/app/src/main/res/layout/activity_appearance.xml
index d394dacb187d..21df8722d5ca 100644
--- a/app/src/main/res/layout/activity_appearance.xml
+++ b/app/src/main/res/layout/activity_appearance.xml
@@ -123,19 +123,19 @@
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/keyline_2"
- android:background="@drawable/selectable_rounded_ripple"
- app:layout_constraintWidth_max="160dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/bottomOmnibarContainer"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent">
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintWidth_max="160dp">
@@ -167,7 +167,6 @@
android:orientation="vertical"
android:padding="@dimen/keyline_2"
app:layout_constraintWidth_max="160dp"
- android:background="@drawable/selectable_rounded_ripple"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/splitOmnibarContainer"
app:layout_constraintStart_toEndOf="@+id/topOmnibarContainer"
@@ -175,9 +174,10 @@
@@ -216,7 +216,6 @@
android:padding="@dimen/keyline_2"
android:gravity="center"
android:orientation="vertical"
- android:background="@drawable/selectable_rounded_ripple"
app:layout_constraintWidth_max="160dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@@ -225,9 +224,10 @@
diff --git a/app/src/main/res/layout/activity_tab_switcher.xml b/app/src/main/res/layout/activity_tab_switcher.xml
index a536acbb8697..4bc91562dea6 100644
--- a/app/src/main/res/layout/activity_tab_switcher.xml
+++ b/app/src/main/res/layout/activity_tab_switcher.xml
@@ -72,6 +72,7 @@
diff --git a/app/src/test/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarViewModelTest.kt b/app/src/test/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarViewModelTest.kt
index 25eea6776d8a..d223ac34be14 100644
--- a/app/src/test/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarViewModelTest.kt
+++ b/app/src/test/java/com/duckduckgo/app/browser/navigation/bar/view/BrowserNavigationBarViewModelTest.kt
@@ -156,4 +156,69 @@ class BrowserNavigationBarViewModelTest {
cancelAndIgnoreRemainingEvents()
}
}
+
+ @Test
+ fun `when setViewMode NewTab then viewState reflects NewTab configuration`() = runTest {
+ testee.viewState.test {
+ val initial = awaitItem()
+ // sanity check defaults
+ Assert.assertTrue(initial.newTabButtonVisible)
+ Assert.assertFalse(initial.autofillButtonVisible)
+
+ testee.setViewMode(BrowserNavigationBarView.ViewMode.NewTab)
+
+ val updated = awaitItem()
+ Assert.assertFalse(updated.newTabButtonVisible)
+ Assert.assertTrue(updated.autofillButtonVisible)
+ // unchanged flags
+ Assert.assertTrue(updated.tabsButtonVisible)
+ Assert.assertTrue(updated.bookmarksButtonVisible)
+ Assert.assertTrue(updated.showShadow)
+ cancelAndIgnoreRemainingEvents()
+ }
+ }
+
+ @Test
+ fun `when setViewMode TabManager then viewState reflects TabManager configuration`() = runTest {
+ testee.viewState.test {
+ awaitItem() // initial
+ testee.setViewMode(BrowserNavigationBarView.ViewMode.TabManager)
+ val updated = awaitItem()
+ Assert.assertTrue(updated.newTabButtonVisible)
+ Assert.assertFalse(updated.autofillButtonVisible)
+ Assert.assertFalse(updated.tabsButtonVisible)
+ Assert.assertFalse(updated.bookmarksButtonVisible)
+ Assert.assertFalse(updated.showShadow)
+ cancelAndIgnoreRemainingEvents()
+ }
+ }
+
+ @Test
+ fun `when switching NewTab then Browser then viewState reflects Browser configuration`() = runTest {
+ testee.viewState.test {
+ awaitItem() // initial
+ testee.setViewMode(BrowserNavigationBarView.ViewMode.NewTab)
+ awaitItem() // NewTab state
+ testee.setViewMode(BrowserNavigationBarView.ViewMode.Browser)
+ val browserState = awaitItem()
+ Assert.assertTrue(browserState.newTabButtonVisible)
+ Assert.assertFalse(browserState.autofillButtonVisible)
+ Assert.assertTrue(browserState.tabsButtonVisible)
+ Assert.assertTrue(browserState.bookmarksButtonVisible)
+ Assert.assertTrue(browserState.showShadow)
+ cancelAndIgnoreRemainingEvents()
+ }
+ }
+
+ @Test
+ fun `when setViewMode CustomTab then navigation bar becomes hidden`() = runTest {
+ testee.viewState.test {
+ val initial = awaitItem()
+ Assert.assertTrue(initial.isVisible)
+
+ testee.setViewMode(BrowserNavigationBarView.ViewMode.CustomTab)
+ val hidden = awaitItem()
+ Assert.assertFalse(hidden.isVisible)
+ }
+ }
}