diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsTracker.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsTracker.kt index a040e89f8751..9e522fb3d576 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsTracker.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsTracker.kt @@ -525,6 +525,7 @@ class AnalyticsTracker private constructor( // -- Jetpack Setup const val KEY_JETPACK_SETUP_IS_ALREADY_CONNECTED = "is_already_connected" const val KEY_JETPACK_SETUP_REQUIRES_CONNECTION_ONLY = "requires_connection_only" + const val KEY_IS_SIGN_UP = "is_signup" const val VALUE_JETPACK_SETUP_STEP_EMAIL_ADDRESS = "email_address" const val VALUE_JETPACK_SETUP_STEP_PASSWORD = "password" const val VALUE_JETPACK_SETUP_STEP_MAGIC_LINK = "magic_link" diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/WPComLoginRepository.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/WPComLoginRepository.kt index 70a7ea909c3c..e57be5402674 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/WPComLoginRepository.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/WPComLoginRepository.kt @@ -76,13 +76,18 @@ class WPComLoginRepository @Inject constructor( } } - suspend fun requestMagicLink(emailOrUsername: String, flow: MagicLinkFlow, source: MagicLinkSource): Result { + suspend fun requestMagicLink( + emailOrUsername: String, + flow: MagicLinkFlow, + source: MagicLinkSource, + isSignup: Boolean + ): Result { WooLog.i(WooLog.T.LOGIN, "Submitting a Magic Link request") val action = AuthenticationActionBuilder.newSendAuthEmailAction( AuthEmailPayload( emailOrUsername, - false, + isSignup, flow, source, AuthEmailPayloadScheme.WOOCOMMERCE @@ -98,6 +103,7 @@ class WPComLoginRepository @Inject constructor( ) Result.failure(OnChangedException(event.error)) } + else -> { WooLog.i(WooLog.T.LOGIN, "Magic Link request sent successfully") Result.success(Unit) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationMagicLinkRequestScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationMagicLinkRequestScreen.kt index d6778d5ff08b..263a4e11f850 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationMagicLinkRequestScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationMagicLinkRequestScreen.kt @@ -172,12 +172,19 @@ private fun MagicLinkSentContent( style = MaterialTheme.typography.subtitle1, textAlign = TextAlign.Center ) + Spacer(modifier = Modifier.height(dimensionResource(id = R.dimen.minor_50))) Text( text = viewState.email, style = MaterialTheme.typography.subtitle1, fontWeight = FontWeight.Bold, textAlign = TextAlign.Center ) + Spacer(modifier = Modifier.height(dimensionResource(id = R.dimen.major_100))) + Text( + text = stringResource(id = R.string.login_magic_links_email_sent_double_check_email), + style = MaterialTheme.typography.body2, + textAlign = TextAlign.Center + ) } else { Text( text = stringResource(id = R.string.login_magic_links_email_sent_to_unknown_email), @@ -208,7 +215,8 @@ private fun MagicLinkRequestPreview() { avatarUrl = "avatar", isJetpackInstalled = false, allowPasswordLogin = true, - isLoadingDialogShown = false + isLoadingDialogShown = false, + isNewWpComAccount = false ) ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationMagicLinkRequestViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationMagicLinkRequestViewModel.kt index 382abde6004d..b9867f16fad9 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationMagicLinkRequestViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationMagicLinkRequestViewModel.kt @@ -46,7 +46,8 @@ class JetpackActivationMagicLinkRequestViewModel @Inject constructor( avatarUrl = avatarUrlFromEmail(navArgs.emailOrUsername), isJetpackInstalled = navArgs.jetpackStatus.isJetpackInstalled, allowPasswordLogin = !navArgs.isAccountPasswordless, - isLoadingDialogShown = false + isLoadingDialogShown = false, + isNewWpComAccount = navArgs.isNewWpComAccount ) ) val viewState = _viewState.asLiveData() @@ -72,7 +73,8 @@ class JetpackActivationMagicLinkRequestViewModel @Inject constructor( JETPACK_SETUP_LOGIN_FLOW, mapOf( AnalyticsTracker.KEY_STEP to AnalyticsTracker.VALUE_JETPACK_SETUP_STEP_MAGIC_LINK, - AnalyticsTracker.KEY_TAP to AnalyticsTracker.VALUE_DISMISS + AnalyticsTracker.KEY_TAP to AnalyticsTracker.VALUE_DISMISS, + AnalyticsTracker.KEY_IS_SIGN_UP to navArgs.isNewWpComAccount ) ) } @@ -82,7 +84,8 @@ class JetpackActivationMagicLinkRequestViewModel @Inject constructor( JETPACK_SETUP_LOGIN_FLOW, mapOf( AnalyticsTracker.KEY_STEP to AnalyticsTracker.VALUE_JETPACK_SETUP_STEP_MAGIC_LINK, - AnalyticsTracker.KEY_TAP to AnalyticsTracker.VALUE_SUBMIT + AnalyticsTracker.KEY_TAP to AnalyticsTracker.VALUE_SUBMIT, + AnalyticsTracker.KEY_IS_SIGN_UP to navArgs.isNewWpComAccount ) ) @@ -91,7 +94,8 @@ class JetpackActivationMagicLinkRequestViewModel @Inject constructor( avatarUrl = avatarUrlFromEmail(navArgs.emailOrUsername), isJetpackInstalled = navArgs.jetpackStatus.isJetpackInstalled, allowPasswordLogin = !navArgs.isAccountPasswordless, - isLoadingDialogShown = true + isLoadingDialogShown = true, + isNewWpComAccount = navArgs.isNewWpComAccount ) val source = when { !navArgs.jetpackStatus.isJetpackInstalled -> MagicLinkSource.JetpackInstallation @@ -101,7 +105,8 @@ class JetpackActivationMagicLinkRequestViewModel @Inject constructor( wpComLoginRepository.requestMagicLink( emailOrUsername = navArgs.emailOrUsername, flow = MagicLinkFlow.SiteCredentialsToWPCom, - source = source + source = source, + isSignup = navArgs.isNewWpComAccount ).fold( onSuccess = { _viewState.value = ViewState.MagicLinkSentState( @@ -118,7 +123,8 @@ class JetpackActivationMagicLinkRequestViewModel @Inject constructor( JETPACK_SETUP_LOGIN_FLOW, mapOf( AnalyticsTracker.KEY_STEP to AnalyticsTracker.VALUE_JETPACK_SETUP_STEP_MAGIC_LINK, - AnalyticsTracker.KEY_TAP to AnalyticsTracker.VALUE_SUBMIT + AnalyticsTracker.KEY_TAP to AnalyticsTracker.VALUE_SUBMIT, + AnalyticsTracker.KEY_IS_SIGN_UP to navArgs.isNewWpComAccount ) ) } @@ -145,7 +151,8 @@ class JetpackActivationMagicLinkRequestViewModel @Inject constructor( val avatarUrl: String, override val isJetpackInstalled: Boolean, override val allowPasswordLogin: Boolean, - val isLoadingDialogShown: Boolean + val isLoadingDialogShown: Boolean, + val isNewWpComAccount: Boolean ) : ViewState @Parcelize diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailFragment.kt index b9cae27c429d..b442c4d381c6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailFragment.kt @@ -79,7 +79,8 @@ class JetpackActivationWPComEmailFragment : BaseFragment() { .actionJetpackActivationWPComEmailFragmentToJetpackActivationMagicLinkRequestFragment( emailOrUsername = event.emailOrUsername, jetpackStatus = event.jetpackStatus, - isAccountPasswordless = true + isAccountPasswordless = true, + isNewWpComAccount = event.isNewWpComAccount ) ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailScreen.kt index 395f800ce863..60de5d654387 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailScreen.kt @@ -18,7 +18,6 @@ import androidx.compose.material.icons.Icons.Filled import androidx.compose.material.icons.filled.Clear import androidx.compose.runtime.Composable import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.dimensionResource @@ -47,7 +46,6 @@ fun JetpackActivationWPComEmailScreen(viewModel: JetpackActivationWPComEmailView } } -@OptIn(ExperimentalComposeUiApi::class) @Composable fun JetpackActivationWPComEmailScreen( viewState: JetpackActivationWPComEmailViewModel.ViewState, @@ -115,6 +113,11 @@ fun JetpackActivationWPComEmailScreen( } ) ) + Spacer(modifier = Modifier.height(dimensionResource(id = R.dimen.major_100))) + Text( + style = MaterialTheme.typography.body2, + text = stringResource(id = R.string.login_jetpack_connection_create_account) + ) } Spacer(modifier = Modifier.weight(1f)) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailViewModel.kt index 71090bb07afd..81c0c108d621 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComEmailViewModel.kt @@ -4,11 +4,14 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import com.woocommerce.android.OnChangedException +import com.woocommerce.android.R import com.woocommerce.android.analytics.AnalyticsEvent.JETPACK_SETUP_LOGIN_FLOW import com.woocommerce.android.analytics.AnalyticsTracker import com.woocommerce.android.analytics.AnalyticsTrackerWrapper import com.woocommerce.android.model.JetpackStatus import com.woocommerce.android.ui.login.WPComLoginRepository +import com.woocommerce.android.util.FeatureFlag +import com.woocommerce.android.util.StringUtils import com.woocommerce.android.viewmodel.MultiLiveEvent import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.ShowSnackbar @@ -21,7 +24,6 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch import org.wordpress.android.fluxc.store.AccountStore.AuthOptionsError import org.wordpress.android.fluxc.store.AccountStore.AuthOptionsErrorType -import org.wordpress.android.login.R import javax.inject.Inject @HiltViewModel @@ -90,17 +92,36 @@ class JetpackActivationWPComEmailViewModel @Inject constructor( wpComLoginRepository.fetchAuthOptions(emailOrUsername).fold( onSuccess = { if (it.isPasswordless) { - triggerEvent(ShowMagicLinkScreen(emailOrUsername, navArgs.jetpackStatus)) + triggerEvent( + ShowMagicLinkScreen(emailOrUsername, navArgs.jetpackStatus, isNewWpComAccount = false) + ) } else { triggerEvent(ShowPasswordScreen(emailOrUsername, navArgs.jetpackStatus)) } }, onFailure = { val failure = (it as? OnChangedException)?.error as? AuthOptionsError + var isSignup = false when (failure?.type) { AuthOptionsErrorType.UNKNOWN_USER -> { - errorMessage.value = R.string.email_not_registered_wpcom + when { + !StringUtils.isValidEmail(emailOrUsername) -> + errorMessage.value = R.string.username_not_registered_wpcom + + FeatureFlag.JETPACK_FLOW_ACCOUNT_CREATION.isEnabled() -> { + triggerEvent( + ShowMagicLinkScreen( + emailOrUsername, + navArgs.jetpackStatus, + isNewWpComAccount = true + ) + ) + isSignup = true + } + + else -> errorMessage.value = R.string.email_not_registered_wpcom + } } AuthOptionsErrorType.EMAIL_LOGIN_NOT_ALLOWED -> { @@ -113,18 +134,26 @@ class JetpackActivationWPComEmailViewModel @Inject constructor( } } - analyticsTrackerWrapper.track( - JETPACK_SETUP_LOGIN_FLOW, - mapOf( - AnalyticsTracker.KEY_STEP to AnalyticsTracker.VALUE_JETPACK_SETUP_STEP_EMAIL_ADDRESS, - AnalyticsTracker.KEY_FAILURE to (failure?.type?.name ?: "Unknown error") - ) - ) + trackLoginFlowAuthOptionError(failure, isSignup) } ) isLoadingDialogShown.value = false } + private fun trackLoginFlowAuthOptionError( + failure: AuthOptionsError?, + isSignup: Boolean + ) { + analyticsTrackerWrapper.track( + JETPACK_SETUP_LOGIN_FLOW, + mapOf( + AnalyticsTracker.KEY_STEP to AnalyticsTracker.VALUE_JETPACK_SETUP_STEP_EMAIL_ADDRESS, + AnalyticsTracker.KEY_FAILURE to (failure?.type?.name ?: "Unknown error"), + AnalyticsTracker.KEY_IS_SIGN_UP to isSignup + ) + ) + } + data class ViewState( val emailOrUsername: String, val isJetpackInstalled: Boolean, @@ -141,6 +170,7 @@ class JetpackActivationWPComEmailViewModel @Inject constructor( data class ShowMagicLinkScreen( val emailOrUsername: String, - val jetpackStatus: JetpackStatus + val jetpackStatus: JetpackStatus, + val isNewWpComAccount: Boolean, ) : MultiLiveEvent.Event() } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComPasswordFragment.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComPasswordFragment.kt index f8981a2fd6ba..104067092df2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComPasswordFragment.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/login/jetpack/wpcom/JetpackActivationWPComPasswordFragment.kt @@ -98,7 +98,8 @@ class JetpackActivationWPComPasswordFragment : BaseFragment() { .actionJetpackActivationWPComPasswordFragmentToJetpackActivationMagicLinkRequestFragment( emailOrUsername = event.emailOrUsername, jetpackStatus = event.jetpackStatus, - isAccountPasswordless = false + isAccountPasswordless = false, + isNewWpComAccount = false ) ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt index 200aebc1dd6f..879bdda64395 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/FeatureFlag.kt @@ -19,7 +19,8 @@ enum class FeatureFlag { CUSTOM_FIELDS, REVAMP_WOO_SHIPPING, OBJECTIVE_SECTION, - POS_NON_SIMPLE_PRODUCT_TYPES; + POS_NON_SIMPLE_PRODUCT_TYPES, + JETPACK_FLOW_ACCOUNT_CREATION; fun isEnabled(context: Context? = null): Boolean { return when (this) { @@ -32,7 +33,8 @@ enum class FeatureFlag { ORDER_CREATION_AUTO_TAX_RATE, WOO_POS_PAYMENTS_ONBOARDING, REVAMP_WOO_SHIPPING, - POS_NON_SIMPLE_PRODUCT_TYPES -> PackageUtils.isDebugBuild() + POS_NON_SIMPLE_PRODUCT_TYPES, + JETPACK_FLOW_ACCOUNT_CREATION -> PackageUtils.isDebugBuild() NEW_SHIPPING_SUPPORT, INBOX, diff --git a/WooCommerce/src/main/res/navigation/nav_graph_jetpack_activation.xml b/WooCommerce/src/main/res/navigation/nav_graph_jetpack_activation.xml index df82d70019b6..10c327447f61 100644 --- a/WooCommerce/src/main/res/navigation/nav_graph_jetpack_activation.xml +++ b/WooCommerce/src/main/res/navigation/nav_graph_jetpack_activation.xml @@ -146,6 +146,9 @@ + Fetching site… Unable to login because application password creation is not approved. We couldn\'t process your app login request + If you don\'t have an account, we\'ll use this email to create one. + @@ -3428,6 +3430,7 @@ Log in with magic link Hmm, we can\'t find a WordPress.com account connected to this email address. + Hmm, we can\'t find a WordPress.com account connected to this username. You can enter an email to create a new account. We\'ll email you a link that\'ll log you in instantly, no password needed. Get a login link by email We’ve emailed you a signup link to create your new WordPress.com account. Check your email on this device, and tap the link in the email you receive from WordPress.com. @@ -3510,6 +3513,7 @@ Use password to sign in Check your email on this device! We just sent a magic link to + Ensure your email is correct and double check your spam folder. We just sent a magic link to your account\'s email address Try another address Or log in with password diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6cb4df8f5fab..24a024214fae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -86,7 +86,7 @@ stripe-terminal = '3.7.1' tinder-statemachine = '0.2.0' wiremock = '2.26.3' wordpress-aztec = 'v2.1.4' -wordpress-fluxc = 'trunk-cc17141a0e910d5b808ba6bbfb4b7d393d3517a0' +wordpress-fluxc = 'trunk-3b731c31d9f8ca9765a1de9ec8d4d064b88ec30a' wordpress-login = '1.19.0' wordpress-libaddressinput = '0.0.2' wordpress-mediapicker = '0.3.1'