Skip to content

Commit c678f2e

Browse files
Add bottom navigation bar (#5757)
Task/Issue URL: https://app.asana.com/0/1208671518894266/1209578839649376 ### Description Adds an experimental bottom navigation bar. ### Steps to test this PR - [x] Build the branch in `play*` variant and verify that bottom navigation bar **is not** present. - [x] Verify that no icons are hidden from the omnibar or form the browser menu. - [x] Verify that there's no Duck.ai button present in the omnibar. - [x] Verify that custom tabs don't show the navigation bar. - [x] Build the branch in `internal*` variant. The new designs and navigation bar should be enabled by default. - [x] Verify that the fire and tabs buttons are hidden from the omnibar. - [x] Verify that the navigation buttons (arrows and refresh spinner) are hidden from the browser menu. - [x] Verify that a new "Refresh Page" button is available in the browser menu. - [x] Verify that there's a new Duck.ai button in the omnibar. - [x] Verify that buttons on the navigation bar work. - [x] Verify that navigation bar hides while scrolling (in tandem with the omnibar). - [x] (optional) Verify that custom tabs show the navigation bar but without the fire, tabs, and Duck.ai buttons. - [x] (optional) Try it in dark mode and verify that the colors are shifted correctly. - [x] Go to "Experimental UI Settings" in the internal settings and turn the navigation bar off. - [x] Verify that navigation bar is gone. ### UI changes | Before | After | | ------ | ----- | ![Screenshot_20250310_173457](https://github.com/user-attachments/assets/bdd50113-f966-4aec-9d29-93c4139011d7)|![Screenshot_20250310_173518](https://github.com/user-attachments/assets/d568e92a-e0cf-46e6-8f9f-1864f68d8c60)| --------- Co-authored-by: Josh Leibstein <[email protected]>
1 parent c40ed17 commit c678f2e

File tree

54 files changed

+1894
-246
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1894
-246
lines changed

.github/workflows/ads-end-to-end.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
uses: gradle/actions/setup-gradle@v3
4949

5050
- name: Assemble the project
51-
run: ./gradlew assembleInternalRelease -Pforce-default-variant
51+
run: ./gradlew assembleInternalRelease -Pforce-default-variant -Pdisable-visual-design-experiment
5252

5353
- name: Move APK to new folder
5454
if: always()

.github/workflows/custom-tabs-nightly.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
uses: gradle/actions/setup-gradle@v3
4949

5050
- name: Assemble internal release APK
51-
run: ./gradlew assembleInternalRelease -Pforce-default-variant -x lint
51+
run: ./gradlew assembleInternalRelease -Pforce-default-variant -Pdisable-visual-design-experiment -x lint
5252

5353
- name: Move APK to new folder
5454
if: always()

.github/workflows/sync-critical-path.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
uses: gradle/actions/setup-gradle@v3
5656

5757
- name: Assemble internal release APK
58-
run: ./gradlew assembleInternalRelease -Pforce-default-variant -Psync-disable-auth-requirement -x lint
58+
run: ./gradlew assembleInternalRelease -Pforce-default-variant -Psync-disable-auth-requirement -Pdisable-visual-design-experiment -x lint
5959

6060
- name: Move APK to new folder
6161
if: always()

app-build-config/app-build-config-api/src/main/java/com/duckduckgo/appbuildconfig/api/AppBuildConfig.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ interface AppBuildConfig {
3434
val isDefaultVariantForced: Boolean
3535
val buildDateTimeMillis: Long
3636
val canSkipOnboarding: Boolean
37+
val visualDesignExperimentEnabledByDefault: Boolean
3738

3839
/**
3940
* You should call [variantName] in a background thread

app/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ android {
6767
} else {
6868
buildConfigField "long", "BUILD_DATE_MILLIS", "0"
6969
}
70+
if (project.hasProperty('disable-visual-design-experiment')) {
71+
buildConfigField "boolean", "VISUAL_DESIGN_EXPERIMENT_ENABLED_BY_DEFAULT", "false"
72+
} else {
73+
buildConfigField "boolean", "VISUAL_DESIGN_EXPERIMENT_ENABLED_BY_DEFAULT", "true"
74+
}
7075

7176
namespace 'com.duckduckgo.app.browser'
7277
}

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ import com.duckduckgo.browser.api.UserBrowserProperties
192192
import com.duckduckgo.browser.api.brokensite.BrokenSiteContext
193193
import com.duckduckgo.common.test.CoroutineTestRule
194194
import com.duckduckgo.common.test.InstantSchedulersRule
195+
import com.duckduckgo.common.ui.experiments.visual.store.VisualDesignExperimentDataStore
196+
import com.duckduckgo.common.ui.experiments.visual.store.VisualDesignExperimentDataStore.FeatureState
195197
import com.duckduckgo.common.utils.DispatcherProvider
196198
import com.duckduckgo.common.utils.device.DeviceInfo
197199
import com.duckduckgo.common.utils.plugins.PluginPoint
@@ -509,6 +511,10 @@ class BrowserTabViewModelTest {
509511
private val defaultBrowserPromptsExperimentShowPopupMenuItemFlow = MutableStateFlow(false)
510512
private val mockDefaultBrowserPromptsExperiment: DefaultBrowserPromptsExperiment = mock()
511513

514+
private val mockVisualDesignExperimentDataStore: VisualDesignExperimentDataStore = mock()
515+
private val defaultVisualExperimentStateFlow = MutableStateFlow(FeatureState(isAvailable = true, isEnabled = false))
516+
private val defaultVisualExperimentNavBarStateFlow = MutableStateFlow(FeatureState(isAvailable = true, isEnabled = false))
517+
512518
@Before
513519
fun before() = runTest {
514520
MockitoAnnotations.openMocks(this)
@@ -613,6 +619,12 @@ class BrowserTabViewModelTest {
613619
whenever(mockDefaultBrowserPromptsExperiment.showSetAsDefaultPopupMenuItem).thenReturn(
614620
defaultBrowserPromptsExperimentShowPopupMenuItemFlow,
615621
)
622+
whenever(mockVisualDesignExperimentDataStore.experimentState).thenReturn(
623+
defaultVisualExperimentStateFlow,
624+
)
625+
whenever(mockVisualDesignExperimentDataStore.navigationBarState).thenReturn(
626+
defaultVisualExperimentNavBarStateFlow,
627+
)
616628

617629
testee = BrowserTabViewModel(
618630
statisticsUpdater = mockStatisticsUpdater,
@@ -681,6 +693,7 @@ class BrowserTabViewModelTest {
681693
tabStatsBucketing = mockTabStatsBucketing,
682694
defaultBrowserPromptsExperiment = mockDefaultBrowserPromptsExperiment,
683695
swipingTabsFeature = swipingTabsFeatureProvider,
696+
visualDesignExperimentDataStore = mockVisualDesignExperimentDataStore,
684697
)
685698

686699
testee.loadData("abc", null, false, false)

app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ import com.duckduckgo.appbuildconfig.api.AppBuildConfig
8383
import com.duckduckgo.autofill.api.emailprotection.EmailProtectionLinkVerifier
8484
import com.duckduckgo.browser.api.ui.BrowserScreens.BookmarksScreenNoParams
8585
import com.duckduckgo.common.ui.DuckDuckGoActivity
86-
import com.duckduckgo.common.ui.store.ExperimentalUIThemingFeature
86+
import com.duckduckgo.common.ui.experiments.visual.store.VisualDesignExperimentDataStore
8787
import com.duckduckgo.common.ui.view.dialog.TextAlertDialogBuilder
8888
import com.duckduckgo.common.ui.view.gone
8989
import com.duckduckgo.common.ui.view.show
@@ -163,7 +163,7 @@ open class BrowserActivity : DuckDuckGoActivity() {
163163
lateinit var duckChat: DuckChat
164164

165165
@Inject
166-
lateinit var experimentalUIThemingFeature: ExperimentalUIThemingFeature
166+
lateinit var visualDesignExperimentDataStore: VisualDesignExperimentDataStore
167167

168168
private val lastActiveTabs = TabList()
169169

@@ -1035,7 +1035,7 @@ open class BrowserActivity : DuckDuckGoActivity() {
10351035
}
10361036

10371037
private fun bindMockupToolbars() {
1038-
if (experimentalUIThemingFeature.self().isEnabled()) {
1038+
if (visualDesignExperimentDataStore.experimentState.value.isEnabled) {
10391039
experimentalToolbarMockupBinding = when (settingsDataStore.omnibarPosition) {
10401040
TOP -> {
10411041
binding.bottomMockupExperimentalToolbar.appBarLayoutMockup.gone()

0 commit comments

Comments
 (0)