Bug 1874768 - Hide default browser onboarding card if user already set us as default browser

fenix/123.0
Roger Yang 9 months ago committed by mergify[bot]
parent f9fdb86eb9
commit 931c43127f

@ -25,8 +25,7 @@ features:
card-type: default-browser card-type: default-browser
title: juno_onboarding_default_browser_title_nimbus_2 title: juno_onboarding_default_browser_title_nimbus_2
ordering: 10 ordering: 10
body: juno_onboarding_default_browser_description_nimbus_2 body: juno_onboarding_default_browser_description_nimbus_3
link-text: juno_onboarding_default_browser_description_link_text
image-res: ic_onboarding_welcome image-res: ic_onboarding_welcome
primary-button-label: juno_onboarding_default_browser_positive_button primary-button-label: juno_onboarding_default_browser_positive_button
secondary-button-label: juno_onboarding_default_browser_negative_button secondary-button-label: juno_onboarding_default_browser_negative_button
@ -83,13 +82,6 @@ objects:
description: The message text displayed to the user. May contain linkable text. description: The message text displayed to the user. May contain linkable text.
# This should never be defaulted. # This should never be defaulted.
default: "" default: ""
link-text:
type: Option<Text>
description: >
The text to link from the body text. This should match the linkable text from the body text exactly.
e.g. body: This is a policy link
link-text: policy link
default: null
image-res: image-res:
type: Image type: Image
description: The resource id of the image to be displayed. description: The resource id of the image to be displayed.

