Skip to content

Commit 1ea540b

Browse files
committed
Squashed 'libs/login/' changes from 8b6384cb59..4b8e83512d
4b8e83512d Added logic to redirect to discovery error if xmlrpc is blocked on site 2c3223bbe7 Reverted logic to check for Jetpack availability during discovery errors since it can return a false negative 846dc2ba99 Handle site not found discovery error which can occur even with Jetpack available e1028df7f4 Modified logic to check for discovery errors first before checking for Jetpack 16c1bbe249 Modified error message for xmlrpc errors 732a0486e7 Modified logic to initiate discovery from LoginBaseDiscoveryFragment fdfb9df9b7 Added logic to redirect to discovery error screen, even if Jetpack is available 0833d5ca77 Add flag to check if Jetpack is available if a discovery error takes place aa7f8cc9d9 Added logic to port over changes from the LoginSiteAddressFragment to utilise LoginBaseDiscoveryFragment e1f2ff2d37 Modified discovery error listener to handle the various error scenarios from the calling fragment a1bc462454 Added option to verify email only if login is for self hosted credentials c2f2bba7a8 Added new string labels for magic link sent label b4b9dbcabb Merge branch 'feature/sign-in-with-self-hosted-credentials' into issue/1482-step2-magic-link-signin-changes 32d2c25fd9 Handle corner case in discovery process and redirect to email screen if site is wp.com d96252d875 Fixed nitpicks in code/xml 9b227c817b Design changes for request magic link screen a8712882c1 Hide keyboard before redirecting to the magic link/no jetpack screen e4e8210da2 Added logic to initiate discovery process for xmlrpc endpoint 2c35450824 Added logic to pass the input site address to forgot password flow, if the xmlrpc url is empty f9ff33ec87 Added separate method to redirect to username screen in LoginListener f71a4065b0 Revert discovery initiation changes to the site fragment 1e3e9cf367 Added logic to fetch SiteModel based on the site url 71ec9bdaec Added logic to redirect to no Jetpack screen when site credentials are entered ad42794306 Revert adding a new method to LoginListener, instead use an existing listener method 8f3649b4b5 Added logic to fetch jetpack user email from site credentials and redirect to magic link screen aa0d39d792 Pass site xmlrpc url to email and jetpack required screen 360480c6ff Initiate discovery process even if jetpack is not installed/active/connected 39b0ee010f Added logic to redirect Woo users to email login or jetpack required screen efd18a8cef Revert the connection info endpoint implementation and update error message when site is not found 96e0ff714f Added label to the top of the LoginUsernamePasswordFragment for Woo login only 082d1e1304 Display login with site credentials link button in login email fragment 27b07bf3e1 Merge commit 'f89f408ee83d29d59dfe5740b2ba26c51dcd00df' into issue/1446-login-lib-merge 2406304ffa Merge pull request #27 from wordpress-mobile/google_login_fix 18ddefd54b Merge pull request #10523 from wordpress-mobile/feature/move_api_client_builder_to_start_stop a87f1ec203 Update Jitpack dependency urls to use the www subdomain 24bb535488 Implement PR comments b63bb72af9 Remove api client cleanup from onDetach bd3410e2ad Move GoogleApiClient.Builder to onStart/Stop methods d70141070b Add commit message for jetpack validation fix 80b21579cf Use only the isJetpackConnected property for jetpack validation c3f9b19157 Merge pull request #10321 from wordpress-mobile/login/fix-login-tracks 0b734cf390 Merge pull request #10270 from wordpress-mobile/issue/9720-login-subtree-update-squashed eb90f72905 Merge pull request #1312 from woocommerce/merge-login-lib bd6086802b Merge commit 'aec4a8317d3188866c02556c182cd8d09d9b0272' into merge-login-lib 378a45be3e Fix leak of anonymous OnCancelListener reference 71cfd27b21 Merge branch 'develop' into amanda/leak_canary 42cf2d56ec Merge pull request #1292 from woocommerce/release/2.3 67de44ca60 Merge branch 'release/2.3' into merge-release/2.2.1-release/2.3 227c48b323 Merge pull request #1277 from woocommerce/merge/WordPress-Login-Flow-Android/24 0123a10b6b Reverted changes to login build.gradle ff16da7e70 Reverted back to SDK 28 (we can update to 29 once Android Q is out of beta) d433fad0df Merge commit '9bb4617dddea713295ce4b53a60aa2a271f318a2' squashed b0b4f17f8a Merge commit 'f6c4fbfadce780aaebc745154c29affe46978545' into issue/9720-login-subtree-update-squashed 66695843b0 Upgraded login library to SDK 29 ff4a69e142 Add leak canary and fix leaks git-subtree-dir: libs/login git-subtree-split: 4b8e83512da7628a11c4b075cf79ac6e3b9864ec
1 parent d4604b8 commit 1ea540b

