Skip to content

Commit f2c16b7

Browse files
authored
Bottom Navigation (#778)
* added simple bottom navigation bar * adding a new behaviour that hides the bottom bar when scrolling down the content, but shows it when scrolling up * cleaning up the bottombar, proper inheritance * added tabswitcher button to bottomnavigationbar * enabling buttons in bottom bar based on state * removing all scrolling layout flags from the xml, we use the OmnibarScrolling for that * adding snapping behaviour to the bottom bar * cleaning up the behaviour * added missing menu for browser activity * added experiment decorator that will handle UI for different experiments * implemented decorator variants as per current designs * PopupMenu also knows about the experiment we are running * added swipe to refresh * using bottom bar for now * cleaning up the code * cleaning up * binding all buttons in bottom bar * added popupmenu that anchors to the bottombar * we can now decorate the toolbar based on the experiment * added experiment variants for the bottom navigation * always showing the omnibar background * no need for old custom webview, scroll is already properly supported * removing pull to refresh for now * using the search experiment by default * removed the second experiment, binding popup and bottom bar click listeners * added new icons for bottom bar and popup menu * popup menu now also respect light / dark theme * using new color attribute for dark / light theme * ignoring variant tests for now, we are lying * bottom bar is only visible if the omnibar has no focus * the search icon is shown only when the serp has focus, and the privacy grade works the opposite way * cleaning up the tabs switcher and removing its animation * updating version for internal release * proper padding of items in bottom bar * remove unused file * add new tabs screen * we have a new activity to show tabs with the experiment * we only use the new activity if the experiment is on * more ui work * Update popup_window_browser_bottom_tab_menu.xml checkbox should also be tinted * all toolbars should be the same * ui tweaks with Robert * improved elevation for the bottom bar * ensure keyboard is not shown if the omnibar does not have focus * search icon / privacy grade should be properly updated * ensure grade button is hidden * added pixels to track experiment engagement * added missing fire icon pixel * ensure we also animate the bottom bar after animating the toolbar * moving search next to the fire icon * added proper background for the bottom bar * ensure that the widget cta is sitting in top of the bottom navigation bar * added delay to keyboard animation so it doesn't look wonky * ensure cta container respects the bottom bar height * remove the animation when hiding the keyboard * make sure that the first time the container shows we respect the bottom bar height * updated pixel values for the experiment * swapped order of icons in bottom bar * adding tests for the variant manager * updated version for release * fixed tds hast test * fixed etag test * enable for now * improved color selection for api 21 * fixing vector drawables so they show the proper path * these tests should be running * addressing some PR comments * cleaning up double assignation * clean up some comments * more code cleanup * swap experiment with feature for readibility * revert experiments to original values, it's not this PR responsibility to remove them * updating experiment names * proper reference * ensure all pixels trigger the variant key * revert wrong variant change * cleaning up colors and selectors * no need for this * cleaning up the toolbar, make sure we show the icons for both experiments * returning experiments back to original distibution * hide new menu buttons when in bottomnav mode * no need for this selector because we use theming now * ensure the omnibar is using full width * ensure widget container is shown properly * removing the behaviour so the omnibar is properly updated * revert this to what it was * revert this to fix tests * proper style for checkbox * cleaning up state and visibility of the toolbar * updated etag for tests * revert tdstest changes * cleanup references * add missing pixel after opening a new tab * move this to the decorator * duplicate call * better method naming * remove duplicate call for this method * ensure bottombar is visible after opening a new tab * another redundant call * renaming bottom bar only icons * no longer used * proper icon name * removing unnecessary method * fix color reference pointing to wrong attribute
1 parent 0be58cf commit f2c16b7

File tree

63 files changed

+1938
-418
lines changed

Some content is hidden

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

63 files changed

+1938
-418
lines changed

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -611,16 +611,18 @@ class BrowserTabViewModelTest {
611611
}
612612

613613
@Test
614-
fun whenBrowserNotShownAndOmnibarInputDoesNotHaveFocusThenPrivacyGradeIsNotShown() {
614+
fun whenOmnibarDoesNotHaveFocusThenPrivacyGradeIsShownAndSearchIconIsHidden() {
615615
testee.onOmnibarInputStateChanged(query = "", hasFocus = false, hasQueryChanged = false)
616-
assertFalse(browserViewState().showPrivacyGrade)
616+
assertTrue(browserViewState().showPrivacyGrade)
617+
assertFalse(browserViewState().showSearchIcon)
617618
}
618619

619620
@Test
620-
fun whenBrowserShownAndOmnibarInputDoesNotHaveFocusThenPrivacyGradeIsShown() {
621+
fun whenBrowserShownAndOmnibarInputDoesNotHaveFocusThenPrivacyGradeIsShownAndSearchIconIsHidden() {
621622
testee.onUserSubmittedQuery("foo")
622623
testee.onOmnibarInputStateChanged(query = "", hasFocus = false, hasQueryChanged = false)
623624
assertTrue(browserViewState().showPrivacyGrade)
625+
assertFalse(browserViewState().showSearchIcon)
624626
}
625627

626628
@Test
@@ -630,10 +632,11 @@ class BrowserTabViewModelTest {
630632
}
631633

632634
@Test
633-
fun whenBrowserShownAndOmnibarInputHasFocusThenPrivacyGradeIsShown() {
635+
fun whenBrowserShownAndOmnibarInputHasFocusThenSearchIconIsShownAndPrivacyGradeIsHidden() {
634636
testee.onUserSubmittedQuery("foo")
635637
testee.onOmnibarInputStateChanged("", true, hasQueryChanged = false)
636-
assertTrue(browserViewState().showPrivacyGrade)
638+
assertFalse(browserViewState().showPrivacyGrade)
639+
assertTrue(browserViewState().showSearchIcon)
637640
}
638641

639642
@Test

app/src/androidTest/java/com/duckduckgo/app/statistics/VariantManagerTest.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,23 @@ class VariantManagerTest {
4343
assertEquals(0, variant.features.size)
4444
}
4545

46+
// Bottom Bar Navigation Experiment
47+
48+
@Test
49+
fun bottomBarNavigationControlVariantIsActiveAndHasNoFeatures() {
50+
val variant = variants.first { it.key == "mm" }
51+
assertEqualsDouble(1.0, variant.weight)
52+
assertEquals(0, variant.features.size)
53+
}
54+
55+
@Test
56+
fun bottomBarNavigationVariantIsActiveAndHasBottomBarNavigationFeature() {
57+
val variant = variants.first { it.key == "mn" }
58+
assertEqualsDouble(1.0, variant.weight)
59+
assertEquals(1, variant.features.size)
60+
assertTrue(variant.hasFeature(BottomBarNavigation))
61+
}
62+
4663
@Test
4764
fun verifyNoDuplicateVariantNames() {
4865
val existingNames = mutableSetOf<String>()

app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,10 @@
234234
android:name="com.duckduckgo.app.tabs.ui.TabSwitcherActivity"
235235
android:label="@string/tabActivityTitle" />
236236

237+
<activity
238+
android:name="com.duckduckgo.app.tabs.ui.TabSwitcherBottomBarFeatureActivity"
239+
android:label="@string/tabActivityTitle" />
240+
237241
<activity
238242
android:name="com.duckduckgo.app.privacy.ui.PrivacyDashboardActivity"
239243
android:label="@string/privacyDashboardActivityTitle"

app/src/main/java/com/duckduckgo/app/about/AboutDuckDuckGoActivity.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,14 @@ class AboutDuckDuckGoActivity : DuckDuckGoActivity() {
3131
override fun onCreate(savedInstanceState: Bundle?) {
3232
super.onCreate(savedInstanceState)
3333
setContentView(R.layout.activity_about_duck_duck_go)
34-
configureActionBar()
34+
setupToolbar(toolbar)
3535

3636
learnMoreLink.setOnClickListener {
3737
startActivity(BrowserActivity.intent(this, Url.ABOUT))
3838
finish()
3939
}
4040
}
4141

42-
private fun configureActionBar() {
43-
setSupportActionBar(toolbar)
44-
supportActionBar?.setDisplayHomeAsUpEnabled(true)
45-
}
46-
4742
companion object {
4843
fun intent(context: Context): Intent {
4944
return Intent(context, AboutDuckDuckGoActivity::class.java)

app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksActivity.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class BookmarksActivity : DuckDuckGoActivity() {
5959
override fun onCreate(savedInstanceState: Bundle?) {
6060
super.onCreate(savedInstanceState)
6161
setContentView(R.layout.activity_bookmarks)
62-
setupActionBar()
62+
setupToolbar(toolbar)
6363
setupBookmarksRecycler()
6464
observeViewModel()
6565
}
@@ -72,11 +72,6 @@ class BookmarksActivity : DuckDuckGoActivity() {
7272
recycler.addItemDecoration(separator)
7373
}
7474

75-
private fun setupActionBar() {
76-
setSupportActionBar(toolbar)
77-
supportActionBar?.setDisplayHomeAsUpEnabled(true)
78-
}
79-
8075
private fun observeViewModel() {
8176
viewModel.viewState.observe(this, Observer<BookmarksViewModel.ViewState> { viewState ->
8277
viewState?.let {

app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteActivity.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import kotlinx.android.synthetic.main.content_broken_sites.*
3131
import kotlinx.android.synthetic.main.include_toolbar.*
3232
import org.jetbrains.anko.longToast
3333

34-
3534
class BrokenSiteActivity : DuckDuckGoActivity() {
3635
private val viewModel: BrokenSiteViewModel by bindViewModel()
3736

@@ -40,17 +39,12 @@ class BrokenSiteActivity : DuckDuckGoActivity() {
4039
setContentView(R.layout.activity_broken_site)
4140
configureListeners()
4241
configureObservers()
43-
setupActionBar()
42+
setupToolbar(toolbar)
4443
if (savedInstanceState == null) {
4544
consumeIntentExtra()
4645
}
4746
}
4847

49-
private fun setupActionBar() {
50-
setSupportActionBar(toolbar)
51-
supportActionBar?.setDisplayHomeAsUpEnabled(true)
52-
}
53-
5448
private fun consumeIntentExtra() {
5549
val url = intent.getStringExtra(URL_EXTRA)
5650
val blockedTrackers = intent.getStringExtra(BLOCKED_TRACKERS_EXTRA)

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@ import android.view.LayoutInflater
2424
import android.view.View
2525
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
2626
import android.widget.PopupWindow
27+
import com.duckduckgo.app.statistics.Variant
28+
import com.duckduckgo.app.statistics.VariantManager
2729

28-
class BrowserPopupMenu : PopupWindow {
30+
class BrowserPopupMenu(layoutInflater: LayoutInflater, variant: Variant, view: View = inflate(layoutInflater, variant)) :
31+
PopupWindow(view, WRAP_CONTENT, WRAP_CONTENT, true) {
2932

30-
constructor(layoutInflater: LayoutInflater, view: View = BrowserPopupMenu.inflate(layoutInflater))
31-
: super(view, WRAP_CONTENT, WRAP_CONTENT, true) {
33+
// popupwindow gets stuck on the screen on API 22 (tested on 23) without a background
34+
// color. Adding it however garbles the elevation so we cannot have elevation here.
3235

36+
init {
3337
if (SDK_INT <= 22) {
34-
// popupwindow gets stuck on the screen on API 22 (tested on 23) without a background
35-
// color. Adding it however garbles the elevation so we cannot have elevation here.
3638
setBackgroundDrawable(ColorDrawable(Color.WHITE))
3739
} else {
3840
elevation = 6.toFloat()
@@ -59,10 +61,21 @@ class BrowserPopupMenu : PopupWindow {
5961

6062
private const val margin = 30
6163

62-
fun inflate(layoutInflater: LayoutInflater): View {
64+
fun inflate(layoutInflater: LayoutInflater, variant: Variant): View {
65+
return if (variant.hasFeature(VariantManager.VariantFeature.BottomBarNavigation)) {
66+
inflateBottomBarWithSearchFeature(layoutInflater)
67+
} else {
68+
inflateToolbarOnly(layoutInflater)
69+
}
70+
}
71+
72+
private fun inflateToolbarOnly(layoutInflater: LayoutInflater): View {
6373
return layoutInflater.inflate(R.layout.popup_window_browser_menu, null)
6474
}
6575

76+
private fun inflateBottomBarWithSearchFeature(layoutInflater: LayoutInflater): View {
77+
return layoutInflater.inflate(R.layout.popup_window_browser_bottom_tab_menu, null)
78+
}
6679
}
6780
}
6881

0 commit comments

Comments
 (0)