Skip to content

Commit 48f561b

Browse files
0nkojoshliebeCopilot
authored
Visual update: Apply new design to the exisiting omnibar (#6283)
Task/Issue URL: https://app.asana.com/1/137249556945/project/1207418217763355/task/1210552742244184?focus=true ### Description This PR uses the new UI design theme and applies it to the existing omnibar layout. ### Steps to test this PR _Input box animation_ - [x] Go to dev settings and enable the `visualUpdatesWithoutBottomBarFeature` feature flag - [x] Make sure the "Enable new UI with the navigation bar" in the Experimental UI settings is disabled, as that takes precedence - [x] Go to the browser - [x] Verify the new UI design theme is shown with the original omnibar layout (no bottom bar, toobar buttons next to the input box) - [x] Tap on the input box to add focus - [x] Notice the input box expands, hiding the toolbar button - [x] Tap on the back arrow - [x] Notice the input box contracts - [x] Go to the menu and select Find in Page - [x] Notice the input box expands and it becomes a search box - [x] Tap on the X to close it - [x] Notice the input box returns to the contracted state _Bottom potision smoke test_ - [x] Switch the omnibar to the bottom position in the Appearance settings - [x] Verify the omnibar looks and behaves as expected _Browser smoke testing_ - [x] Smoke test searching and website navigation --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1210662924836033 --------- Co-authored-by: Josh Leibstein <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 3dc3d62 commit 48f561b

File tree

58 files changed

+1780
-627
lines changed

Some content is hidden

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

58 files changed

+1780
-627
lines changed

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ import com.duckduckgo.browser.api.autocomplete.AutoCompleteSettings
220220
import com.duckduckgo.browser.api.brokensite.BrokenSiteContext
221221
import com.duckduckgo.common.test.CoroutineTestRule
222222
import com.duckduckgo.common.test.InstantSchedulersRule
223-
import com.duckduckgo.common.ui.experiments.visual.store.VisualDesignExperimentDataStore
223+
import com.duckduckgo.common.ui.experiments.visual.store.ExperimentalThemingDataStore
224224
import com.duckduckgo.common.ui.tabs.SwipingTabsFeature
225225
import com.duckduckgo.common.ui.tabs.SwipingTabsFeatureProvider
226226
import com.duckduckgo.common.utils.DispatcherProvider
@@ -557,7 +557,7 @@ class BrowserTabViewModelTest {
557557
private val mockDefaultBrowserPromptsExperiment: DefaultBrowserPromptsExperiment = mock()
558558
val mockStack: WebBackForwardList = mock()
559559

560-
private val mockVisualDesignExperimentDataStore: VisualDesignExperimentDataStore = mock()
560+
private val mockExperimentalThemingDataStore: ExperimentalThemingDataStore = mock()
561561
private val defaultVisualExperimentStateFlow = MutableStateFlow(false)
562562

563563
private val mockSiteErrorHandlerKillSwitch: SiteErrorHandlerKillSwitch = mock()
@@ -709,9 +709,6 @@ class BrowserTabViewModelTest {
709709
whenever(mockDefaultBrowserPromptsExperiment.showSetAsDefaultPopupMenuItem).thenReturn(
710710
defaultBrowserPromptsExperimentShowPopupMenuItemFlow,
711711
)
712-
whenever(mockVisualDesignExperimentDataStore.isExperimentEnabled).thenReturn(
713-
defaultVisualExperimentStateFlow,
714-
)
715712

716713
whenever(mockSiteErrorHandlerKillSwitch.self()).thenReturn(mockSiteErrorHandlerKillSwitchToggle)
717714

@@ -790,7 +787,7 @@ class BrowserTabViewModelTest {
790787
tabStatsBucketing = mockTabStatsBucketing,
791788
defaultBrowserPromptsExperiment = mockDefaultBrowserPromptsExperiment,
792789
swipingTabsFeature = swipingTabsFeatureProvider,
793-
visualDesignExperimentDataStore = mockVisualDesignExperimentDataStore,
790+
experimentalThemingDataStore = mockExperimentalThemingDataStore,
794791
siteErrorHandlerKillSwitch = mockSiteErrorHandlerKillSwitch,
795792
siteErrorHandler = mockSiteErrorHandler,
796793
siteHttpErrorHandler = mockSiteHttpErrorHandler,

app/src/androidTest/java/com/duckduckgo/app/browser/omnibar/animations/LottiePrivacyShieldAnimationHelperTest.kt

Lines changed: 28 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import com.duckduckgo.app.browser.senseofprotection.SenseOfProtectionExperiment
2323
import com.duckduckgo.app.global.model.PrivacyShield.MALICIOUS
2424
import com.duckduckgo.app.global.model.PrivacyShield.PROTECTED
2525
import com.duckduckgo.app.global.model.PrivacyShield.UNPROTECTED
26-
import com.duckduckgo.common.ui.experiments.visual.store.VisualDesignExperimentDataStore
26+
import com.duckduckgo.common.ui.experiments.visual.store.ExperimentalThemingDataStore
2727
import com.duckduckgo.common.ui.store.AppTheme
2828
import kotlinx.coroutines.flow.MutableStateFlow
2929
import kotlinx.coroutines.test.runTest
@@ -36,13 +36,13 @@ import org.mockito.kotlin.whenever
3636
class LottiePrivacyShieldAnimationHelperTest {
3737

3838
private val senseOfProtectionExperiment: SenseOfProtectionExperiment = mock()
39-
private val visualDesignExperimentDataStore: VisualDesignExperimentDataStore = mock()
39+
private val experimentalThemingDataStore: ExperimentalThemingDataStore = mock()
4040
private val enabledVisualExperimentStateFlow = MutableStateFlow(true)
4141
private val disabledVisualExperimentStateFlow = MutableStateFlow(false)
4242

4343
@Before
4444
fun setup() {
45-
whenever(visualDesignExperimentDataStore.isExperimentEnabled).thenReturn(
45+
whenever(experimentalThemingDataStore.isSingleOmnibarEnabled).thenReturn(
4646
disabledVisualExperimentStateFlow,
4747
)
4848
}
@@ -54,7 +54,7 @@ class LottiePrivacyShieldAnimationHelperTest {
5454
val holder: LottieAnimationView = mock()
5555
val appTheme: AppTheme = mock()
5656
whenever(appTheme.isLightModeEnabled()).thenReturn(true)
57-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
57+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
5858

5959
testee.setAnimationView(holder, PROTECTED)
6060

@@ -68,7 +68,7 @@ class LottiePrivacyShieldAnimationHelperTest {
6868
val holder: LottieAnimationView = mock()
6969
val appTheme: AppTheme = mock()
7070
whenever(appTheme.isLightModeEnabled()).thenReturn(false)
71-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
71+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
7272

7373
testee.setAnimationView(holder, PROTECTED)
7474

@@ -82,7 +82,7 @@ class LottiePrivacyShieldAnimationHelperTest {
8282
val holder: LottieAnimationView = mock()
8383
val appTheme: AppTheme = mock()
8484
whenever(appTheme.isLightModeEnabled()).thenReturn(true)
85-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
85+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
8686

8787
testee.setAnimationView(holder, UNPROTECTED)
8888

@@ -97,7 +97,7 @@ class LottiePrivacyShieldAnimationHelperTest {
9797
val holder: LottieAnimationView = mock()
9898
val appTheme: AppTheme = mock()
9999
whenever(appTheme.isLightModeEnabled()).thenReturn(false)
100-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
100+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
101101

102102
testee.setAnimationView(holder, UNPROTECTED)
103103

@@ -112,7 +112,7 @@ class LottiePrivacyShieldAnimationHelperTest {
112112
val holder: LottieAnimationView = mock()
113113
val appTheme: AppTheme = mock()
114114
whenever(appTheme.isLightModeEnabled()).thenReturn(true)
115-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
115+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
116116

117117
testee.setAnimationView(holder, MALICIOUS)
118118

@@ -127,7 +127,7 @@ class LottiePrivacyShieldAnimationHelperTest {
127127
val holder: LottieAnimationView = mock()
128128
val appTheme: AppTheme = mock()
129129
whenever(appTheme.isLightModeEnabled()).thenReturn(false)
130-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
130+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
131131

132132
testee.setAnimationView(holder, MALICIOUS)
133133

@@ -144,7 +144,7 @@ class LottiePrivacyShieldAnimationHelperTest {
144144
val appTheme: AppTheme = mock()
145145
whenever(appTheme.isLightModeEnabled()).thenReturn(true)
146146

147-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
147+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
148148

149149
testee.setAnimationView(holder, PROTECTED)
150150

@@ -160,7 +160,7 @@ class LottiePrivacyShieldAnimationHelperTest {
160160
val appTheme: AppTheme = mock()
161161
whenever(appTheme.isLightModeEnabled()).thenReturn(true)
162162

163-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
163+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
164164

165165
testee.setAnimationView(holder, UNPROTECTED)
166166

@@ -176,7 +176,7 @@ class LottiePrivacyShieldAnimationHelperTest {
176176
val appTheme: AppTheme = mock()
177177
whenever(appTheme.isLightModeEnabled()).thenReturn(false)
178178

179-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
179+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
180180

181181
testee.setAnimationView(holder, PROTECTED)
182182

@@ -192,7 +192,7 @@ class LottiePrivacyShieldAnimationHelperTest {
192192
val appTheme: AppTheme = mock()
193193
whenever(appTheme.isLightModeEnabled()).thenReturn(false)
194194

195-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
195+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
196196

197197
testee.setAnimationView(holder, UNPROTECTED)
198198

@@ -209,7 +209,7 @@ class LottiePrivacyShieldAnimationHelperTest {
209209
val appTheme: AppTheme = mock()
210210
whenever(appTheme.isLightModeEnabled()).thenReturn(true)
211211

212-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
212+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
213213

214214
testee.setAnimationView(holder, PROTECTED)
215215

@@ -218,36 +218,36 @@ class LottiePrivacyShieldAnimationHelperTest {
218218

219219
@SuppressLint("DenyListedApi")
220220
@Test
221-
fun whenLightModeAndProtectedAndSelfEnabledAndShouldShowNewVisualDesignShieldThenUseExperimentAssets() = runTest {
221+
fun whenLightModeAndProtectedAndNewSignleOmnibarDesignEnabledShowCheckmarkAssets() = runTest {
222222
whenever(senseOfProtectionExperiment.shouldShowNewPrivacyShield()).thenReturn(false)
223-
whenever(visualDesignExperimentDataStore.isExperimentEnabled).thenReturn(
223+
whenever(experimentalThemingDataStore.isSingleOmnibarEnabled).thenReturn(
224224
enabledVisualExperimentStateFlow,
225225
)
226226

227227
val holder: LottieAnimationView = mock()
228228
val appTheme: AppTheme = mock()
229229
whenever(appTheme.isLightModeEnabled()).thenReturn(true)
230230

231-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
231+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
232232

233233
testee.setAnimationView(holder, PROTECTED)
234234

235-
verify(holder).setAnimation(R.raw.protected_shield_visual_updates)
235+
verify(holder).setAnimation(R.raw.protected_shield_new_design)
236236
}
237237

238238
@SuppressLint("DenyListedApi")
239239
@Test
240-
fun whenLightModeAndUnprotectedAndSelfEnabledAndShouldShowNewVisualDesignShieldThenUseExperimentAssets() = runTest {
240+
fun whenLightModeAndUnprotectedAndNewSignleOmnibarDesignEnabledThenUseExperimentAssets() = runTest {
241241
whenever(senseOfProtectionExperiment.shouldShowNewPrivacyShield()).thenReturn(false)
242-
whenever(visualDesignExperimentDataStore.isExperimentEnabled).thenReturn(
242+
whenever(experimentalThemingDataStore.isSingleOmnibarEnabled).thenReturn(
243243
enabledVisualExperimentStateFlow,
244244
)
245245

246246
val holder: LottieAnimationView = mock()
247247
val appTheme: AppTheme = mock()
248248
whenever(appTheme.isLightModeEnabled()).thenReturn(true)
249249

250-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
250+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
251251

252252
testee.setAnimationView(holder, UNPROTECTED)
253253

@@ -256,59 +256,39 @@ class LottiePrivacyShieldAnimationHelperTest {
256256

257257
@SuppressLint("DenyListedApi")
258258
@Test
259-
fun whenDarkModeAndProtectedAndSelfEnabledAndShouldShowNewVisualDesignShieldThenUseExperimentAssets() = runTest {
259+
fun whenDarkModeAndProtectedAndNewSignleOmnibarDesignEnabledShowCheckmarkAssets() = runTest {
260260
whenever(senseOfProtectionExperiment.shouldShowNewPrivacyShield()).thenReturn(false)
261-
whenever(visualDesignExperimentDataStore.isExperimentEnabled).thenReturn(
261+
whenever(experimentalThemingDataStore.isSingleOmnibarEnabled).thenReturn(
262262
enabledVisualExperimentStateFlow,
263263
)
264264

265265
val holder: LottieAnimationView = mock()
266266
val appTheme: AppTheme = mock()
267267
whenever(appTheme.isLightModeEnabled()).thenReturn(false)
268268

269-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
269+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
270270

271271
testee.setAnimationView(holder, PROTECTED)
272272

273-
verify(holder).setAnimation(R.raw.dark_protected_shield_visual_updates)
273+
verify(holder).setAnimation(R.raw.dark_protected_shield_new_design)
274274
}
275275

276276
@SuppressLint("DenyListedApi")
277277
@Test
278-
fun whenDarkModeAndUnprotectedAndSelfEnabledAndShouldShowNewVisualDesignShieldThenUseExperimentAssets() = runTest {
278+
fun whenDarkModeAndUnprotectedAndNewSignleOmnibarDesignEnabledThenUseExperimentAssets() = runTest {
279279
whenever(senseOfProtectionExperiment.shouldShowNewPrivacyShield()).thenReturn(false)
280-
whenever(visualDesignExperimentDataStore.isExperimentEnabled).thenReturn(
280+
whenever(experimentalThemingDataStore.isSingleOmnibarEnabled).thenReturn(
281281
enabledVisualExperimentStateFlow,
282282
)
283283

284284
val holder: LottieAnimationView = mock()
285285
val appTheme: AppTheme = mock()
286286
whenever(appTheme.isLightModeEnabled()).thenReturn(false)
287287

288-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
288+
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, experimentalThemingDataStore)
289289

290290
testee.setAnimationView(holder, UNPROTECTED)
291291

292292
verify(holder).setAnimation(R.raw.dark_unprotected_shield_visual_updates)
293293
}
294-
295-
@SuppressLint("DenyListedApi")
296-
@Test
297-
fun whenLightModeAndProtectedAndSelfEnabledAndShouldShowNotNewVisualDesignShieldThenUseNonExperimentAssets() = runTest {
298-
whenever(senseOfProtectionExperiment.shouldShowNewPrivacyShield()).thenReturn(false)
299-
whenever(senseOfProtectionExperiment.isUserEnrolledInAVariantAndExperimentEnabled()).thenReturn(false)
300-
whenever(visualDesignExperimentDataStore.isExperimentEnabled).thenReturn(
301-
disabledVisualExperimentStateFlow,
302-
)
303-
304-
val holder: LottieAnimationView = mock()
305-
val appTheme: AppTheme = mock()
306-
whenever(appTheme.isLightModeEnabled()).thenReturn(true)
307-
308-
val testee = LottiePrivacyShieldAnimationHelper(appTheme, senseOfProtectionExperiment, visualDesignExperimentDataStore)
309-
310-
testee.setAnimationView(holder, PROTECTED)
311-
312-
verify(holder).setAnimation(R.raw.protected_shield)
313-
}
314294
}

app/src/androidTest/java/com/duckduckgo/espresso/BasicJourneyTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import androidx.test.ext.junit.rules.activityScenarioRule
2424
import androidx.test.ext.junit.runners.AndroidJUnit4
2525
import com.duckduckgo.app.browser.BrowserActivity
2626
import com.duckduckgo.app.browser.R
27+
import org.hamcrest.Matchers.allOf
2728
import org.junit.Rule
2829
import org.junit.Test
2930
import org.junit.runner.RunWith
@@ -45,7 +46,7 @@ class BasicJourneyTest {
4546
onView(isRoot()).perform(waitForView(withId(R.id.browserMenu)))
4647

4748
// tap on PopupMenu
48-
onView(withId(R.id.browserMenu)).perform(click())
49+
onView(allOf(withId(R.id.browserMenu), isClickable())).perform(click())
4950

5051
// check that the forward arrow is visible
5152
onView(withId(R.id.forwardMenuItem)).check(matches(isDisplayed()))

app/src/androidTest/java/com/duckduckgo/espresso/DaxDialogsJourneyTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import androidx.test.filters.FlakyTest
2727
import androidx.test.filters.SdkSuppress
2828
import com.duckduckgo.app.browser.R
2929
import com.duckduckgo.app.onboarding.ui.OnboardingActivity
30+
import org.hamcrest.Matchers.allOf
3031
import org.junit.Rule
3132
import org.junit.Test
3233
import org.junit.runner.RunWith
@@ -54,7 +55,7 @@ class DaxDialogsJourneyTest {
5455
onView(withId(R.id.continueButton)).perform(click())
5556

5657
onView(isRoot()).perform(waitForView(withId(R.id.browserMenu)))
57-
onView(withId(R.id.browserMenu)).perform(click())
58+
onView(allOf(withId(R.id.browserMenu), isClickable())).perform(click())
5859

5960
onView(withId(R.id.forwardMenuItem)).check(matches(isDisplayed()))
6061
}

app/src/androidTest/java/com/duckduckgo/espresso/privacy/RequestBlockingTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import com.duckduckgo.espresso.*
3434
import com.duckduckgo.privacy.config.impl.network.JSONObjectAdapter
3535
import com.squareup.moshi.JsonAdapter
3636
import com.squareup.moshi.Moshi
37+
import org.hamcrest.Matchers.allOf
3738
import org.junit.Assert.assertEquals
3839
import org.junit.Assert.assertTrue
3940
import org.junit.Rule
@@ -86,7 +87,7 @@ class RequestBlockingTest {
8687
val idlingResourceForDisableProtections = WebViewIdlingResource(webView!!)
8788
IdlingRegistry.getInstance().register(idlingResourceForDisableProtections)
8889

89-
onView(withId(R.id.browserMenu)).perform(click())
90+
onView(allOf(withId(R.id.browserMenu), isClickable())).perform(click())
9091
onView(isRoot()).perform(waitForView(withId(R.id.privacyProtectionMenuItem)))
9192
onView(withId(R.id.privacyProtectionMenuItem)).perform(click())
9293

app/src/androidTest/java/com/duckduckgo/espresso/privacy/SurrogatesTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import com.duckduckgo.espresso.*
3232
import com.duckduckgo.privacy.config.impl.network.JSONObjectAdapter
3333
import com.squareup.moshi.JsonAdapter
3434
import com.squareup.moshi.Moshi
35+
import org.hamcrest.Matchers.allOf
3536
import org.junit.Assert.assertFalse
3637
import org.junit.Assert.assertTrue
3738
import org.junit.Rule
@@ -93,7 +94,7 @@ class SurrogatesTest {
9394
val idlingResourceForDisableProtections = WebViewIdlingResource(webView!!)
9495
IdlingRegistry.getInstance().register(idlingResourceForDisableProtections)
9596

96-
onView(withId(R.id.browserMenu)).perform(ViewActions.click())
97+
onView(allOf(withId(R.id.browserMenu), isClickable())).perform(ViewActions.click())
9798
onView(isRoot()).perform(waitForView(withId(R.id.privacyProtectionMenuItem)))
9899
onView(withId(R.id.privacyProtectionMenuItem)).perform(ViewActions.click())
99100

0 commit comments

Comments
 (0)