Skip to content

Commit c704c01

Browse files
authored
Add Buck onboarding implementation (#6491)
Task/Issue URL: https://app.asana.com/1/137249556945/project/1205648422731273/task/1210925181973291?focus=true ### Description This PR adds an experimental version of pre-onboarding experience with a refreshed design. It is currently disabled, so no changes are visible by default. ### Steps to test this PR To enable Buck pre-browser onboarding, edit OnboardingPageManager.kt and make the following change: ``` - pages.add(WelcomePageBlueprint) + pages.add(BuckWelcomePageBlueprint) ``` _Feature 1_ - [ ] - [ ] ### UI changes | Before | After | | ------ | ----- | !(Upload before screenshot)|(Upload after screenshot)|
1 parent de42a47 commit c704c01

Some content is hidden

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

42 files changed

+2227
-60
lines changed

app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingPageBuilder.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,25 @@
1616

1717
package com.duckduckgo.app.onboarding.ui
1818

19+
import com.duckduckgo.app.onboarding.ui.page.BuckWelcomePage
1920
import com.duckduckgo.app.onboarding.ui.page.DefaultBrowserPage
2021
import com.duckduckgo.app.onboarding.ui.page.WelcomePage
2122

2223
interface OnboardingPageBuilder {
23-
fun buildExperimentWelcomePage(): WelcomePage
24+
fun buildWelcomePage(): WelcomePage
25+
fun buildBuckWelcomePage(): BuckWelcomePage
2426
fun buildDefaultBrowserPage(): DefaultBrowserPage
2527

2628
sealed class OnboardingPageBlueprint {
2729
data object DefaultBrowserBlueprint : OnboardingPageBlueprint()
28-
data object ExperimentWelcomeBluePrint : OnboardingPageBlueprint()
30+
data object WelcomePageBlueprint : OnboardingPageBlueprint()
31+
data object BuckWelcomePageBlueprint : OnboardingPageBlueprint()
2932
}
3033
}
3134

3235
class OnboardingFragmentPageBuilder : OnboardingPageBuilder {
3336

34-
override fun buildExperimentWelcomePage() = WelcomePage()
37+
override fun buildWelcomePage() = WelcomePage()
38+
override fun buildBuckWelcomePage() = BuckWelcomePage()
3539
override fun buildDefaultBrowserPage() = DefaultBrowserPage()
3640
}

app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingPageManager.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ package com.duckduckgo.app.onboarding.ui
1919
import com.duckduckgo.app.browser.defaultbrowsing.DefaultBrowserDetector
2020
import com.duckduckgo.app.global.DefaultRoleBrowserDialog
2121
import com.duckduckgo.app.onboarding.ui.OnboardingPageBuilder.OnboardingPageBlueprint
22+
import com.duckduckgo.app.onboarding.ui.OnboardingPageBuilder.OnboardingPageBlueprint.BuckWelcomePageBlueprint
2223
import com.duckduckgo.app.onboarding.ui.OnboardingPageBuilder.OnboardingPageBlueprint.DefaultBrowserBlueprint
23-
import com.duckduckgo.app.onboarding.ui.OnboardingPageBuilder.OnboardingPageBlueprint.ExperimentWelcomeBluePrint
24+
import com.duckduckgo.app.onboarding.ui.OnboardingPageBuilder.OnboardingPageBlueprint.WelcomePageBlueprint
25+
import com.duckduckgo.app.onboarding.ui.page.BuckWelcomePage
2426
import com.duckduckgo.app.onboarding.ui.page.DefaultBrowserPage
2527
import com.duckduckgo.app.onboarding.ui.page.OnboardingPageFragment
2628
import com.duckduckgo.app.onboarding.ui.page.WelcomePage
@@ -44,7 +46,7 @@ class OnboardingPageManagerWithTrackerBlocking(
4446
override fun buildPageBlueprints() {
4547
pages.clear()
4648

47-
pages.add(ExperimentWelcomeBluePrint)
49+
pages.add(WelcomePageBlueprint)
4850

4951
if (shouldShowDefaultBrowserPage()) {
5052
pages.add((DefaultBrowserBlueprint))
@@ -53,7 +55,8 @@ class OnboardingPageManagerWithTrackerBlocking(
5355

5456
override fun buildPage(position: Int): OnboardingPageFragment? {
5557
return when (pages.getOrNull(position)) {
56-
is ExperimentWelcomeBluePrint -> buildExperimentWelcomePage()
58+
is WelcomePageBlueprint -> buildWelcomePage()
59+
is BuckWelcomePageBlueprint -> buildBuckWelcomePage()
5760
is DefaultBrowserBlueprint -> buildDefaultBrowserPage()
5861
else -> null
5962
}
@@ -69,7 +72,11 @@ class OnboardingPageManagerWithTrackerBlocking(
6972
return onboardingPageBuilder.buildDefaultBrowserPage()
7073
}
7174

72-
private fun buildExperimentWelcomePage(): WelcomePage {
73-
return onboardingPageBuilder.buildExperimentWelcomePage()
75+
private fun buildWelcomePage(): WelcomePage {
76+
return onboardingPageBuilder.buildWelcomePage()
77+
}
78+
79+
private fun buildBuckWelcomePage(): BuckWelcomePage {
80+
return onboardingPageBuilder.buildBuckWelcomePage()
7481
}
7582
}

app/src/main/java/com/duckduckgo/app/onboarding/ui/page/BuckWelcomePage.kt

Lines changed: 633 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2025 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.app.onboarding.ui.page
18+
19+
enum class PreOnboardingDialogType {
20+
INITIAL_REINSTALL_USER,
21+
INITIAL,
22+
SKIP_ONBOARDING_OPTION,
23+
COMPARISON_CHART,
24+
ADDRESS_BAR_POSITION,
25+
}

app/src/main/java/com/duckduckgo/app/onboarding/ui/page/WelcomePage.kt

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ import android.app.Activity
2222
import android.content.Intent
2323
import android.graphics.Color
2424
import android.os.Bundle
25-
import android.view.LayoutInflater
2625
import android.view.View
27-
import android.view.ViewGroup
2826
import android.view.WindowManager
2927
import androidx.activity.result.contract.ActivityResultContracts
3028
import androidx.core.view.ViewCompat
@@ -39,15 +37,14 @@ import androidx.transition.TransitionManager
3937
import com.duckduckgo.anvil.annotations.InjectWith
4038
import com.duckduckgo.app.browser.R
4139
import com.duckduckgo.app.browser.databinding.ContentOnboardingWelcomePageBinding
42-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.ADDRESS_BAR_POSITION
43-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.COMPARISON_CHART
44-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.INITIAL
45-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.INITIAL_REINSTALL_USER
46-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.SKIP_ONBOARDING_OPTION
40+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.ADDRESS_BAR_POSITION
41+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.COMPARISON_CHART
42+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.INITIAL
43+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.INITIAL_REINSTALL_USER
44+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.SKIP_ONBOARDING_OPTION
4745
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.Finish
4846
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.OnboardingSkipped
4947
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.SetAddressBarPositionOptions
50-
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.SetBackgroundResource
5148
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.ShowAddressBarPositionDialog
5249
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.ShowComparisonChart
5350
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.ShowDefaultBrowserDialog
@@ -97,13 +94,9 @@ class WelcomePage : OnboardingPageFragment(R.layout.content_onboarding_welcome_p
9794
}
9895
}
9996

100-
override fun onCreateView(
101-
inflater: LayoutInflater,
102-
container: ViewGroup?,
103-
savedInstanceState: Bundle?,
104-
): View {
105-
val binding = ContentOnboardingWelcomePageBinding.inflate(inflater, container, false)
106-
viewModel.setBackgroundResource(appTheme.isLightModeEnabled())
97+
override fun onCreate(savedInstanceState: Bundle?) {
98+
super.onCreate(savedInstanceState)
99+
107100
viewModel.commands.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED).onEach {
108101
when (it) {
109102
is ShowInitialReinstallUserDialog -> configureDaxCta(INITIAL_REINSTALL_USER)
@@ -114,11 +107,9 @@ class WelcomePage : OnboardingPageFragment(R.layout.content_onboarding_welcome_p
114107
is ShowAddressBarPositionDialog -> configureDaxCta(ADDRESS_BAR_POSITION)
115108
is Finish -> onContinuePressed()
116109
is OnboardingSkipped -> onSkipPressed()
117-
is SetBackgroundResource -> setBackgroundRes(it.backgroundRes)
118110
is SetAddressBarPositionOptions -> setAddressBarPositionOptions(it.defaultOption)
119111
}
120112
}.launchIn(lifecycleScope)
121-
return binding.root
122113
}
123114

124115
private fun setAddressBarPositionOptions(defaultOption: Boolean) {
@@ -140,6 +131,15 @@ class WelcomePage : OnboardingPageFragment(R.layout.content_onboarding_welcome_p
140131
savedInstanceState: Bundle?,
141132
) {
142133
super.onViewCreated(view, savedInstanceState)
134+
135+
setBackgroundRes(
136+
if (appTheme.isLightModeEnabled()) {
137+
R.drawable.onboarding_background_bitmap_light
138+
} else {
139+
R.drawable.onboarding_background_bitmap_dark
140+
},
141+
)
142+
143143
requestNotificationsPermissions()
144144
setSkipAnimationListener()
145145
}
@@ -379,15 +379,6 @@ class WelcomePage : OnboardingPageFragment(R.layout.content_onboarding_welcome_p
379379
}
380380

381381
companion object {
382-
383-
enum class PreOnboardingDialogType {
384-
INITIAL_REINSTALL_USER,
385-
INITIAL,
386-
SKIP_ONBOARDING_OPTION,
387-
COMPARISON_CHART,
388-
ADDRESS_BAR_POSITION,
389-
}
390-
391382
private const val MIN_ALPHA = 0f
392383
private const val MAX_ALPHA = 1f
393384
private const val ANIMATION_DURATION = 400L

app/src/main/java/com/duckduckgo/app/onboarding/ui/page/WelcomePageViewModel.kt

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,20 @@ package com.duckduckgo.app.onboarding.ui.page
1919
import android.annotation.SuppressLint
2020
import android.content.Context
2121
import android.content.Intent
22-
import androidx.annotation.DrawableRes
2322
import androidx.lifecycle.ViewModel
2423
import androidx.lifecycle.viewModelScope
2524
import com.duckduckgo.anvil.annotations.ContributesViewModel
26-
import com.duckduckgo.app.browser.R
2725
import com.duckduckgo.app.browser.omnibar.model.OmnibarPosition
2826
import com.duckduckgo.app.global.DefaultRoleBrowserDialog
2927
import com.duckduckgo.app.global.install.AppInstallStore
30-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType
31-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.ADDRESS_BAR_POSITION
32-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.COMPARISON_CHART
33-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.INITIAL
34-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.INITIAL_REINSTALL_USER
35-
import com.duckduckgo.app.onboarding.ui.page.WelcomePage.Companion.PreOnboardingDialogType.SKIP_ONBOARDING_OPTION
28+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.ADDRESS_BAR_POSITION
29+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.COMPARISON_CHART
30+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.INITIAL
31+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.INITIAL_REINSTALL_USER
32+
import com.duckduckgo.app.onboarding.ui.page.PreOnboardingDialogType.SKIP_ONBOARDING_OPTION
3633
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.Finish
3734
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.OnboardingSkipped
3835
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.SetAddressBarPositionOptions
39-
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.SetBackgroundResource
4036
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.ShowAddressBarPositionDialog
4137
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.ShowComparisonChart
4238
import com.duckduckgo.app.onboarding.ui.page.WelcomePageViewModel.Command.ShowDefaultBrowserDialog
@@ -96,7 +92,6 @@ class WelcomePageViewModel @Inject constructor(
9692
data object ShowAddressBarPositionDialog : Command
9793
data object Finish : Command
9894
data object OnboardingSkipped : Command
99-
data class SetBackgroundResource(@DrawableRes val backgroundRes: Int) : Command
10095
data class SetAddressBarPositionOptions(val defaultOption: Boolean) : Command
10196
}
10297

@@ -227,17 +222,6 @@ class WelcomePageViewModel @Inject constructor(
227222
}
228223
}
229224

230-
fun setBackgroundResource(lightModeEnabled: Boolean) {
231-
val backgroundRes = if (lightModeEnabled) {
232-
R.drawable.onboarding_background_bitmap_light
233-
} else {
234-
R.drawable.onboarding_background_bitmap_dark
235-
}
236-
viewModelScope.launch {
237-
_commands.send(SetBackgroundResource(backgroundRes))
238-
}
239-
}
240-
241225
fun onAddressBarPositionOptionSelected(defaultOption: Boolean) {
242226
defaultAddressBarPosition = defaultOption
243227
viewModelScope.launch {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ Copyright (c) 2025 DuckDuckGo
3+
~
4+
~ Licensed under the Apache License, Version 2.0 (the "License");
5+
~ you may not use this file except in compliance with the License.
6+
~ You may obtain a copy of the License at
7+
~
8+
~ http://www.apache.org/licenses/LICENSE-2.0
9+
~
10+
~ Unless required by applicable law or agreed to in writing, software
11+
~ distributed under the License is distributed on an "AS IS" BASIS,
12+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
~ See the License for the specific language governing permissions and
14+
~ limitations under the License.
15+
-->
16+
17+
<selector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">
18+
19+
<item android:color="@color/buckColorPreonboardingOptionBackgroundSelected" android:state_selected="true" tools:ignore="InvalidColorAttribute" />
20+
<item android:color="@color/buckColorPreonboardingOptionBackground" tools:ignore="InvalidColorAttribute" />
21+
22+
</selector>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ Copyright (c) 2025 DuckDuckGo
3+
~
4+
~ Licensed under the Apache License, Version 2.0 (the "License");
5+
~ you may not use this file except in compliance with the License.
6+
~ You may obtain a copy of the License at
7+
~
8+
~ http://www.apache.org/licenses/LICENSE-2.0
9+
~
10+
~ Unless required by applicable law or agreed to in writing, software
11+
~ distributed under the License is distributed on an "AS IS" BASIS,
12+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
~ See the License for the specific language governing permissions and
14+
~ limitations under the License.
15+
-->
16+
17+
<selector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">
18+
19+
<item android:color="@color/buckColorPreonboardingOptionIconSelected" android:state_selected="true" tools:ignore="InvalidColorAttribute" />
20+
<item android:color="@color/buckColorPreonboardingOptionIcon" tools:ignore="InvalidColorAttribute" />
21+
22+
</selector>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ Copyright (c) 2025 DuckDuckGo
3+
~
4+
~ Licensed under the Apache License, Version 2.0 (the "License");
5+
~ you may not use this file except in compliance with the License.
6+
~ You may obtain a copy of the License at
7+
~
8+
~ http://www.apache.org/licenses/LICENSE-2.0
9+
~
10+
~ Unless required by applicable law or agreed to in writing, software
11+
~ distributed under the License is distributed on an "AS IS" BASIS,
12+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
~ See the License for the specific language governing permissions and
14+
~ limitations under the License.
15+
-->
16+
17+
<selector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">
18+
19+
<item android:color="#2C2926" android:state_selected="true" tools:ignore="InvalidColorAttribute" />
20+
<item android:color="@color/buckColorPrimaryText" tools:ignore="InvalidColorAttribute" />
21+
22+
</selector>

app/src/main/res/drawable/background_buck_onboarding_dialog.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
android:shape="rectangle">
2020
<solid android:color="?attr/daxColorOnboardingDialogBackground"/>
2121
<corners
22-
android:topLeftRadius="32dp"
23-
android:topRightRadius="32dp"
24-
android:bottomRightRadius="32dp"
22+
android:topLeftRadius="40dp"
23+
android:topRightRadius="40dp"
24+
android:bottomRightRadius="40dp"
2525
android:bottomLeftRadius="0dp"/>
2626
</shape>

0 commit comments

Comments
 (0)