13 files changed

+418
-144
lines changed

WordPressLoginFlow/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ apply plugin: 'com.android.library'
1313
repositories {
1414
google()
1515
jcenter()
16-
maven { url "https://jitpack.io" }
16+
maven { url "https://www.jitpack.io" }
1717
}
1818

1919
android {
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package org.wordpress.android.login;
2+
3+
import org.greenrobot.eventbus.Subscribe;
4+
import org.greenrobot.eventbus.ThreadMode;
5+
import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder;
6+
import org.wordpress.android.fluxc.network.discovery.SelfHostedEndpointFinder.DiscoveryError;
7+
import org.wordpress.android.fluxc.store.AccountStore.OnDiscoveryResponse;
8+
import org.wordpress.android.util.AppLog;
9+
import org.wordpress.android.util.AppLog.T;
10+
import org.wordpress.android.util.NetworkUtils;
11+
12+
public abstract class LoginBaseDiscoveryFragment extends LoginBaseFormFragment<LoginListener> {
13+
LoginBaseDiscoveryListener mLoginBaseDiscoveryListener;
14+
15+
public interface LoginBaseDiscoveryListener {
16+
String getRequestedSiteAddress();
17+
void handleWpComDiscoveryError(String failedEndpoint);
18+
void handleDiscoverySuccess(String endpointAddress);
19+
void handleDiscoveryError(DiscoveryError error, String failedEndpoint);
20+
}
21+
22+
@Override
23+
public void onDetach() {
24+
super.onDetach();
25+
mLoginBaseDiscoveryListener = null;
26+
}
27+
28+
void initiateDiscovery() {
29+
if (!NetworkUtils.checkConnection(getActivity())) {
30+
return;
31+
}
32+
33+
// Start the discovery process
34+
mDispatcher.dispatch(AuthenticationActionBuilder.newDiscoverEndpointAction(
35+
mLoginBaseDiscoveryListener.getRequestedSiteAddress()));
36+
}
37+
38+
@SuppressWarnings("unused")
39+
@Subscribe(threadMode = ThreadMode.MAIN)
40+
public void onDiscoverySucceeded(OnDiscoveryResponse event) {
41+
// hold the URL in a variable to use below otherwise it gets cleared up by endProgress
42+
// bail if user canceled
43+
String mRequestedSiteAddress = mLoginBaseDiscoveryListener.getRequestedSiteAddress();
44+
if (mRequestedSiteAddress == null) {
45+
return;
46+
}
47+
48+
if (!isAdded()) {
49+
return;
50+
}
51+
52+
if (event.isError()) {
53+
if (isInProgress()) {
54+
endProgress();
55+
}
56+
57+
mAnalyticsListener.trackLoginFailed(event.getClass().getSimpleName(),
58+
event.error.name(), event.error.toString());
59+
60+
AppLog.e(T.API, "onDiscoveryResponse has error: " + event.error.name()
61+
+ " - " + event.error.toString());
62+
handleDiscoveryError(event.error, event.failedEndpoint);
63+
return;
64+
}
65+
66+
AppLog.i(T.NUX, "Discovery succeeded, endpoint: " + event.xmlRpcEndpoint);
67+
mLoginBaseDiscoveryListener.handleDiscoverySuccess(event.xmlRpcEndpoint);
68+
}
69+
70+
private void handleDiscoveryError(DiscoveryError error, final String failedEndpoint) {
71+
if (error == DiscoveryError.WORDPRESS_COM_SITE) {
72+
mLoginBaseDiscoveryListener.handleWpComDiscoveryError(failedEndpoint);
73+
} else {
74+
mLoginBaseDiscoveryListener.handleDiscoveryError(error, failedEndpoint);
75+
}
76+
}
77+
}

WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ protected void endProgress() {
237237

238238
if (mProgressDialog != null) {
239239
mProgressDialog.cancel();
240+
mProgressDialog.setOnCancelListener(null);
240241
mProgressDialog = null;
241242
}
242243

WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginEmailFragment.java

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@
5252
import java.util.regex.Matcher;
5353
import java.util.regex.Pattern;
5454

55-
import dagger.android.support.AndroidSupportInjection;
56-
5755
import static android.app.Activity.RESULT_OK;
5856

57+
import dagger.android.support.AndroidSupportInjection;
58+
5959
public class LoginEmailFragment extends LoginBaseFormFragment<LoginListener> implements TextWatcher,
6060
OnEditorCommitListener, ConnectionCallbacks, OnConnectionFailedListener {
6161
private static final String KEY_GOOGLE_EMAIL = "KEY_GOOGLE_EMAIL";
@@ -68,7 +68,6 @@ public class LoginEmailFragment extends LoginBaseFormFragment<LoginListener> imp
6868
private static final int GOOGLE_API_CLIENT_ID = 1002;
6969
private static final int EMAIL_CREDENTIALS_REQUEST_CODE = 25100;
7070

71-
private static final String ARG_HIDE_LOGIN_BY_SITE_OPTION = "ARG_HIDE_LOGIN_BY_SITE_OPTION";
7271
private static final String ARG_LOGIN_SITE_URL = "ARG_LOGIN_SITE_URL";
7372

7473
public static final String TAG = "login_email_fragment_tag";
@@ -83,13 +82,11 @@ public class LoginEmailFragment extends LoginBaseFormFragment<LoginListener> imp
8382
protected WPLoginInputRow mEmailInput;
8483
protected boolean mHasDismissedEmailHints;
8584
protected boolean mIsDisplayingEmailHints;
86-
protected boolean mHideLoginWithSiteOption;
8785
protected String mLoginSiteUrl;
8886

89-
public static LoginEmailFragment newInstance(Boolean hideLoginWithSiteOption, String url) {
87+
public static LoginEmailFragment newInstance(String url) {
9088
LoginEmailFragment fragment = new LoginEmailFragment();
9189
Bundle args = new Bundle();
92-
args.putBoolean(ARG_HIDE_LOGIN_BY_SITE_OPTION, hideLoginWithSiteOption);
9390
args.putString(ARG_LOGIN_SITE_URL, url);
9491
fragment.setArguments(args);
9592
return fragment;
@@ -180,30 +177,32 @@ public void onClick(View view) {
180177
});
181178

182179
LinearLayout siteLoginButton = rootView.findViewById(R.id.login_site_button);
183-
if (mHideLoginWithSiteOption) {
184-
siteLoginButton.setVisibility(View.GONE);
185-
} else {
186-
siteLoginButton.setOnClickListener(new OnClickListener() {
187-
@Override
188-
public void onClick(View view) {
189-
if (mLoginListener != null) {
190-
if (mLoginListener.getLoginMode() == LoginMode.JETPACK_STATS) {
191-
mLoginListener.loginViaWpcomUsernameInstead();
192-
} else {
193-
mLoginListener.loginViaSiteAddress();
194-
}
180+
siteLoginButton.setOnClickListener(new OnClickListener() {
181+
@Override
182+
public void onClick(View view) {
183+
if (mLoginListener != null) {
184+
LoginMode loginMode = mLoginListener.getLoginMode();
185+
if (loginMode == LoginMode.JETPACK_STATS) {
186+
mLoginListener.loginViaWpcomUsernameInstead();
187+
} else if (loginMode == LoginMode.WOO_LOGIN_MODE) {
188+
mLoginListener.loginViaSiteCredentials(mLoginSiteUrl);
189+
} else {
190+
mLoginListener.loginViaSiteAddress();
195191
}
196192
}
197-
});
198-
}
193+
}
194+
});
199195

200196
ImageView siteLoginButtonIcon = rootView.findViewById(R.id.login_site_button_icon);
201197
TextView siteLoginButtonText = rootView.findViewById(R.id.login_site_button_text);
202198

203199
switch (mLoginListener.getLoginMode()) {
200+
case WOO_LOGIN_MODE:
201+
siteLoginButtonIcon.setImageResource(R.drawable.ic_domains_grey_24dp);
202+
siteLoginButtonText.setText(R.string.enter_site_credentials_instead);
203+
break;
204204
case FULL:
205205
case WPCOM_LOGIN_ONLY:
206-
case WOO_LOGIN_MODE:
207206
case SHARE_INTENT:
208207
siteLoginButtonIcon.setImageResource(R.drawable.ic_domains_grey_24dp);
209208
siteLoginButtonText.setText(R.string.enter_site_address_instead);
@@ -277,17 +276,31 @@ public void onCreate(Bundle savedInstanceState) {
277276

278277
Bundle args = getArguments();
279278
if (args != null) {
280-
mHideLoginWithSiteOption = args.getBoolean(ARG_HIDE_LOGIN_BY_SITE_OPTION, false);
281279
mLoginSiteUrl = args.getString(ARG_LOGIN_SITE_URL, "");
282280
}
281+
}
283282

283+
@Override
284+
public void onStart() {
285+
super.onStart();
284286
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
285287
.addConnectionCallbacks(LoginEmailFragment.this)
286288
.enableAutoManage(getActivity(), GOOGLE_API_CLIENT_ID, LoginEmailFragment.this)
287289
.addApi(Auth.CREDENTIALS_API)
288290
.build();
289291
}
290292

293+
@Override
294+
public void onStop() {
295+
super.onStop();
296+
if (mGoogleApiClient != null) {
297+
mGoogleApiClient.stopAutoManage(getActivity());
298+
if (mGoogleApiClient.isConnected()) {
299+
mGoogleApiClient.disconnect();
300+
}
301+
}
302+
}
303+
291304
@Override
292305
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
293306
super.onActivityCreated(savedInstanceState);
@@ -333,11 +346,6 @@ protected void next(String email) {
333346
public void onDetach() {
334347
super.onDetach();
335348
mLoginListener = null;
336-
337-
mGoogleApiClient.stopAutoManage(getActivity());
338-
if (mGoogleApiClient.isConnected()) {
339-
mGoogleApiClient.disconnect();
340-
}
341349
}
342350

343351
private String getCleanedEmail() {
@@ -424,7 +432,7 @@ public void onAvailabilityChecked(OnAvailabilityChecked event) {
424432
showEmailError(R.string.email_not_registered_wpcom);
425433
} else if (mLoginListener != null) {
426434
ActivityUtils.hideKeyboardForced(mEmailInput);
427-
mLoginListener.gotWpcomEmail(event.value);
435+
mLoginListener.gotWpcomEmail(event.value, false);
428436
}
429437
break;
430438
default:

WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginListener.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ interface SelfSignedSSLCallback {
1818
LoginMode getLoginMode();
1919

2020
// Login Email input callbacks
21-
void gotWpcomEmail(String email);
21+
void gotWpcomEmail(String email, boolean verifyEmail);
2222
void loginViaSiteAddress();
2323
void loginViaSocialAccount(String email, String idToken, String service, boolean isPasswordRequired);
2424
void loggedInViaSocialAccount(ArrayList<Integer> oldSiteIds, boolean doLoginUpdate);
2525
void loginViaWpcomUsernameInstead();
26+
void loginViaSiteCredentials(String inputSiteAddress);
2627
void helpEmailScreen(String email);
2728
void helpSocialEmailScreen(String email);
2829
void addGoogleLoginFragment();
@@ -59,6 +60,10 @@ void saveCredentialsInSmartLock(@Nullable String username, @Nullable String pass
5960
@NonNull String displayName, @Nullable Uri profilePicture);
6061
void loggedInViaUsernamePassword(ArrayList<Integer> oldSitesIds);
6162
void helpUsernamePassword(String url, String username, boolean isWpcom);
63+
void helpNoJetpackScreen(String siteAddress, String endpointAddress, String username,
64+
String password, String userAvatarUrl, Boolean checkJetpackAvailability);
65+
void helpHandleDiscoveryError(String siteAddress, String endpointAddress, String username,
66+
String password, String userAvatarUrl, int errorMessage);
6267

6368
// Login 2FA screen callbacks
6469
void help2FaScreen(String email);

WordPressLoginFlow/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
import android.content.DialogInterface;
66
import android.graphics.drawable.Drawable;
77
import android.os.Bundle;
8+
import android.text.Html;
89
import android.view.LayoutInflater;
910
import android.view.Menu;
1011
import android.view.MenuInflater;
1112
import android.view.MenuItem;
1213
import android.view.View;
1314
import android.view.ViewGroup;
15+
import android.view.ViewGroup.LayoutParams;
1416
import android.widget.Button;
1517
import android.widget.ImageView;
18+
import android.widget.TextView;
1619

1720
import androidx.annotation.Nullable;
1821
import androidx.appcompat.app.ActionBar;
@@ -56,6 +59,7 @@ public class LoginMagicLinkRequestFragment extends Fragment {
5659
private static final String ARG_MAGIC_LINK_SCHEME = "ARG_MAGIC_LINK_SCHEME";
5760
private static final String ARG_IS_JETPACK_CONNECT = "ARG_IS_JETPACK_CONNECT";
5861
private static final String ARG_JETPACK_CONNECT_SOURCE = "ARG_JETPACK_CONNECT_SOURCE";
62+
private static final String ARG_VERIFY_MAGIC_LINK_EMAIL = "ARG_VERIFY_MAGIC_LINK_EMAIL";
5963

6064
private static final String ERROR_KEY = "error";
6165

@@ -71,18 +75,21 @@ public class LoginMagicLinkRequestFragment extends Fragment {
7175

7276
private boolean mInProgress;
7377
private boolean mIsJetpackConnect;
78+
private boolean mVerifyMagicLinkEmail;
7479

7580
@Inject protected Dispatcher mDispatcher;
7681

7782
@Inject protected LoginAnalyticsListener mAnalyticsListener;
7883
public static LoginMagicLinkRequestFragment newInstance(String email, AuthEmailPayloadScheme scheme,
79-
boolean isJetpackConnect, String jetpackConnectSource) {
84+
boolean isJetpackConnect, String jetpackConnectSource,
85+
boolean verifyEmail) {
8086
LoginMagicLinkRequestFragment fragment = new LoginMagicLinkRequestFragment();
8187
Bundle args = new Bundle();
8288
args.putString(ARG_EMAIL_ADDRESS, email);
8389
args.putSerializable(ARG_MAGIC_LINK_SCHEME, scheme);
8490
args.putBoolean(ARG_IS_JETPACK_CONNECT, isJetpackConnect);
8591
args.putString(ARG_JETPACK_CONNECT_SOURCE, jetpackConnectSource);
92+
args.putBoolean(ARG_VERIFY_MAGIC_LINK_EMAIL, verifyEmail);
8693
fragment.setArguments(args);
8794
return fragment;
8895
}
@@ -107,6 +114,7 @@ public void onCreate(Bundle savedInstanceState) {
107114
mMagicLinkScheme = (AuthEmailPayloadScheme) getArguments().getSerializable(ARG_MAGIC_LINK_SCHEME);
108115
mIsJetpackConnect = getArguments().getBoolean(ARG_IS_JETPACK_CONNECT);
109116
mJetpackConnectSource = getArguments().getString(ARG_JETPACK_CONNECT_SOURCE);
117+
mVerifyMagicLinkEmail = getArguments().getBoolean(ARG_VERIFY_MAGIC_LINK_EMAIL);
110118
}
111119

112120
setHasOptionsMenu(true);
@@ -143,28 +151,49 @@ public void onClick(View v) {
143151

144152
mAvatarProgressBar = view.findViewById(R.id.avatar_progress);
145153
ImageView avatarView = view.findViewById(R.id.gravatar);
146-
Glide.with(this)
147-
.load(GravatarUtils.gravatarFromEmail(mEmail,
148-
getContext().getResources().getDimensionPixelSize(R.dimen.avatar_sz_login)))
149-
.apply(RequestOptions.circleCropTransform())
150-
.apply(RequestOptions.placeholderOf(R.drawable.ic_gridicons_user_circle_100dp))
151-
.apply(RequestOptions.errorOf(R.drawable.ic_gridicons_user_circle_100dp))
152-
.listener(new RequestListener<Drawable>() {
153-
@Override
154-
public boolean onLoadFailed(@Nullable GlideException e, Object o, Target<Drawable> target,
155-
boolean b) {
156-
mAvatarProgressBar.setVisibility(View.GONE);
157-
return false;
158-
}
159154

160-
@Override
161-
public boolean onResourceReady(Drawable drawable, Object o, Target<Drawable> target,
162-
DataSource dataSource, boolean b) {
163-
mAvatarProgressBar.setVisibility(View.GONE);
164-
return false;
165-
}
166-
})
167-
.into(avatarView);
155+
// Design changes added to the Woo Magic link sign-in
156+
if (mVerifyMagicLinkEmail) {
157+
View avatarContainerView = view.findViewById(R.id.avatar_container);
158+
159+
LayoutParams lp = avatarContainerView.getLayoutParams();
160+
lp.width = getContext().getResources().getDimensionPixelSize(R.dimen.magic_link_sent_illustration_sz);
161+
lp.height = getContext().getResources().getDimensionPixelSize(R.dimen.magic_link_sent_illustration_sz);
162+
avatarContainerView.setLayoutParams(lp);
163+
164+
mAvatarProgressBar.setVisibility(View.GONE);
165+
avatarView.setImageResource(R.drawable.login_email_alert);
166+
167+
TextView labelTextView = view.findViewById(R.id.label);
168+
labelTextView.setText(Html.fromHtml(String.format(getResources().getString(
169+
R.string.login_site_credentials_magic_link_label), mEmail)));
170+
171+
mRequestMagicLinkButton.setText(getString(R.string.send_verification_email));
172+
} else {
173+
Glide.with(this)
174+
.load(GravatarUtils.gravatarFromEmail(mEmail,
175+
getContext().getResources().getDimensionPixelSize(R.dimen.avatar_sz_login)))
176+
.apply(RequestOptions.circleCropTransform())
177+
.apply(RequestOptions.placeholderOf(R.drawable.ic_gridicons_user_circle_100dp))
178+
.apply(RequestOptions.errorOf(R.drawable.ic_gridicons_user_circle_100dp))
179+
.listener(new RequestListener<Drawable>() {
180+
@Override
181+
public boolean onLoadFailed(@Nullable GlideException e, Object o, Target<Drawable> target,
182+
boolean b) {
183+
mAvatarProgressBar.setVisibility(View.GONE);
184+
return false;
185+
}
186+
187+
@Override
188+
public boolean onResourceReady(Drawable drawable, Object o, Target<Drawable> target,
189+
DataSource dataSource, boolean b) {
190+
mAvatarProgressBar.setVisibility(View.GONE);
191+
return false;
192+
}
193+
})
194+
.into(avatarView);
195+
}
196+
168197
return view;
169198
}
170199

0 commit comments

Comments
 (0)