diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java index ff0ea0cf5736..368cabb80005 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java @@ -826,4 +826,12 @@ private void dismissSignupSheet() { public AndroidInjector supportFragmentInjector() { return mFragmentInjector; } + + @Override public void showHelpFindingConnectedEmail() { + // Not used in WordPress app + } + + @Override public void gotConnectedSiteInfo(String siteAddress, boolean hasJetpack) { + // Not used in WordPress app + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginAnalyticsTracker.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginAnalyticsTracker.java index 3fd1b6bcb983..c9af77eb8258 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginAnalyticsTracker.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginAnalyticsTracker.java @@ -236,4 +236,18 @@ public void trackUsernamePasswordFormViewed() { public void trackWpComBackgroundServiceUpdate(Map properties) { AnalyticsTracker.track(AnalyticsTracker.Stat.LOGIN_WPCOM_BACKGROUND_SERVICE_UPDATE, properties); } + + @Override public void trackConnectedSiteInfoRequested(String url) { + // Not used in WordPress app + } + + @Override + public void trackConnectedSiteInfoFailed(String url, String errorContext, String errorType, + String errorDescription) { + // Not used in WordPress app + } + + @Override public void trackConnectedSiteInfoSucceeded(Map properties) { + // Not used in WordPress app + } } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 52efb3f9d613..12c001b6453f 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2270,6 +2270,7 @@ Enter your password instead Alternatively: Log in to WordPress.com using an email address to manage all your WordPress sites. + Log in with WordPress.com to connect to %1$s Next Open mail Log in by entering your site address. @@ -2320,6 +2321,8 @@ Google login could not be started. \nMaybe try a different account? Please enter a WordPress.com or Jetpack-connected self-hosted WordPress site + The website at this address is not a WordPress site. For us to connect to it, the site must have WordPress installed. + Need help finding the email you connected with? Email address login Site address login diff --git a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java index 231b1d09d04f..0143865f1d07 100644 --- a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java +++ b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java @@ -51,4 +51,7 @@ public interface LoginAnalyticsListener { void trackUrlHelpScreenViewed(); void trackUsernamePasswordFormViewed(); void trackWpComBackgroundServiceUpdate(Map properties); + void trackConnectedSiteInfoRequested(String url); + void trackConnectedSiteInfoFailed(String url, String errorContext, String errorType, String errorDescription); + void trackConnectedSiteInfoSucceeded(Map properties); } diff --git a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 4480e7ee597c..4fa31858f042 100644 --- a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -1,6 +1,7 @@ package org.wordpress.android.login; import android.app.PendingIntent; +import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.IntentSender; @@ -67,6 +68,9 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private static final int GOOGLE_API_CLIENT_ID = 1002; private static final int EMAIL_CREDENTIALS_REQUEST_CODE = 25100; + private static final String ARG_HIDE_LOGIN_BY_SITE_OPTION = "ARG_HIDE_LOGIN_BY_SITE_OPTION"; + private static final String ARG_LOGIN_SITE_URL = "ARG_LOGIN_SITE_URL"; + public static final String TAG = "login_email_fragment_tag"; public static final int MAX_EMAIL_LENGTH = 100; @@ -79,6 +83,17 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp protected WPLoginInputRow mEmailInput; protected boolean mHasDismissedEmailHints; protected boolean mIsDisplayingEmailHints; + protected boolean mHideLoginWithSiteOption; + protected String mLoginSiteUrl; + + public static LoginEmailFragment newInstance(Boolean hideLoginWithSiteOption, String url) { + LoginEmailFragment fragment = new LoginEmailFragment(); + Bundle args = new Bundle(); + args.putBoolean(ARG_HIDE_LOGIN_BY_SITE_OPTION, hideLoginWithSiteOption); + args.putString(ARG_LOGIN_SITE_URL, url); + fragment.setArguments(args); + return fragment; + } @Override protected @LayoutRes int getContentLayout() { @@ -103,6 +118,9 @@ protected void setupLabel(@NonNull TextView label) { case WPCOM_LOGIN_ONLY: label.setText(R.string.enter_email_wordpress_com); break; + case WOO_LOGIN_MODE: + label.setText(getString(R.string.enter_email_for_site, mLoginSiteUrl)); + break; case JETPACK_STATS: label.setText(R.string.login_to_to_connect_jetpack); break; @@ -162,18 +180,22 @@ public void onClick(View view) { }); LinearLayout siteLoginButton = rootView.findViewById(R.id.login_site_button); - siteLoginButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - if (mLoginListener != null) { - if (mLoginListener.getLoginMode() == LoginMode.JETPACK_STATS) { - mLoginListener.loginViaWpcomUsernameInstead(); - } else { - mLoginListener.loginViaSiteAddress(); + if (mHideLoginWithSiteOption) { + siteLoginButton.setVisibility(View.GONE); + } else { + siteLoginButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if (mLoginListener != null) { + if (mLoginListener.getLoginMode() == LoginMode.JETPACK_STATS) { + mLoginListener.loginViaWpcomUsernameInstead(); + } else { + mLoginListener.loginViaSiteAddress(); + } } } - } - }); + }); + } ImageView siteLoginButtonIcon = rootView.findViewById(R.id.login_site_button_icon); TextView siteLoginButtonText = rootView.findViewById(R.id.login_site_button_text); @@ -181,6 +203,7 @@ public void onClick(View view) { switch (mLoginListener.getLoginMode()) { case FULL: case WPCOM_LOGIN_ONLY: + case WOO_LOGIN_MODE: case SHARE_INTENT: siteLoginButtonIcon.setImageResource(R.drawable.ic_domains_grey_24dp); siteLoginButtonText.setText(R.string.enter_site_address_instead); @@ -211,6 +234,13 @@ public void onClick(View view) { } } }); + } else if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { + secondaryButton.setText(getResources().getString(R.string.login_need_help_finding_connected_email)); + secondaryButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + mLoginListener.showHelpFindingConnectedEmail(); + } + }); } else { secondaryButton.setVisibility(View.GONE); } @@ -244,6 +274,13 @@ public void onAttach(Context context) { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + Bundle args = getArguments(); + if (args != null) { + mHideLoginWithSiteOption = args.getBoolean(ARG_HIDE_LOGIN_BY_SITE_OPTION, false); + mLoginSiteUrl = args.getString(ARG_LOGIN_SITE_URL, ""); + } + mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) .addConnectionCallbacks(LoginEmailFragment.this) .enableAutoManage(getActivity(), GOOGLE_API_CLIENT_ID, LoginEmailFragment.this) @@ -445,6 +482,8 @@ public void getEmailHints() { startIntentSenderForResult(intent.getIntentSender(), EMAIL_CREDENTIALS_REQUEST_CODE, null, 0, 0, 0, null); } catch (IntentSender.SendIntentException exception) { AppLog.d(T.NUX, LOG_TAG + "Could not start email hint picker" + exception); + } catch (ActivityNotFoundException exception) { + AppLog.d(T.NUX, LOG_TAG + "Could not find any activity to handle email hint picker" + exception); } } diff --git a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginListener.java index dd0a215a455d..a55fb4125142 100644 --- a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginListener.java @@ -26,6 +26,7 @@ interface SelfSignedSSLCallback { void helpEmailScreen(String email); void helpSocialEmailScreen(String email); void addGoogleLoginFragment(); + void showHelpFindingConnectedEmail(); // Login Request Magic Link callbacks void showMagicLinkSentScreen(String email); @@ -47,6 +48,7 @@ interface SelfSignedSSLCallback { // Login Site Address input callbacks void alreadyLoggedInWpcom(ArrayList oldSitesIds); void gotWpcomSiteInfo(String siteAddress, String siteName, String siteIconUrl); + void gotConnectedSiteInfo(String siteAddress, boolean hasJetpack); void gotXmlRpcEndpoint(String inputSiteAddress, String endpointAddress); void handleSslCertificateError(MemorizingTrustManager memorizingTrustManager, SelfSignedSSLCallback callback); void helpSiteAddress(String url); diff --git a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginMode.java b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginMode.java index 8e569c053bd1..c71973571efb 100644 --- a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginMode.java +++ b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginMode.java @@ -9,7 +9,8 @@ public enum LoginMode { JETPACK_STATS, WPCOM_LOGIN_DEEPLINK, WPCOM_REAUTHENTICATE, - SHARE_INTENT; + SHARE_INTENT, + WOO_LOGIN_MODE; private static final String ARG_LOGIN_MODE = "ARG_LOGIN_MODE"; diff --git a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index 1afbed9187a4..2bcbfff80faa 100644 --- a/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -29,6 +29,7 @@ import org.wordpress.android.fluxc.network.discovery.SelfHostedEndpointFinder.DiscoveryError; import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.AccountStore.OnDiscoveryResponse; +import org.wordpress.android.fluxc.store.SiteStore.OnConnectSiteInfoChecked; import org.wordpress.android.fluxc.store.SiteStore.OnWPComSiteFetched; import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.widgets.WPLoginInputRow; @@ -40,6 +41,7 @@ import org.wordpress.android.util.UrlUtils; import java.util.ArrayList; +import java.util.HashMap; import javax.inject.Inject; @@ -87,6 +89,9 @@ protected void setupContent(ViewGroup rootView) { // important for accessibility - talkback getActivity().setTitle(R.string.site_address_login_title); mSiteAddressInput = rootView.findViewById(R.id.login_site_address_row); + if (BuildConfig.DEBUG) { + mSiteAddressInput.getEditText().setText(BuildConfig.DEBUG_WPCOM_WEBSITE_URL); + } mSiteAddressInput.addTextChangedListener(this); mSiteAddressInput.setOnEditorCommitListener(this); } @@ -163,7 +168,16 @@ protected void discover() { mRequestedSiteAddress = cleanedSiteAddress; String cleanedXmlrpcSuffix = UrlUtils.removeXmlrpcSuffix(mRequestedSiteAddress); - mDispatcher.dispatch(SiteActionBuilder.newFetchWpcomSiteByUrlAction(cleanedXmlrpcSuffix)); + + if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { + // TODO: This is temporary code to test out sign in flow milestone 1 effectiveness. If we move + // forward with this flow, we will need to just call the XMLRPC discovery code and handle all the + // edge cases such as HTTP auth and self-signed SSL. + mAnalyticsListener.trackConnectedSiteInfoRequested(cleanedXmlrpcSuffix); + mDispatcher.dispatch(SiteActionBuilder.newFetchConnectSiteInfoAction(cleanedXmlrpcSuffix)); + } else { + mDispatcher.dispatch(SiteActionBuilder.newFetchWpcomSiteByUrlAction(cleanedXmlrpcSuffix)); + } startProgress(); } @@ -354,4 +368,65 @@ public void onDiscoverySucceeded(OnDiscoveryResponse event) { AppLog.i(T.NUX, "Discovery succeeded, endpoint: " + event.xmlRpcEndpoint); mLoginListener.gotXmlRpcEndpoint(requestedSiteAddress, event.xmlRpcEndpoint); } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { + if (mRequestedSiteAddress == null) { + // bail if user canceled + return; + } + + if (!isAdded()) { + return; + } + + // hold the URL in a variable to use below otherwise it gets cleared up by endProgress + final String requestedSiteAddress = mRequestedSiteAddress; + + if (isInProgress()) { + endProgress(); + } + + if (event.isError()) { + mAnalyticsListener.trackConnectedSiteInfoFailed( + requestedSiteAddress, + event.getClass().getSimpleName(), + event.error.type.name(), + event.error.message); + + AppLog.e(T.API, "onFetchedConnectSiteInfo has error: " + event.error.message); + + showError(R.string.invalid_site_url_message); + } else { + // TODO: If we plan to keep this logic we should convert these labels to constants + HashMap properties = new HashMap<>(); + properties.put("url", event.info.url); + properties.put("urlAfterRedirects", event.info.urlAfterRedirects); + properties.put("exists", Boolean.toString(event.info.exists)); + properties.put("hasJetpack", Boolean.toString(event.info.hasJetpack)); + properties.put("isJetpackActive", Boolean.toString(event.info.isJetpackActive)); + properties.put("isJetpackConnected", Boolean.toString(event.info.isJetpackConnected)); + properties.put("isWordPress", Boolean.toString(event.info.isWordPress)); + properties.put("isWPCom", Boolean.toString(event.info.isWPCom)); + mAnalyticsListener.trackConnectedSiteInfoSucceeded(properties); + + if (!event.info.exists) { + // Site does not exist + showError(R.string.invalid_site_url_message); + } else if (!event.info.isWordPress) { + // Not a WordPress site + showError(R.string.enter_wordpress_site); + } else { + boolean hasJetpack = false; + if (event.info.isWPCom && event.info.hasJetpack) { + // This is likely an atomic site. + hasJetpack = true; + } else if (event.info.hasJetpack && event.info.isJetpackActive && event.info.isJetpackConnected) { + hasJetpack = true; + } + mLoginListener.gotConnectedSiteInfo(event.info.url, hasJetpack); + } + } + } } diff --git a/libs/login/WordPressLoginFlow/src/main/res/layout/login_email_password_screen.xml b/libs/login/WordPressLoginFlow/src/main/res/layout/login_email_password_screen.xml index d0fb277070dd..bd28c1e74ca3 100644 --- a/libs/login/WordPressLoginFlow/src/main/res/layout/login_email_password_screen.xml +++ b/libs/login/WordPressLoginFlow/src/main/res/layout/login_email_password_screen.xml @@ -18,6 +18,8 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/margin_extra_large" android:layout_marginBottom="@dimen/margin_extra_large" + android:textAlignment="viewStart" + android:gravity="start" tools:text="@string/enter_site_address" /> diff --git a/libs/login/WordPressLoginFlow/src/main/res/layout/login_form_screen.xml b/libs/login/WordPressLoginFlow/src/main/res/layout/login_form_screen.xml index bbcd96e240e0..b73464ee00ae 100644 --- a/libs/login/WordPressLoginFlow/src/main/res/layout/login_form_screen.xml +++ b/libs/login/WordPressLoginFlow/src/main/res/layout/login_form_screen.xml @@ -52,6 +52,7 @@ android:paddingEnd="@dimen/margin_medium_large" android:layout_marginRight="@dimen/margin_extra_large" android:layout_marginEnd="@dimen/margin_extra_large" + android:textAlignment="viewStart" android:gravity="start|center_vertical" tools:text="Secondary action"/> diff --git a/libs/login/WordPressLoginFlow/src/main/res/layout/login_site_address_screen.xml b/libs/login/WordPressLoginFlow/src/main/res/layout/login_site_address_screen.xml index 31adda6f3563..305760d03a13 100644 --- a/libs/login/WordPressLoginFlow/src/main/res/layout/login_site_address_screen.xml +++ b/libs/login/WordPressLoginFlow/src/main/res/layout/login_site_address_screen.xml @@ -17,6 +17,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margin_extra_large" + android:textAlignment="viewStart" + android:gravity="start" android:layout_marginBottom="@dimen/margin_extra_large" tools:text="@string/enter_site_address" /> diff --git a/libs/login/WordPressLoginFlow/src/main/res/values/strings.xml b/libs/login/WordPressLoginFlow/src/main/res/values/strings.xml index 8ad1509f0c47..26c045e7c2ab 100644 --- a/libs/login/WordPressLoginFlow/src/main/res/values/strings.xml +++ b/libs/login/WordPressLoginFlow/src/main/res/values/strings.xml @@ -15,6 +15,7 @@ Your notifications travel with you — see comments and likes as they happen. Manage your Jetpack-powered site on the go — you\'ve got WordPress in your pocket. Log in to WordPress.com using an email address to manage all your WordPress sites. + Log in with WordPress.com to connect to %1$s Next Open mail Alternatively: @@ -100,7 +101,7 @@ site XMLRPC endpoint. The app needs that in order to communicate with your site. Contact your host to solve this problem. Please enter a WordPress.com or Jetpack-connected self-hosted WordPress site - + The website at this address is not a WordPress site. For us to connect to it, the site must have WordPress installed. A network error occurred. Please check your connection and try again. Logged in! @@ -139,4 +140,6 @@ placeholder + + Need help finding the email you connected with? diff --git a/libs/login/gradle.properties-example b/libs/login/gradle.properties-example index 829868372efd..d6cbf29bcc27 100644 --- a/libs/login/gradle.properties-example +++ b/libs/login/gradle.properties-example @@ -4,6 +4,7 @@ wp.debug.wpcom_login_email = wp.debug.wpcom_login_username = wp.debug.wpcom_login_password = +wp.debug.wpcom_website_url = android.useAndroidX=true android.enableJetifier=true