@ -45,10 +45,12 @@ class OnboardingMapperTest {
@Test @Test
fun showNotificationTrue_showAddWidgetFalse_pagesToDisplay_returnsSortedListOfAllConvertedPages_withoutAddWidgetPage() { fun showNotificationTrue_showAddWidgetFalse_pagesToDisplay_returnsSortedListOfAllConvertedPages_withoutAddWidgetPage() {
val expected = listOf(defaultBrowserPageUiData, syncPageUiData, notificationPageUiData) val expected = listOf(defaultBrowserPageUiDataWithPrivacyCaption, syncPageUiData, notificationPageUiData)
assertEquals( assertEquals(
expected, expected,
unsortedAllKnownCardData.toPageUiData( unsortedAllKnownCardData.toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = true, showNotificationPage = true,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -59,10 +61,12 @@ class OnboardingMapperTest {
@Test @Test
fun showNotificationFalse_showAddWidgetFalse_pagesToDisplay_returnsSortedListOfConvertedPages_withoutNotificationPage_and_addWidgetPage() { fun showNotificationFalse_showAddWidgetFalse_pagesToDisplay_returnsSortedListOfConvertedPages_withoutNotificationPage_and_addWidgetPage() {
val expected = listOf(defaultBrowserPageUiData, syncPageUiData) val expected = listOf(defaultBrowserPageUiDataWithPrivacyCaption, syncPageUiData)
assertEquals( assertEquals(
expected, expected,
unsortedAllKnownCardData.toPageUiData( unsortedAllKnownCardData.toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -71,12 +75,77 @@ class OnboardingMapperTest {
) )
} }
@Test
fun pagesToDisplay_returnsSortedListOfConvertedPages_withPrivacyCaption_alwaysOnFirstPage() {
var result = unsortedAllKnownCardData.toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = false,
showNotificationPage = false,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
)
assertEquals(result[0].privacyCaption, privacyCaption)
result = unsortedAllKnownCardData.toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = false,
showNotificationPage = true,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
)
assertEquals(result[0].privacyCaption, privacyCaption)
assertEquals(result[1].privacyCaption, null)
result = unsortedAllKnownCardData.toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = true,
showAddWidgetPage = false,
jexlConditions = jexlConditions,
func = evalFunction,
)
assertEquals(result[0].privacyCaption, privacyCaption)
assertEquals(result[1].privacyCaption, null)
assertEquals(result[2].privacyCaption, null)
result = unsortedAllKnownCardData.toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = false,
showNotificationPage = false,
showAddWidgetPage = true,
jexlConditions = jexlConditions,
func = evalFunction,
)
assertEquals(result[0].privacyCaption, privacyCaption)
assertEquals(result[1].privacyCaption, null)
}
@Test
fun showDefaultBrowserPageFalse_showNotificationFalse_showAddWidgetTrue_pagesToDisplay_returnsSortedListOfAllConvertedPages() {
val expected = listOf(addSearchWidgetPageUiDataWithPrivacyCaption, syncPageUiData)
assertEquals(
expected,
unsortedAllKnownCardData.toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = false,
showNotificationPage = false,
showAddWidgetPage = true,
jexlConditions = jexlConditions,
func = evalFunction,
),
)
}
@Test @Test
fun showNotificationFalse_showAddWidgetTrue_pagesToDisplay_returnsSortedListOfAllConvertedPages_withoutNotificationPage() { fun showNotificationFalse_showAddWidgetTrue_pagesToDisplay_returnsSortedListOfAllConvertedPages_withoutNotificationPage() {
val expected = listOf(defaultBrowserPageUiData, addSearchWidgetPageUiData, syncPageUiData) val expected = listOf(defaultBrowserPageUiDataWithPrivacyCaption, addSearchWidgetPageUiData, syncPageUiData)
assertEquals( assertEquals(
expected, expected,
unsortedAllKnownCardData.toPageUiData( unsortedAllKnownCardData.toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = true, showAddWidgetPage = true,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -88,7 +157,7 @@ class OnboardingMapperTest {
@Test @Test
fun showNotificationTrue_and_showAddWidgetTrue_pagesToDisplay_returnsSortedListOfConvertedPages() { fun showNotificationTrue_and_showAddWidgetTrue_pagesToDisplay_returnsSortedListOfConvertedPages() {
val expected = listOf( val expected = listOf(
defaultBrowserPageUiData, defaultBrowserPageUiDataWithPrivacyCaption,
addSearchWidgetPageUiData, addSearchWidgetPageUiData,
syncPageUiData, syncPageUiData,
notificationPageUiData, notificationPageUiData,
@ -96,6 +165,8 @@ class OnboardingMapperTest {
assertEquals( assertEquals(
expected, expected,
unsortedAllKnownCardData.toPageUiData( unsortedAllKnownCardData.toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = true, showNotificationPage = true,
showAddWidgetPage = true, showAddWidgetPage = true,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -107,11 +178,13 @@ class OnboardingMapperTest {
@Test @Test
fun cardConditionsMatchJexlConditions_shouldDisplayCard_returnsConvertedPage() { fun cardConditionsMatchJexlConditions_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false") val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false")
val expected = listOf(defaultBrowserPageUiData) val expected = listOf(defaultBrowserPageUiDataWithPrivacyCaption)
assertEquals( assertEquals(
expected, expected,
listOf(defaultBrowserCardData).toPageUiData( listOf(defaultBrowserCardData).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -128,6 +201,8 @@ class OnboardingMapperTest {
assertEquals( assertEquals(
expected, expected,
listOf(addSearchWidgetCardDataNoConditions).toPageUiData( listOf(addSearchWidgetCardDataNoConditions).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -144,6 +219,8 @@ class OnboardingMapperTest {
assertEquals( assertEquals(
expected, expected,
listOf(defaultBrowserCardData).toPageUiData( listOf(defaultBrowserCardData).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -155,11 +232,13 @@ class OnboardingMapperTest {
@Test @Test
fun prerequisitesMatchJexlConditions_shouldDisplayCard_returnsConvertedPage() { fun prerequisitesMatchJexlConditions_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("ALWAYS" to "true") val jexlConditions = mapOf("ALWAYS" to "true")
val expected = listOf(defaultBrowserPageUiData) val expected = listOf(defaultBrowserPageUiDataWithPrivacyCaption)
assertEquals( assertEquals(
expected, expected,
listOf(defaultBrowserCardData).toPageUiData( listOf(defaultBrowserCardData).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -176,6 +255,8 @@ class OnboardingMapperTest {
assertEquals( assertEquals(
expected, expected,
listOf(defaultBrowserCardData).toPageUiData( listOf(defaultBrowserCardData).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -192,6 +273,8 @@ class OnboardingMapperTest {
assertEquals( assertEquals(
expected, expected,
listOf(addSearchWidgetCardDataNoConditions).toPageUiData( listOf(addSearchWidgetCardDataNoConditions).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -203,11 +286,13 @@ class OnboardingMapperTest {
@Test @Test
fun noDisqualifiers_shouldDisplayCard_returnsConvertedPage() { fun noDisqualifiers_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false") val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false")
val expected = listOf(defaultBrowserPageUiData) val expected = listOf(defaultBrowserPageUiDataWithPrivacyCaption)
assertEquals( assertEquals(
expected, expected,
listOf(defaultBrowserCardDataNoDisqualifiers).toPageUiData( listOf(defaultBrowserCardDataNoDisqualifiers).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -219,11 +304,13 @@ class OnboardingMapperTest {
@Test @Test
fun disqualifiersMatchJexlConditions_shouldDisplayCard_returnsConvertedPage() { fun disqualifiersMatchJexlConditions_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("NEVER" to "false") val jexlConditions = mapOf("NEVER" to "false")
val expected = listOf(syncPageUiData) val expected = listOf(syncPageUiDataWithPrivacyCaption)
assertEquals( assertEquals(
expected, expected,
listOf(syncCardData).toPageUiData( listOf(syncCardData).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -240,6 +327,8 @@ class OnboardingMapperTest {
assertEquals( assertEquals(
expected, expected,
listOf(notificationCardData).toPageUiData( listOf(notificationCardData).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -251,11 +340,13 @@ class OnboardingMapperTest {
@Test @Test
fun noPrerequisites_shouldDisplayCard_returnsConvertedPage() { fun noPrerequisites_shouldDisplayCard_returnsConvertedPage() {
val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false") val jexlConditions = mapOf("ALWAYS" to "true", "NEVER" to "false")
val expected = listOf(syncPageUiData) val expected = listOf(syncPageUiDataWithPrivacyCaption)
assertEquals( assertEquals(
expected, expected,
listOf(syncCardData).toPageUiData( listOf(syncCardData).toPageUiData(
privacyCaption = privacyCaption,
showDefaultBrowserPage = true,
showNotificationPage = false, showNotificationPage = false,
showAddWidgetPage = false, showAddWidgetPage = false,
jexlConditions = jexlConditions, jexlConditions = jexlConditions,
@ -264,24 +355,34 @@ class OnboardingMapperTest {
) )
} }
} }
val privacyCaption: Caption = mockk(relaxed = true)
private val defaultBrowserPageUiData = OnboardingPageUiData( private val defaultBrowserPageUiDataWithPrivacyCaption = OnboardingPageUiData(
type = OnboardingPageUiData.Type.DEFAULT_BROWSER, type = OnboardingPageUiData.Type.DEFAULT_BROWSER,
imageRes = R.drawable.ic_onboarding_welcome, imageRes = R.drawable.ic_onboarding_welcome,
title = "default browser title", title = "default browser title",
description = "default browser body with link text", description = "default browser body",
linkText = "link text",
primaryButtonLabel = "default browser primary button text", primaryButtonLabel = "default browser primary button text",
secondaryButtonLabel = "default browser secondary button text", secondaryButtonLabel = "default browser secondary button text",
privacyCaption = privacyCaption,
) )
private val addSearchWidgetPageUiData = OnboardingPageUiData( private val addSearchWidgetPageUiData = OnboardingPageUiData(
type = OnboardingPageUiData.Type.ADD_SEARCH_WIDGET, type = OnboardingPageUiData.Type.ADD_SEARCH_WIDGET,
imageRes = R.drawable.ic_onboarding_search_widget, imageRes = R.drawable.ic_onboarding_search_widget,
title = "add search widget title", title = "add search widget title",
description = "add search widget body with link text", description = "add search widget body",
linkText = "link text", primaryButtonLabel = "add search widget primary button text",
secondaryButtonLabel = "add search widget secondary button text",
privacyCaption = null,
)
private val addSearchWidgetPageUiDataWithPrivacyCaption = OnboardingPageUiData(
type = OnboardingPageUiData.Type.ADD_SEARCH_WIDGET,
imageRes = R.drawable.ic_onboarding_search_widget,
title = "add search widget title",
description = "add search widget body",
primaryButtonLabel = "add search widget primary button text", primaryButtonLabel = "add search widget primary button text",
secondaryButtonLabel = "add search widget secondary button text", secondaryButtonLabel = "add search widget secondary button text",
privacyCaption = privacyCaption,
) )
private val syncPageUiData = OnboardingPageUiData( private val syncPageUiData = OnboardingPageUiData(
type = OnboardingPageUiData.Type.SYNC_SIGN_IN, type = OnboardingPageUiData.Type.SYNC_SIGN_IN,
@ -290,6 +391,16 @@ private val syncPageUiData = OnboardingPageUiData(
description = "sync body", description = "sync body",
primaryButtonLabel = "sync primary button text", primaryButtonLabel = "sync primary button text",
secondaryButtonLabel = "sync secondary button text", secondaryButtonLabel = "sync secondary button text",
privacyCaption = null,
)
private val syncPageUiDataWithPrivacyCaption = OnboardingPageUiData(
type = OnboardingPageUiData.Type.SYNC_SIGN_IN,
imageRes = R.drawable.ic_onboarding_sync,
title = "sync title",
description = "sync body",
primaryButtonLabel = "sync primary button text",
secondaryButtonLabel = "sync secondary button text",
privacyCaption = privacyCaption,
) )
private val notificationPageUiData = OnboardingPageUiData( private val notificationPageUiData = OnboardingPageUiData(
type = OnboardingPageUiData.Type.NOTIFICATION_PERMISSION, type = OnboardingPageUiData.Type.NOTIFICATION_PERMISSION,
@ -298,14 +409,14 @@ private val notificationPageUiData = OnboardingPageUiData(
description = "notification body", description = "notification body",
primaryButtonLabel = "notification primary button text", primaryButtonLabel = "notification primary button text",
secondaryButtonLabel = "notification secondary button text", secondaryButtonLabel = "notification secondary button text",
privacyCaption = null,
) )
private val defaultBrowserCardData = OnboardingCardData( private val defaultBrowserCardData = OnboardingCardData(
cardType = OnboardingCardType.DEFAULT_BROWSER, cardType = OnboardingCardType.DEFAULT_BROWSER,
imageRes = R.drawable.ic_onboarding_welcome, imageRes = R.drawable.ic_onboarding_welcome,
title = StringHolder(null, "default browser title"), title = StringHolder(null, "default browser title"),
body = StringHolder(null, "default browser body with link text"), body = StringHolder(null, "default browser body"),
linkText = StringHolder(null, "link text"),
primaryButtonLabel = StringHolder(null, "default browser primary button text"), primaryButtonLabel = StringHolder(null, "default browser primary button text"),
secondaryButtonLabel = StringHolder(null, "default browser secondary button text"), secondaryButtonLabel = StringHolder(null, "default browser secondary button text"),
ordering = 10, ordering = 10,
@ -317,8 +428,7 @@ private val defaultBrowserCardDataNoDisqualifiers = OnboardingCardData(
cardType = OnboardingCardType.DEFAULT_BROWSER, cardType = OnboardingCardType.DEFAULT_BROWSER,
imageRes = R.drawable.ic_onboarding_welcome, imageRes = R.drawable.ic_onboarding_welcome,
title = StringHolder(null, "default browser title"), title = StringHolder(null, "default browser title"),
body = StringHolder(null, "default browser body with link text"), body = StringHolder(null, "default browser body"),
linkText = StringHolder(null, "link text"),
primaryButtonLabel = StringHolder(null, "default browser primary button text"), primaryButtonLabel = StringHolder(null, "default browser primary button text"),
secondaryButtonLabel = StringHolder(null, "default browser secondary button text"), secondaryButtonLabel = StringHolder(null, "default browser secondary button text"),
ordering = 10, ordering = 10,
@ -330,8 +440,7 @@ private val addSearchWidgetCardDataNoConditions = OnboardingCardData(
cardType = OnboardingCardType.ADD_SEARCH_WIDGET, cardType = OnboardingCardType.ADD_SEARCH_WIDGET,
imageRes = R.drawable.ic_onboarding_search_widget, imageRes = R.drawable.ic_onboarding_search_widget,
title = StringHolder(null, "add search widget title"), title = StringHolder(null, "add search widget title"),
body = StringHolder(null, "add search widget body with link text"), body = StringHolder(null, "add search widget body"),
linkText = StringHolder(null, "link text"),
primaryButtonLabel = StringHolder(null, "add search widget primary button text"), primaryButtonLabel = StringHolder(null, "add search widget primary button text"),
secondaryButtonLabel = StringHolder(null, "add search widget secondary button text"), secondaryButtonLabel = StringHolder(null, "add search widget secondary button text"),
ordering = 15, ordering = 15,
@ -343,8 +452,7 @@ private val addSearchWidgetCardData = OnboardingCardData(
cardType = OnboardingCardType.ADD_SEARCH_WIDGET, cardType = OnboardingCardType.ADD_SEARCH_WIDGET,
imageRes = R.drawable.ic_onboarding_search_widget, imageRes = R.drawable.ic_onboarding_search_widget,
title = StringHolder(null, "add search widget title"), title = StringHolder(null, "add search widget title"),
body = StringHolder(null, "add search widget body with link text"), body = StringHolder(null, "add search widget body"),
linkText = StringHolder(null, "link text"),
primaryButtonLabel = StringHolder(null, "add search widget primary button text"), primaryButtonLabel = StringHolder(null, "add search widget primary button text"),
secondaryButtonLabel = StringHolder(null, "add search widget secondary button text"), secondaryButtonLabel = StringHolder(null, "add search widget secondary button text"),
ordering = 15, ordering = 15,

@ -140,7 +140,7 @@ class HomeScreenRobot {
).assertExists() ).assertExists()
it.onNodeWithText( it.onNodeWithText(
getStringResource(R.string.juno_onboarding_default_browser_description_nimbus_2), getStringResource(R.string.juno_onboarding_default_browser_description_nimbus_3),
).assertExists() ).assertExists()
it.onNodeWithText( it.onNodeWithText(

@ -18,21 +18,23 @@ import android.view.ViewGroup
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import mozilla.components.service.nimbus.evalJexlSafe import mozilla.components.service.nimbus.evalJexlSafe
import mozilla.components.support.base.ext.areNotificationsEnabledSafe import mozilla.components.support.base.ext.areNotificationsEnabledSafe
import mozilla.components.support.utils.BrowsersCache
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.accounts.FenixFxAEntryPoint import org.mozilla.fenix.components.accounts.FenixFxAEntryPoint
import org.mozilla.fenix.compose.LinkTextState
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.hideToolbar import org.mozilla.fenix.ext.hideToolbar
import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.openSetDefaultBrowserOption import org.mozilla.fenix.ext.openSetDefaultBrowserOption
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.nimbus.FxNimbus import org.mozilla.fenix.nimbus.FxNimbus
import org.mozilla.fenix.onboarding.view.Caption
import org.mozilla.fenix.onboarding.view.OnboardingPageUiData import org.mozilla.fenix.onboarding.view.OnboardingPageUiData
import org.mozilla.fenix.onboarding.view.OnboardingScreen import org.mozilla.fenix.onboarding.view.OnboardingScreen
import org.mozilla.fenix.onboarding.view.sequencePosition import org.mozilla.fenix.onboarding.view.sequencePosition
@ -49,6 +51,7 @@ class OnboardingFragment : Fragment() {
private val pagesToDisplay by lazy { private val pagesToDisplay by lazy {
pagesToDisplay( pagesToDisplay(
shouldShowDefaultBrowserCard(requireContext()),
canShowNotificationPage(requireContext()), canShowNotificationPage(requireContext()),
canShowAddWidgetCard(), canShowAddWidgetCard(),
) )
@ -59,6 +62,11 @@ class OnboardingFragment : Fragment() {
@SuppressLint("SourceLockedOrientationActivity") @SuppressLint("SourceLockedOrientationActivity")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (pagesToDisplay.isEmpty()) {
/* do not continue if there's no onboarding pages to display */
onFinish(null)
}
if (isNotATablet()) { if (isNotATablet()) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
} }
@ -97,7 +105,6 @@ class OnboardingFragment : Fragment() {
@Composable @Composable
@Suppress("LongMethod") @Suppress("LongMethod")
private fun ScreenContent() { private fun ScreenContent() {
val context = LocalContext.current
OnboardingScreen( OnboardingScreen(
pagesToDisplay = pagesToDisplay, pagesToDisplay = pagesToDisplay,
onMakeFirefoxDefaultClick = { onMakeFirefoxDefaultClick = {
@ -113,18 +120,6 @@ class OnboardingFragment : Fragment() {
pagesToDisplay.sequencePosition(OnboardingPageUiData.Type.DEFAULT_BROWSER), pagesToDisplay.sequencePosition(OnboardingPageUiData.Type.DEFAULT_BROWSER),
) )
}, },
onPrivacyPolicyClick = { url ->
startActivity(
SupportUtils.createSandboxCustomTabIntent(
context = context,
url = url,
),
)
telemetryRecorder.onPrivacyPolicyClick(
pagesToDisplay.telemetrySequenceId(),
pagesToDisplay.sequencePosition(OnboardingPageUiData.Type.DEFAULT_BROWSER),
)
},
onSignInButtonClick = { onSignInButtonClick = {
findNavController().nav( findNavController().nav(
id = R.id.onboardingFragment, id = R.id.onboardingFragment,
@ -172,10 +167,7 @@ class OnboardingFragment : Fragment() {
) )
}, },
onFinish = { onFinish = {
onFinish( onFinish(it)
sequenceId = pagesToDisplay.telemetrySequenceId(),
sequencePosition = pagesToDisplay.sequencePosition(it.type),
)
}, },
onImpression = { onImpression = {
telemetryRecorder.onImpression( telemetryRecorder.onImpression(
@ -200,18 +192,28 @@ class OnboardingFragment : Fragment() {
} }
} }
private fun onFinish(sequenceId: String, sequencePosition: String) { private fun onFinish(onboardingPageUiData: OnboardingPageUiData?) {
/* onboarding page UI data can be null if there was no pages to display */
if (onboardingPageUiData != null) {
val sequenceId = pagesToDisplay.telemetrySequenceId()
val sequencePosition = pagesToDisplay.sequencePosition(onboardingPageUiData.type)
telemetryRecorder.onOnboardingComplete(
sequenceId = sequenceId,
sequencePosition = sequencePosition,
)
}
requireComponents.fenixOnboarding.finish() requireComponents.fenixOnboarding.finish()
findNavController().nav( findNavController().nav(
id = R.id.onboardingFragment, id = R.id.onboardingFragment,
directions = OnboardingFragmentDirections.actionHome(), directions = OnboardingFragmentDirections.actionHome(),
) )
telemetryRecorder.onOnboardingComplete(
sequenceId = sequenceId,
sequencePosition = sequencePosition,
)
} }
private fun shouldShowDefaultBrowserCard(context: Context) =
!BrowsersCache.all(context.applicationContext).isDefaultBrowser
private fun canShowNotificationPage(context: Context) = private fun canShowNotificationPage(context: Context) =
!NotificationManagerCompat.from(context.applicationContext) !NotificationManagerCompat.from(context.applicationContext)
.areNotificationsEnabledSafe() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU .areNotificationsEnabledSafe() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
@ -221,13 +223,35 @@ class OnboardingFragment : Fragment() {
private fun isNotATablet() = !resources.getBoolean(R.bool.tablet) private fun isNotATablet() = !resources.getBoolean(R.bool.tablet)
private fun pagesToDisplay( private fun pagesToDisplay(
showDefaultBrowserPage: Boolean,
showNotificationPage: Boolean, showNotificationPage: Boolean,
showAddWidgetPage: Boolean, showAddWidgetPage: Boolean,
): List<OnboardingPageUiData> { ): List<OnboardingPageUiData> {
val jexlConditions = FxNimbus.features.junoOnboarding.value().conditions val jexlConditions = FxNimbus.features.junoOnboarding.value().conditions
val jexlHelper = requireContext().components.analytics.messagingStorage.helper val jexlHelper = requireContext().components.analytics.messagingStorage.helper
val privacyCaption = Caption(
text = getString(R.string.juno_onboarding_privacy_notice_text),
linkTextState = LinkTextState(
text = getString(R.string.juno_onboarding_privacy_notice_text),
url = SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE),
onClick = {
startActivity(
SupportUtils.createSandboxCustomTabIntent(
context = requireContext(),
url = it,
),
)
telemetryRecorder.onPrivacyPolicyClick(
pagesToDisplay.telemetrySequenceId(),
pagesToDisplay.sequencePosition(OnboardingPageUiData.Type.DEFAULT_BROWSER),
)
},
),
)
return FxNimbus.features.junoOnboarding.value().cards.values.toPageUiData( return FxNimbus.features.junoOnboarding.value().cards.values.toPageUiData(
privacyCaption,
showDefaultBrowserPage,
showNotificationPage, showNotificationPage,
showAddWidgetPage, showAddWidgetPage,
jexlConditions, jexlConditions,

@ -4,15 +4,15 @@
package org.mozilla.fenix.onboarding.view package org.mozilla.fenix.onboarding.view
import org.mozilla.fenix.compose.LinkTextState
import org.mozilla.fenix.nimbus.OnboardingCardData import org.mozilla.fenix.nimbus.OnboardingCardData
import org.mozilla.fenix.nimbus.OnboardingCardType import org.mozilla.fenix.nimbus.OnboardingCardType
import org.mozilla.fenix.settings.SupportUtils
/** /**
* Returns a list of all the required Nimbus 'cards' that have been converted to [OnboardingPageUiData]. * Returns a list of all the required Nimbus 'cards' that have been converted to [OnboardingPageUiData].
*/ */
internal fun Collection<OnboardingCardData>.toPageUiData( internal fun Collection<OnboardingCardData>.toPageUiData(
privacyCaption: Caption,
showDefaultBrowserPage: Boolean,
showNotificationPage: Boolean, showNotificationPage: Boolean,
showAddWidgetPage: Boolean, showAddWidgetPage: Boolean,
jexlConditions: Map<String, String>, jexlConditions: Map<String, String>,
@ -21,16 +21,25 @@ internal fun Collection<OnboardingCardData>.toPageUiData(
// we are first filtering the cards based on Nimbus configuration // we are first filtering the cards based on Nimbus configuration
return filter { it.shouldDisplayCard(func, jexlConditions) } return filter { it.shouldDisplayCard(func, jexlConditions) }
// we are then filtering again based on device capabilities // we are then filtering again based on device capabilities
.filter { it.isCardEnabled(showNotificationPage, showAddWidgetPage) } .filter { it.isCardEnabled(showDefaultBrowserPage, showNotificationPage, showAddWidgetPage) }
.sortedBy { it.ordering } .sortedBy { it.ordering }
.map { it.toPageUiData() } .mapIndexed {
index, onboardingCardData ->
// only first onboarding card shows privacy caption
onboardingCardData.toPageUiData(if (index == 0) privacyCaption else null)
}
} }
private fun OnboardingCardData.isCardEnabled( private fun OnboardingCardData.isCardEnabled(
showDefaultBrowserPage: Boolean,
showNotificationPage: Boolean, showNotificationPage: Boolean,
showAddWidgetPage: Boolean, showAddWidgetPage: Boolean,
): Boolean = ): Boolean =
when (cardType) { when (cardType) {
OnboardingCardType.DEFAULT_BROWSER -> {
enabled && showDefaultBrowserPage
}
OnboardingCardType.NOTIFICATION_PERMISSION -> { OnboardingCardType.NOTIFICATION_PERMISSION -> {
enabled && showNotificationPage enabled && showNotificationPage
} }
@ -91,14 +100,14 @@ private fun OnboardingCardData.shouldDisplayCard(
return validPrerequisites && !hasDisqualifiers return validPrerequisites && !hasDisqualifiers
} }
private fun OnboardingCardData.toPageUiData() = OnboardingPageUiData( private fun OnboardingCardData.toPageUiData(privacyCaption: Caption?) = OnboardingPageUiData(
type = cardType.toPageUiDataType(), type = cardType.toPageUiDataType(),
imageRes = imageRes.resourceId, imageRes = imageRes.resourceId,
title = title, title = title,
description = body, description = body,
linkText = linkText,
primaryButtonLabel = primaryButtonLabel, primaryButtonLabel = primaryButtonLabel,
secondaryButtonLabel = secondaryButtonLabel, secondaryButtonLabel = secondaryButtonLabel,
privacyCaption = privacyCaption,
) )
private fun OnboardingCardType.toPageUiDataType() = when (this) { private fun OnboardingCardType.toPageUiDataType() = when (this) {
@ -117,7 +126,6 @@ internal fun mapToOnboardingPageState(
onboardingPageUiData: OnboardingPageUiData, onboardingPageUiData: OnboardingPageUiData,
onMakeFirefoxDefaultClick: () -> Unit, onMakeFirefoxDefaultClick: () -> Unit,
onMakeFirefoxDefaultSkipClick: () -> Unit, onMakeFirefoxDefaultSkipClick: () -> Unit,
onPrivacyPolicyClick: (String) -> Unit,
onSignInButtonClick: () -> Unit, onSignInButtonClick: () -> Unit,
onSignInSkipClick: () -> Unit, onSignInSkipClick: () -> Unit,
onNotificationPermissionButtonClick: () -> Unit, onNotificationPermissionButtonClick: () -> Unit,
@ -129,14 +137,12 @@ internal fun mapToOnboardingPageState(
onboardingPageUiData = onboardingPageUiData, onboardingPageUiData = onboardingPageUiData,
onPositiveButtonClick = onMakeFirefoxDefaultClick, onPositiveButtonClick = onMakeFirefoxDefaultClick,
onNegativeButtonClick = onMakeFirefoxDefaultSkipClick, onNegativeButtonClick = onMakeFirefoxDefaultSkipClick,
onUrlClick = onPrivacyPolicyClick,
) )
OnboardingPageUiData.Type.ADD_SEARCH_WIDGET -> createOnboardingPageState( OnboardingPageUiData.Type.ADD_SEARCH_WIDGET -> createOnboardingPageState(
onboardingPageUiData = onboardingPageUiData, onboardingPageUiData = onboardingPageUiData,
onPositiveButtonClick = onAddFirefoxWidgetClick, onPositiveButtonClick = onAddFirefoxWidgetClick,
onNegativeButtonClick = onAddFirefoxWidgetSkipClick, onNegativeButtonClick = onAddFirefoxWidgetSkipClick,
onUrlClick = onPrivacyPolicyClick,
) )
OnboardingPageUiData.Type.SYNC_SIGN_IN -> createOnboardingPageState( OnboardingPageUiData.Type.SYNC_SIGN_IN -> createOnboardingPageState(
@ -156,18 +162,11 @@ private fun createOnboardingPageState(
onboardingPageUiData: OnboardingPageUiData, onboardingPageUiData: OnboardingPageUiData,
onPositiveButtonClick: () -> Unit, onPositiveButtonClick: () -> Unit,
onNegativeButtonClick: () -> Unit, onNegativeButtonClick: () -> Unit,
onUrlClick: (String) -> Unit = {},
): OnboardingPageState = OnboardingPageState( ): OnboardingPageState = OnboardingPageState(
imageRes = onboardingPageUiData.imageRes, imageRes = onboardingPageUiData.imageRes,
title = onboardingPageUiData.title, title = onboardingPageUiData.title,
description = onboardingPageUiData.description, description = onboardingPageUiData.description,
linkTextState = onboardingPageUiData.linkText?.let {
LinkTextState(
text = it,
url = SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE),
onClick = onUrlClick,
)
},
primaryButton = Action(onboardingPageUiData.primaryButtonLabel, onPositiveButtonClick), primaryButton = Action(onboardingPageUiData.primaryButtonLabel, onPositiveButtonClick),
secondaryButton = Action(onboardingPageUiData.secondaryButtonLabel, onNegativeButtonClick), secondaryButton = Action(onboardingPageUiData.secondaryButtonLabel, onNegativeButtonClick),
privacyCaption = onboardingPageUiData.privacyCaption,
) )

@ -30,7 +30,6 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.compose.LinkText import org.mozilla.fenix.compose.LinkText
import org.mozilla.fenix.compose.LinkTextState
import org.mozilla.fenix.compose.annotation.LightDarkPreview import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.compose.button.PrimaryButton import org.mozilla.fenix.compose.button.PrimaryButton
import org.mozilla.fenix.compose.button.SecondaryButton import org.mozilla.fenix.compose.button.SecondaryButton
@ -61,6 +60,7 @@ private const val IMAGE_HEIGHT_RATIO_SMALL = 0.28f
* it doesn't show the close button. * it doesn't show the close button.
*/ */
@Composable @Composable
@Suppress("LongMethod")
fun OnboardingPage( fun OnboardingPage(
pageState: OnboardingPageState, pageState: OnboardingPageState,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -116,10 +116,21 @@ fun OnboardingPage(
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
DescriptionText( Text(
description = pageState.description, text = pageState.description,
linkTextState = pageState.linkTextState, color = FirefoxTheme.colors.textSecondary,
textAlign = TextAlign.Center,
style = FirefoxTheme.typography.body2,
) )
Spacer(modifier = Modifier.height(16.dp))
pageState.privacyCaption?.let { privacyCaption ->
LinkText(
text = privacyCaption.text,
linkTextStates = listOf(privacyCaption.linkTextState),
)
}
} }
Column( Column(
@ -147,26 +158,6 @@ fun OnboardingPage(
} }
} }
@Composable
private fun DescriptionText(
description: String,
linkTextState: LinkTextState?,
) {
if (linkTextState != null && description.contains(linkTextState.text, ignoreCase = true)) {
LinkText(
text = description,
linkTextStates = listOf(linkTextState),
)
} else {
Text(
text = description,
color = FirefoxTheme.colors.textSecondary,
textAlign = TextAlign.Center,
style = FirefoxTheme.typography.body2,
)
}
}
/** /**
* Calculates the image height to be set. The ratio is selected based on parent height. * Calculates the image height to be set. The ratio is selected based on parent height.
*/ */

@ -13,7 +13,7 @@ import org.mozilla.fenix.compose.LinkTextState
* @property imageRes [DrawableRes] displayed on the page. * @property imageRes [DrawableRes] displayed on the page.
* @property title [String] title of the page. * @property title [String] title of the page.
* @property description [String] description of the page. * @property description [String] description of the page.
* @property linkTextState [LinkTextState] part of description text with a link. * @property privacyCaption privacy caption to show and allow user to view on privacy policy.
* @property primaryButton [Action] action for the primary button. * @property primaryButton [Action] action for the primary button.
* @property secondaryButton [Action] action for the secondary button. * @property secondaryButton [Action] action for the secondary button.
* @property onRecordImpressionEvent Callback for recording impression event. * @property onRecordImpressionEvent Callback for recording impression event.
@ -22,7 +22,7 @@ data class OnboardingPageState(
@DrawableRes val imageRes: Int, @DrawableRes val imageRes: Int,
val title: String, val title: String,
val description: String, val description: String,
val linkTextState: LinkTextState? = null, val privacyCaption: Caption? = null,
val primaryButton: Action, val primaryButton: Action,
val secondaryButton: Action? = null, val secondaryButton: Action? = null,
val onRecordImpressionEvent: () -> Unit = {}, val onRecordImpressionEvent: () -> Unit = {},
@ -35,3 +35,11 @@ data class Action(
val text: String, val text: String,
val onClick: () -> Unit, val onClick: () -> Unit,
) )
/**
* Model containing text and [LinkTextState] for a caption.
*/
data class Caption(
val text: String,
val linkTextState: LinkTextState,
)

@ -15,9 +15,9 @@ data class OnboardingPageUiData(
@DrawableRes val imageRes: Int, @DrawableRes val imageRes: Int,
val title: String, val title: String,
val description: String, val description: String,
val linkText: String? = null,
val primaryButtonLabel: String, val primaryButtonLabel: String,
val secondaryButtonLabel: String, val secondaryButtonLabel: String,
val privacyCaption: Caption?,
) { ) {
/** /**
* Model for different types of Onboarding Pages. * Model for different types of Onboarding Pages.

@ -37,6 +37,7 @@ import kotlinx.coroutines.launch
import mozilla.components.lib.state.ext.observeAsComposableState import mozilla.components.lib.state.ext.observeAsComposableState
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.components import org.mozilla.fenix.components.components
import org.mozilla.fenix.compose.LinkTextState
import org.mozilla.fenix.compose.PagerIndicator import org.mozilla.fenix.compose.PagerIndicator
import org.mozilla.fenix.compose.annotation.LightDarkPreview import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.onboarding.WidgetPinnedReceiver.WidgetPinnedState import org.mozilla.fenix.onboarding.WidgetPinnedReceiver.WidgetPinnedState
@ -48,7 +49,6 @@ import org.mozilla.fenix.theme.FirefoxTheme
* @param pagesToDisplay List of pages to be displayed in onboarding pager ui. * @param pagesToDisplay List of pages to be displayed in onboarding pager ui.
* @param onMakeFirefoxDefaultClick Invoked when positive button on default browser page is clicked. * @param onMakeFirefoxDefaultClick Invoked when positive button on default browser page is clicked.
* @param onSkipDefaultClick Invoked when negative button on default browser page is clicked. * @param onSkipDefaultClick Invoked when negative button on default browser page is clicked.
* @param onPrivacyPolicyClick Invoked when the privacy policy link text is clicked.
* @param onSignInButtonClick Invoked when the positive button on the sign in page is clicked. * @param onSignInButtonClick Invoked when the positive button on the sign in page is clicked.
* @param onSkipSignInClick Invoked when the negative button on the sign in page is clicked. * @param onSkipSignInClick Invoked when the negative button on the sign in page is clicked.
* @param onNotificationPermissionButtonClick Invoked when positive button on notification page is * @param onNotificationPermissionButtonClick Invoked when positive button on notification page is
@ -65,7 +65,6 @@ fun OnboardingScreen(
pagesToDisplay: List<OnboardingPageUiData>, pagesToDisplay: List<OnboardingPageUiData>,
onMakeFirefoxDefaultClick: () -> Unit, onMakeFirefoxDefaultClick: () -> Unit,
onSkipDefaultClick: () -> Unit, onSkipDefaultClick: () -> Unit,
onPrivacyPolicyClick: (url: String) -> Unit,
onSignInButtonClick: () -> Unit, onSignInButtonClick: () -> Unit,
onSkipSignInClick: () -> Unit, onSkipSignInClick: () -> Unit,
onNotificationPermissionButtonClick: () -> Unit, onNotificationPermissionButtonClick: () -> Unit,
@ -127,9 +126,6 @@ fun OnboardingScreen(
scrollToNextPageOrDismiss() scrollToNextPageOrDismiss()
onSkipDefaultClick() onSkipDefaultClick()
}, },
onPrivacyPolicyClick = {
onPrivacyPolicyClick(it)
},
onSignInButtonClick = { onSignInButtonClick = {
onSignInButtonClick() onSignInButtonClick()
scrollToNextPageOrDismiss() scrollToNextPageOrDismiss()
@ -167,7 +163,6 @@ private fun OnboardingContent(
pagerState: PagerState, pagerState: PagerState,
onMakeFirefoxDefaultClick: () -> Unit, onMakeFirefoxDefaultClick: () -> Unit,
onMakeFirefoxDefaultSkipClick: () -> Unit, onMakeFirefoxDefaultSkipClick: () -> Unit,
onPrivacyPolicyClick: (String) -> Unit,
onSignInButtonClick: () -> Unit, onSignInButtonClick: () -> Unit,
onSignInSkipClick: () -> Unit, onSignInSkipClick: () -> Unit,
onNotificationPermissionButtonClick: () -> Unit, onNotificationPermissionButtonClick: () -> Unit,
@ -195,7 +190,6 @@ private fun OnboardingContent(
onboardingPageUiData = pageUiState, onboardingPageUiData = pageUiState,
onMakeFirefoxDefaultClick = onMakeFirefoxDefaultClick, onMakeFirefoxDefaultClick = onMakeFirefoxDefaultClick,
onMakeFirefoxDefaultSkipClick = onMakeFirefoxDefaultSkipClick, onMakeFirefoxDefaultSkipClick = onMakeFirefoxDefaultSkipClick,
onPrivacyPolicyClick = onPrivacyPolicyClick,
onSignInButtonClick = onSignInButtonClick, onSignInButtonClick = onSignInButtonClick,
onSignInSkipClick = onSignInSkipClick, onSignInSkipClick = onSignInSkipClick,
onNotificationPermissionButtonClick = onNotificationPermissionButtonClick, onNotificationPermissionButtonClick = onNotificationPermissionButtonClick,
@ -251,7 +245,6 @@ private fun OnboardingScreenPreview() {
}, },
onMakeFirefoxDefaultClick = {}, onMakeFirefoxDefaultClick = {},
onMakeFirefoxDefaultSkipClick = {}, onMakeFirefoxDefaultSkipClick = {},
onPrivacyPolicyClick = {},
onSignInButtonClick = {}, onSignInButtonClick = {},
onSignInSkipClick = {}, onSignInSkipClick = {},
onNotificationPermissionButtonClick = {}, onNotificationPermissionButtonClick = {},
@ -268,10 +261,17 @@ private fun defaultPreviewPages() = listOf(
type = OnboardingPageUiData.Type.DEFAULT_BROWSER, type = OnboardingPageUiData.Type.DEFAULT_BROWSER,
imageRes = R.drawable.ic_onboarding_welcome, imageRes = R.drawable.ic_onboarding_welcome,
title = stringResource(R.string.juno_onboarding_default_browser_title_nimbus_2), title = stringResource(R.string.juno_onboarding_default_browser_title_nimbus_2),
description = stringResource(R.string.juno_onboarding_default_browser_description_nimbus_2), description = stringResource(R.string.juno_onboarding_default_browser_description_nimbus_3),
linkText = stringResource(R.string.juno_onboarding_default_browser_description_link_text),
primaryButtonLabel = stringResource(R.string.juno_onboarding_default_browser_positive_button), primaryButtonLabel = stringResource(R.string.juno_onboarding_default_browser_positive_button),
secondaryButtonLabel = stringResource(R.string.juno_onboarding_default_browser_negative_button), secondaryButtonLabel = stringResource(R.string.juno_onboarding_default_browser_negative_button),
privacyCaption = Caption(
text = stringResource(R.string.juno_onboarding_privacy_notice_text),
linkTextState = LinkTextState(
text = stringResource(R.string.juno_onboarding_privacy_notice_text),
url = "",
onClick = {},
),
),
), ),
OnboardingPageUiData( OnboardingPageUiData(
type = OnboardingPageUiData.Type.SYNC_SIGN_IN, type = OnboardingPageUiData.Type.SYNC_SIGN_IN,
@ -280,6 +280,14 @@ private fun defaultPreviewPages() = listOf(
description = stringResource(R.string.juno_onboarding_sign_in_description_2), description = stringResource(R.string.juno_onboarding_sign_in_description_2),
primaryButtonLabel = stringResource(R.string.juno_onboarding_sign_in_positive_button), primaryButtonLabel = stringResource(R.string.juno_onboarding_sign_in_positive_button),
secondaryButtonLabel = stringResource(R.string.juno_onboarding_sign_in_negative_button), secondaryButtonLabel = stringResource(R.string.juno_onboarding_sign_in_negative_button),
privacyCaption = Caption(
text = stringResource(R.string.juno_onboarding_privacy_notice_text),
linkTextState = LinkTextState(
text = stringResource(R.string.juno_onboarding_privacy_notice_text),
url = "",
onClick = {},
),
),
), ),
OnboardingPageUiData( OnboardingPageUiData(
type = OnboardingPageUiData.Type.NOTIFICATION_PERMISSION, type = OnboardingPageUiData.Type.NOTIFICATION_PERMISSION,
@ -288,5 +296,13 @@ private fun defaultPreviewPages() = listOf(
description = stringResource(R.string.juno_onboarding_enable_notifications_description_nimbus_2), description = stringResource(R.string.juno_onboarding_enable_notifications_description_nimbus_2),
primaryButtonLabel = stringResource(R.string.juno_onboarding_enable_notifications_positive_button), primaryButtonLabel = stringResource(R.string.juno_onboarding_enable_notifications_positive_button),
secondaryButtonLabel = stringResource(R.string.juno_onboarding_enable_notifications_negative_button), secondaryButtonLabel = stringResource(R.string.juno_onboarding_enable_notifications_negative_button),
privacyCaption = Caption(
text = stringResource(R.string.juno_onboarding_privacy_notice_text),
linkTextState = LinkTextState(
text = stringResource(R.string.juno_onboarding_privacy_notice_text),
url = "",
onClick = {},
),
),
), ),
) )

@ -310,13 +310,18 @@
<string name="onboarding_home_enable_notifications_negative_button">Not now</string> <string name="onboarding_home_enable_notifications_negative_button">Not now</string>
<!-- Juno first user onboarding flow experiment, strings are marked unused as they are only referenced by Nimbus experiments. --> <!-- Juno first user onboarding flow experiment, strings are marked unused as they are only referenced by Nimbus experiments. -->
<!-- Description for learning more about our privacy notice. -->
<string name="juno_onboarding_privacy_notice_text">Firefox privacy notice</string>
<!-- Text for the button to set firefox as default browser on the device -->
<!-- Title for set firefox as default browser screen used by Nimbus experiments. --> <!-- Title for set firefox as default browser screen used by Nimbus experiments. -->
<string name="juno_onboarding_default_browser_title_nimbus_2">We love keeping you safe</string> <string name="juno_onboarding_default_browser_title_nimbus_2">We love keeping you safe</string>
<!-- Description for set firefox as default browser screen used by Nimbus experiments. --> <!-- Description for set firefox as default browser screen used by Nimbus experiments. -->
<string name="juno_onboarding_default_browser_description_nimbus_2">Our non-profit backed browser helps stop companies from secretly following you around the web.\n\nLearn more in our privacy notice.</string> <string name="juno_onboarding_default_browser_description_nimbus_3">Our non-profit backed browser helps stop companies from secretly following you around the web.</string>
<!-- Description for set firefox as default browser screen used by Nimbus experiments. -->
<string name="juno_onboarding_default_browser_description_nimbus_2" moz:RemovedIn="124" tools:ignore="UnusedResources">Our non-profit backed browser helps stop companies from secretly following you around the web.\n\nLearn more in our privacy notice.</string>
<!-- Text for the link to the privacy notice webpage for set as firefox default browser screen. <!-- Text for the link to the privacy notice webpage for set as firefox default browser screen.
This is part of the string with the key "juno_onboarding_default_browser_description". --> This is part of the string with the key "juno_onboarding_default_browser_description". -->
<string name="juno_onboarding_default_browser_description_link_text" tools:ignore="UnusedResources">privacy notice</string> <string name="juno_onboarding_default_browser_description_link_text" moz:RemovedIn="124" tools:ignore="UnusedResources">privacy notice</string>
<!-- Text for the button to set firefox as default browser on the device --> <!-- Text for the button to set firefox as default browser on the device -->
<string name="juno_onboarding_default_browser_positive_button" tools:ignore="UnusedResources">Set as default browser</string> <string name="juno_onboarding_default_browser_positive_button" tools:ignore="UnusedResources">Set as default browser</string>
<!-- Text for the button dismiss the screen and move on with the flow --> <!-- Text for the button dismiss the screen and move on with the flow -->

@ -7,8 +7,6 @@ package org.mozilla.fenix.onboarding.view
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.compose.LinkTextState
import org.mozilla.fenix.settings.SupportUtils
class OnboardingMapperTest { class OnboardingMapperTest {
@ -18,11 +16,6 @@ class OnboardingMapperTest {
imageRes = R.drawable.ic_onboarding_welcome, imageRes = R.drawable.ic_onboarding_welcome,
title = "default browser title", title = "default browser title",
description = "default browser body with link text", description = "default browser body with link text",
linkTextState = LinkTextState(
text = "link text",
url = SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE),
onClick = stringLambda,
),
primaryButton = Action("default browser primary button text", unitLambda), primaryButton = Action("default browser primary button text", unitLambda),
secondaryButton = Action("default browser secondary button text", unitLambda), secondaryButton = Action("default browser secondary button text", unitLambda),
) )
@ -32,15 +25,14 @@ class OnboardingMapperTest {
imageRes = R.drawable.ic_onboarding_welcome, imageRes = R.drawable.ic_onboarding_welcome,
title = "default browser title", title = "default browser title",
description = "default browser body with link text", description = "default browser body with link text",
linkText = "link text",
primaryButtonLabel = "default browser primary button text", primaryButtonLabel = "default browser primary button text",
secondaryButtonLabel = "default browser secondary button text", secondaryButtonLabel = "default browser secondary button text",
privacyCaption = null,
) )
val actual = mapToOnboardingPageState( val actual = mapToOnboardingPageState(
onboardingPageUiData = onboardingPageUiData, onboardingPageUiData = onboardingPageUiData,
onMakeFirefoxDefaultClick = unitLambda, onMakeFirefoxDefaultClick = unitLambda,
onMakeFirefoxDefaultSkipClick = unitLambda, onMakeFirefoxDefaultSkipClick = unitLambda,
onPrivacyPolicyClick = stringLambda,
onSignInButtonClick = {}, onSignInButtonClick = {},
onSignInSkipClick = {}, onSignInSkipClick = {},
onNotificationPermissionButtonClick = {}, onNotificationPermissionButtonClick = {},
@ -67,15 +59,14 @@ class OnboardingMapperTest {
imageRes = R.drawable.ic_onboarding_sync, imageRes = R.drawable.ic_onboarding_sync,
title = "sync title", title = "sync title",
description = "sync body", description = "sync body",
linkText = null,
primaryButtonLabel = "sync primary button text", primaryButtonLabel = "sync primary button text",
secondaryButtonLabel = "sync secondary button text", secondaryButtonLabel = "sync secondary button text",
privacyCaption = null,
) )
val actual = mapToOnboardingPageState( val actual = mapToOnboardingPageState(
onboardingPageUiData = onboardingPageUiData, onboardingPageUiData = onboardingPageUiData,
onMakeFirefoxDefaultClick = {}, onMakeFirefoxDefaultClick = {},
onMakeFirefoxDefaultSkipClick = {}, onMakeFirefoxDefaultSkipClick = {},
onPrivacyPolicyClick = {},
onSignInButtonClick = unitLambda, onSignInButtonClick = unitLambda,
onSignInSkipClick = unitLambda, onSignInSkipClick = unitLambda,
onNotificationPermissionButtonClick = {}, onNotificationPermissionButtonClick = {},
@ -102,15 +93,14 @@ class OnboardingMapperTest {
imageRes = R.drawable.ic_notification_permission, imageRes = R.drawable.ic_notification_permission,
title = "notification title", title = "notification title",
description = "notification body", description = "notification body",
linkText = null,
primaryButtonLabel = "notification primary button text", primaryButtonLabel = "notification primary button text",
secondaryButtonLabel = "notification secondary button text", secondaryButtonLabel = "notification secondary button text",
privacyCaption = null,
) )
val actual = mapToOnboardingPageState( val actual = mapToOnboardingPageState(
onboardingPageUiData = onboardingPageUiData, onboardingPageUiData = onboardingPageUiData,
onMakeFirefoxDefaultClick = {}, onMakeFirefoxDefaultClick = {},
onMakeFirefoxDefaultSkipClick = {}, onMakeFirefoxDefaultSkipClick = {},
onPrivacyPolicyClick = {},
onSignInButtonClick = {}, onSignInButtonClick = {},
onSignInSkipClick = {}, onSignInSkipClick = {},
onNotificationPermissionButtonClick = unitLambda, onNotificationPermissionButtonClick = unitLambda,
@ -128,11 +118,6 @@ class OnboardingMapperTest {
imageRes = R.drawable.ic_onboarding_search_widget, imageRes = R.drawable.ic_onboarding_search_widget,
title = "add search widget title", title = "add search widget title",
description = "add search widget body with link text", description = "add search widget body with link text",
linkTextState = LinkTextState(
text = "link text",
url = SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE),
onClick = stringLambda,
),
primaryButton = Action("add search widget primary button text", unitLambda), primaryButton = Action("add search widget primary button text", unitLambda),
secondaryButton = Action("add search widget secondary button text", unitLambda), secondaryButton = Action("add search widget secondary button text", unitLambda),
) )
@ -142,15 +127,14 @@ class OnboardingMapperTest {
imageRes = R.drawable.ic_onboarding_search_widget, imageRes = R.drawable.ic_onboarding_search_widget,
title = "add search widget title", title = "add search widget title",
description = "add search widget body with link text", description = "add search widget body with link text",
linkText = "link text",
primaryButtonLabel = "add search widget primary button text", primaryButtonLabel = "add search widget primary button text",
secondaryButtonLabel = "add search widget secondary button text", secondaryButtonLabel = "add search widget secondary button text",
privacyCaption = null,
) )
val actual = mapToOnboardingPageState( val actual = mapToOnboardingPageState(
onboardingPageUiData = onboardingPageUiData, onboardingPageUiData = onboardingPageUiData,
onMakeFirefoxDefaultClick = {}, onMakeFirefoxDefaultClick = {},
onMakeFirefoxDefaultSkipClick = {}, onMakeFirefoxDefaultSkipClick = {},
onPrivacyPolicyClick = stringLambda,
onSignInButtonClick = {}, onSignInButtonClick = {},
onSignInSkipClick = {}, onSignInSkipClick = {},
onNotificationPermissionButtonClick = {}, onNotificationPermissionButtonClick = {},
@ -164,7 +148,6 @@ class OnboardingMapperTest {
} }
private val unitLambda = { dummyUnitFunc() } private val unitLambda = { dummyUnitFunc() }
private val stringLambda = { s: String -> dummyStringArgFunc(s) }
private fun dummyUnitFunc() {} private fun dummyUnitFunc() {}

@ -56,9 +56,9 @@ private val defaultBrowserPageUiData = OnboardingPageUiData(
imageRes = R.drawable.ic_onboarding_welcome, imageRes = R.drawable.ic_onboarding_welcome,
title = "default browser title", title = "default browser title",
description = "default browser body with link text", description = "default browser body with link text",
linkText = "link text",
primaryButtonLabel = "default browser primary button text", primaryButtonLabel = "default browser primary button text",
secondaryButtonLabel = "default browser secondary button text", secondaryButtonLabel = "default browser secondary button text",
privacyCaption = null,
) )
private val syncPageUiData = OnboardingPageUiData( private val syncPageUiData = OnboardingPageUiData(
@ -68,6 +68,7 @@ private val syncPageUiData = OnboardingPageUiData(
description = "sync body", description = "sync body",
primaryButtonLabel = "sync primary button text", primaryButtonLabel = "sync primary button text",
secondaryButtonLabel = "sync secondary button text", secondaryButtonLabel = "sync secondary button text",
privacyCaption = null,
) )
private val notificationPageUiData = OnboardingPageUiData( private val notificationPageUiData = OnboardingPageUiData(
@ -77,6 +78,7 @@ private val notificationPageUiData = OnboardingPageUiData(
description = "notification body", description = "notification body",
primaryButtonLabel = "notification primary button text", primaryButtonLabel = "notification primary button text",
secondaryButtonLabel = "notification secondary button text", secondaryButtonLabel = "notification secondary button text",
privacyCaption = null,
) )
private val allKnownPages = listOf( private val allKnownPages = listOf(

Loading…
Cancel
Save