From f61a45c4463f9e75c7dab1264a5e9bae8bce3a03 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Mon, 25 Sep 2017 17:48:26 +0300 Subject: [PATCH 001/888] Set up login flow library --- libs/login/build.gradle | 25 +++++++++++++++++++++++++ libs/login/src/main/AndroidManifest.xml | 3 +++ 2 files changed, 28 insertions(+) create mode 100644 libs/login/build.gradle create mode 100644 libs/login/src/main/AndroidManifest.xml diff --git a/libs/login/build.gradle b/libs/login/build.gradle new file mode 100644 index 00000000000..ecfc758ef1b --- /dev/null +++ b/libs/login/build.gradle @@ -0,0 +1,25 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.3' + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 25 + buildToolsVersion "25.0.3" + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 25 + versionCode 1 + versionName "1.0" + + } +} + +dependencies {} diff --git a/libs/login/src/main/AndroidManifest.xml b/libs/login/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..66ba33cd212 --- /dev/null +++ b/libs/login/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + + From 9cc51d19d0b12338696370f1a74a1cf692a6716c Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Wed, 27 Sep 2017 17:06:35 +0300 Subject: [PATCH 002/888] Use login library in app --- libs/login/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index ecfc758ef1b..d1816519b20 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -10,6 +10,8 @@ buildscript { apply plugin: 'com.android.library' android { + publishNonDefault true + compileSdkVersion 25 buildToolsVersion "25.0.3" From 8c68b27a728360dc79eb012ff68e6549cf0ad0c9 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Wed, 27 Sep 2017 17:25:22 +0300 Subject: [PATCH 003/888] Move LoginMode to library --- .../wordpress/android/login/LoginMode.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/LoginMode.java diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java new file mode 100644 index 00000000000..525024c9cf9 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java @@ -0,0 +1,25 @@ +package org.wordpress.android.login; + +import android.content.Intent; + +public enum LoginMode { + FULL, + SELFHOSTED_ONLY, + JETPACK_STATS, + WPCOM_LOGIN_DEEPLINK, + WPCOM_REAUTHENTICATE; + + private static final String ARG_LOGIN_MODE = "ARG_LOGIN_MODE"; + + public static LoginMode fromIntent(Intent intent) { + if (intent.hasExtra(ARG_LOGIN_MODE)) { + return LoginMode.valueOf(intent.getStringExtra(ARG_LOGIN_MODE)); + } else { + return FULL; + } + } + + public void putInto(Intent intent) { + intent.putExtra(ARG_LOGIN_MODE, this.name()); + } +} From 79f78c7d53e7a025a9586894aa41141a8b80b1bc Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Wed, 27 Sep 2017 17:41:34 +0300 Subject: [PATCH 004/888] Move LoginListener to library --- libs/login/build.gradle | 4 +- .../android/login/LoginListener.java | 55 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/LoginListener.java diff --git a/libs/login/build.gradle b/libs/login/build.gradle index d1816519b20..7f00535af1b 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -24,4 +24,6 @@ android { } } -dependencies {} +dependencies { + compile 'com.android.support:support-annotations:25.3.1' +} diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java new file mode 100644 index 00000000000..df97d0e0ef1 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -0,0 +1,55 @@ +package org.wordpress.android.login; + +import android.net.Uri; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.util.ArrayList; + +public interface LoginListener { + LoginMode getLoginMode(); + + // Login Prologue callbacks + void showEmailLoginScreen(); + void doStartSignup(); + void loggedInViaSignup(ArrayList oldSitesIds); + void newUserCreatedButErrored(String email, String password); + + // Login Email input callbacks + void gotWpcomEmail(String email); + void loginViaSiteAddress(); + void loginViaWpcomUsernameInstead(); + void helpEmailScreen(String email); + + // Login Request Magic Link callbacks + void showMagicLinkSentScreen(String email); + void usePasswordInstead(String email); + void forgotPassword(String url); + void helpMagicLinkRequest(String email); + + // Login Magic Link Sent callbacks + void openEmailClient(); + void helpMagicLinkSent(String email); + + // Login email password callbacks + void needs2fa(String email, String password); + void loggedInViaPassword(ArrayList oldSitesIds); + void helpEmailPasswordScreen(String email); + + // Login Site Address input callbacks + void alreadyLoggedInWpcom(ArrayList oldSitesIds); + void gotWpcomSiteInfo(String siteAddress, String siteName, String siteIconUrl); + void gotXmlRpcEndpoint(String inputSiteAddress, String endpointAddress); + void helpSiteAddress(String url); + + // Login username password callbacks + void saveCredentials(@NonNull final String username, @NonNull final String password, + @NonNull final String displayName, @Nullable final Uri profilePicture); + void loggedInViaUsernamePassword(ArrayList oldSitesIds); + void helpUsernamePassword(String url, String username, boolean isWpcom); + + // Login 2FA screen callbacks + void help2FaScreen(String email); + + void setHelpContext(String faqId, String faqSection); +} From 84aa1df64f898f0388b8ab96e7a4002804045721 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Thu, 28 Sep 2017 09:21:38 +0300 Subject: [PATCH 005/888] Move login styles to library --- libs/login/build.gradle | 2 +- libs/login/src/main/res/values/colors.xml | 97 +++++++++++++++++++++++ libs/login/src/main/res/values/styles.xml | 58 ++++++++++++++ 3 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 libs/login/src/main/res/values/colors.xml create mode 100644 libs/login/src/main/res/values/styles.xml diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 7f00535af1b..d2461dd487c 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -25,5 +25,5 @@ android { } dependencies { - compile 'com.android.support:support-annotations:25.3.1' + compile 'com.android.support:appcompat-v7:25.3.1' } diff --git a/libs/login/src/main/res/values/colors.xml b/libs/login/src/main/res/values/colors.xml new file mode 100644 index 00000000000..d7897fb6249 --- /dev/null +++ b/libs/login/src/main/res/values/colors.xml @@ -0,0 +1,97 @@ + + + + + @color/blue_wordpress + @color/status_bar_tint + @color/orange_jazzy + @color/white + @color/blue_light + @color/grey_lighten_20 + + + #00000000 + @color/grey_lighten_30 + @color/grey_lighten_20 + #FFFFFF + #F1F1F1 + + #000000 + @color/grey_lighten_30 + + + + + + #0087be + #78dcfa + #00aadc + #005082 + + + #87a6bc + #f3f6f8 + #2e4453 + @color/grey_darken_10 + + + #e9eff3 + #c8d7e1 + #a8bece + #668eaa + #4f748e + #3d596d + + + #f0821e + #d54e21 + + + #f0b849 + #d94f4f + #4ab866 + + + #66000000 + #80000000 + #cc78dcfa + #802e4453 + #b32e4453 + #80888888 + #80a8bece + #80c8d7e1 + #80e9eff3 + #66ffffff + #99ffffff + #a6ffffff + + + + + + #fffafafa + #fff5f5f5 + #ffeeeeee + #ffe0e0e0 + #ffbdbdbd + #ff9e9e9e + #ff757575 + #ff616161 + #ff424242 + #ff212121 + + + + #006b98 + #ff517188 + + + @color/grey_light + diff --git a/libs/login/src/main/res/values/styles.xml b/libs/login/src/main/res/values/styles.xml new file mode 100644 index 00000000000..ff90df93928 --- /dev/null +++ b/libs/login/src/main/res/values/styles.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + From 3d2748331001f2943ebd6d15fc2d0b584643dead Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Thu, 28 Sep 2017 09:35:48 +0300 Subject: [PATCH 006/888] Move login-specific widgets to library --- libs/login/build.gradle | 1 + .../android/login/util/ViewUtils.java | 58 +++++ .../login/widgets/WPLoginInputRow.java | 238 ++++++++++++++++++ .../login/widgets/WPTextInputLayout.java | 47 ++++ .../main/res/drawable/ic_user_grey_24dp.xml | 13 + .../src/main/res/layout/login_input_row.xml | 36 +++ libs/login/src/main/res/values/attrs.xml | 16 ++ libs/login/src/main/res/values/dimens.xml | 25 ++ libs/login/src/main/res/values/strings.xml | 4 + 9 files changed, 438 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/util/ViewUtils.java create mode 100644 libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java create mode 100644 libs/login/src/main/java/org/wordpress/android/login/widgets/WPTextInputLayout.java create mode 100644 libs/login/src/main/res/drawable/ic_user_grey_24dp.xml create mode 100644 libs/login/src/main/res/layout/login_input_row.xml create mode 100644 libs/login/src/main/res/values/attrs.xml create mode 100644 libs/login/src/main/res/values/dimens.xml create mode 100644 libs/login/src/main/res/values/strings.xml diff --git a/libs/login/build.gradle b/libs/login/build.gradle index d2461dd487c..412b3538203 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -26,4 +26,5 @@ android { dependencies { compile 'com.android.support:appcompat-v7:25.3.1' + compile 'com.android.support:design:25.3.1' } diff --git a/libs/login/src/main/java/org/wordpress/android/login/util/ViewUtils.java b/libs/login/src/main/java/org/wordpress/android/login/util/ViewUtils.java new file mode 100644 index 00000000000..c640ff0082f --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/util/ViewUtils.java @@ -0,0 +1,58 @@ +package org.wordpress.android.login.util; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.support.annotation.AttrRes; +import android.support.annotation.StyleRes; +import android.support.v4.view.ViewCompat; +import android.view.View; + +import java.util.concurrent.atomic.AtomicInteger; + +// TODO Move to utils lib +public class ViewUtils { + /** + * Generate a value suitable for use in {@link View#setId(int)}. + * This value will not collide with ID values generated at build time by aapt for R.id. + * Uses the native implementation if API 17 or above, otherwise uses a copied implementation. + * + * @return a generated ID value + */ + public static int generateViewId() { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { + return View.generateViewId(); + } else { + return copiedGenerateViewId(); + } + } + + private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); + + /** + * Copied from {@link View#generateViewId()} + * Generate a value suitable for use in {@link View#setId(int)}. + * This value will not collide with ID values generated at build time by aapt for R.id. + * + * @return a generated ID value + */ + private static int copiedGenerateViewId() { + for (;;) { + final int result = sNextGeneratedId.get(); + // aapt-generated IDs have the high byte nonzero; clamp to the range under that. + int newValue = result + 1; + if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. + if (sNextGeneratedId.compareAndSet(result, newValue)) { + return result; + } + } + } + + public static void setButtonBackgroundColor(Context context, View button, @StyleRes int styleId, + @AttrRes int colorAttribute) { + TypedArray a = context.obtainStyledAttributes(styleId, new int[] { colorAttribute } ); + ColorStateList color = a.getColorStateList(0); + a.recycle(); + ViewCompat.setBackgroundTintList(button, color); + } +} diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java new file mode 100644 index 00000000000..ae3c0fcb144 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java @@ -0,0 +1,238 @@ +package org.wordpress.android.login.widgets; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.Nullable; +import android.support.design.widget.TextInputLayout; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import org.wordpress.android.login.R; +import org.wordpress.android.login.util.ViewUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Compound view composed of an icon and an EditText + */ +public class WPLoginInputRow extends RelativeLayout { + + public interface OnEditorCommitListener { + void OnEditorCommit(); + } + + private ImageView mIcon; + private TextInputLayout mTextInputLayout; + private EditText mEditText; + + private List mNewIds; + + public ImageView getIcon() { + return mIcon; + } + + public EditText getEditText() { + return mEditText; + } + + public WPLoginInputRow(Context context) { + super(context); + init(context, null); + } + + public WPLoginInputRow(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public WPLoginInputRow(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + inflate(context, R.layout.login_input_row, this); + + mIcon = (ImageView) findViewById(R.id.icon); + mTextInputLayout = (TextInputLayout) findViewById(R.id.input_layout); + mEditText = (EditText) findViewById(R.id.input); + + if (attrs != null) { + TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.wpLoginInputRow, 0, 0); + + try { + if (a.hasValue(R.styleable.wpLoginInputRow_wpIconDrawable)) { + mIcon.setImageResource(a.getResourceId(R.styleable.wpLoginInputRow_wpIconDrawable, 0)); + mIcon.setVisibility(View.VISIBLE); + } else { + mIcon.setVisibility(View.GONE); + } + + if (a.hasValue(R.styleable.wpLoginInputRow_android_hint)) { + mTextInputLayout.setHint(a.getString(R.styleable.wpLoginInputRow_android_hint)); + } + + if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleEnabled)) { + mTextInputLayout.setPasswordVisibilityToggleEnabled( + a.getBoolean(R.styleable.wpLoginInputRow_passwordToggleEnabled, false)); + + } + + if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleTint)) { + mTextInputLayout.setPasswordVisibilityToggleTintList( + a.getColorStateList(R.styleable.wpLoginInputRow_passwordToggleTint)); + } + + if (a.hasValue(R.styleable.wpLoginInputRow_android_inputType)) { + mEditText.setInputType(a.getInteger(R.styleable.wpLoginInputRow_android_inputType, 0)); + } + + if (a.hasValue(R.styleable.wpLoginInputRow_android_imeOptions)) { + mEditText.setImeOptions(a.getInteger(R.styleable.wpLoginInputRow_android_imeOptions, 0)); + } + } finally { + a.recycle(); + } + } + + mNewIds = Arrays.asList(ViewUtils.generateViewId(), ViewUtils.generateViewId(), ViewUtils.generateViewId()); + + reassignIds(); + } + + /** + * Assign new IDs to the Views so multiple instances of the compound View can exist in the same layout and + * auto-save of the Views state can be performed + */ + private void reassignIds() { + RelativeLayout.LayoutParams iconLayoutParams = (LayoutParams) mIcon.getLayoutParams(); + int[] rules = iconLayoutParams.getRules(); + for (int i = 0; i < rules.length; i++) { + if (rules[i] == mTextInputLayout.getId()) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { + rules[i] = mNewIds.get(1); + } else { + iconLayoutParams.addRule(i, mNewIds.get(1)); + } + } + } + mIcon.setLayoutParams(iconLayoutParams); + + RelativeLayout.LayoutParams editTextLayoutParams = (LayoutParams) mTextInputLayout.getLayoutParams(); + rules = editTextLayoutParams.getRules(); + for (int i = 0; i < rules.length; i++) { + if (rules[i] == mIcon.getId()) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { + rules[i] = mNewIds.get(0); + } else { + editTextLayoutParams.addRule(i, mNewIds.get(0)); + } + } + } + mTextInputLayout.setLayoutParams(editTextLayoutParams); + + mIcon.setId(mNewIds.get(0)); + mTextInputLayout.setId(mNewIds.get(1)); + mEditText.setId(mNewIds.get(2)); + } + + @Override + protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + return new SavedState(superState, mNewIds); + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + //begin boilerplate code so parent classes can restore state + if(!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + SavedState savedState = (SavedState) state; + super.onRestoreInstanceState(savedState.getSuperState()); + + mNewIds = savedState.mIds; + + reassignIds(); + } + + public void addTextChangedListener(TextWatcher watcher) { + mEditText.addTextChangedListener(watcher); + } + + public void setOnEditorCommitListener(final OnEditorCommitListener listener) { + mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE || + actionId == EditorInfo.IME_ACTION_NEXT || + (event != null + && event.getAction() == KeyEvent.ACTION_UP + && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + listener.OnEditorCommit(); + } + + // always consume the event so the focus stays in the EditText + return true; + } + }); + } + + public void setOnEditorActionListener(TextView.OnEditorActionListener l) { + mEditText.setOnEditorActionListener(l); + } + + public final void setText(CharSequence text) { + mEditText.setText(text); + } + + public void setError(@Nullable final CharSequence error) { + mTextInputLayout.setError(error); + } + + private static class SavedState extends BaseSavedState { + private List mIds; + + SavedState(Parcelable superState, List ids) { + super(superState); + mIds = ids; + } + + SavedState(Parcel in) { + super(in); + + mIds = new ArrayList<>(); + in.readList(mIds, List.class.getClassLoader()); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeList(mIds); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } +} diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPTextInputLayout.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPTextInputLayout.java new file mode 100644 index 00000000000..515613afd66 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPTextInputLayout.java @@ -0,0 +1,47 @@ +package org.wordpress.android.login.widgets; + +import android.content.Context; +import android.support.design.widget.TextInputLayout; +import android.util.AttributeSet; +import android.view.View; +import android.widget.EditText; + +import org.wordpress.android.login.R; + +/** + * Custom TextInputLayout to provide a usable getBaseline() and error view padding + */ +// TODO Move to utils lib +public class WPTextInputLayout extends TextInputLayout { + public WPTextInputLayout(Context context) { + super(context); + } + + public WPTextInputLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public WPTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public int getBaseline() { + EditText editText = getEditText(); + return editText != null ? editText.getBaseline() - editText.getPaddingBottom() + + getResources().getDimensionPixelSize(R.dimen.textinputlayout_baseline_correction) : 0; + } + + @Override + public void setErrorEnabled(boolean enabled) { + super.setErrorEnabled(enabled); + + // remove hardcoded side padding of the error view + if (enabled) { + View errorView = findViewById(android.support.design.R.id.textinput_error); + if (errorView != null && errorView.getParent() != null) { + ((View) errorView.getParent()).setPadding(0, errorView.getPaddingTop(), 0, errorView.getPaddingBottom()); + } + } + } +} diff --git a/libs/login/src/main/res/drawable/ic_user_grey_24dp.xml b/libs/login/src/main/res/drawable/ic_user_grey_24dp.xml new file mode 100644 index 00000000000..33b71620428 --- /dev/null +++ b/libs/login/src/main/res/drawable/ic_user_grey_24dp.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/libs/login/src/main/res/layout/login_input_row.xml b/libs/login/src/main/res/layout/login_input_row.xml new file mode 100644 index 00000000000..473c1a502dc --- /dev/null +++ b/libs/login/src/main/res/layout/login_input_row.xml @@ -0,0 +1,36 @@ + + + + + + + + + + diff --git a/libs/login/src/main/res/values/attrs.xml b/libs/login/src/main/res/values/attrs.xml new file mode 100644 index 00000000000..2479c4b3912 --- /dev/null +++ b/libs/login/src/main/res/values/attrs.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/libs/login/src/main/res/values/dimens.xml b/libs/login/src/main/res/values/dimens.xml new file mode 100644 index 00000000000..817dd043822 --- /dev/null +++ b/libs/login/src/main/res/values/dimens.xml @@ -0,0 +1,25 @@ + + + 0dp + 24dp + 1dp + 2dp + 4dp + 6dp + 8dp + 10dp + 12dp + 16dp + 24dp + 32dp + 48dp + + + 20dp + 92dp + 4dp + 2dp + 4.3dp + -8.6dp + 120dp + diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml new file mode 100644 index 00000000000..86fe32d0ba7 --- /dev/null +++ b/libs/login/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Email address + \ No newline at end of file From ea7fe5849eeb98e72ccf6df2573ff25bdbee9f54 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Fri, 29 Sep 2017 10:04:31 +0300 Subject: [PATCH 007/888] Add hooks for analytics tracking to LoginListener --- libs/login/build.gradle | 7 +++++++ .../java/org/wordpress/android/login/LoginListener.java | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 412b3538203..d9858a63188 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -9,6 +9,11 @@ buildscript { apply plugin: 'com.android.library' +repositories { + jcenter() + maven { url "https://dl.bintray.com/wordpress-mobile/maven" } // Drop once analytics lib is added to jcenter +} + android { publishNonDefault true @@ -25,6 +30,8 @@ android { } dependencies { + compile 'org.wordpress:analytics:1.3.0' + compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:design:25.3.1' } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index df97d0e0ef1..740a5945d0b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -4,7 +4,10 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import org.wordpress.android.analytics.AnalyticsTracker; + import java.util.ArrayList; +import java.util.Map; public interface LoginListener { LoginMode getLoginMode(); @@ -52,4 +55,8 @@ void saveCredentials(@NonNull final String username, @NonNull final String passw void help2FaScreen(String email); void setHelpContext(String faqId, String faqSection); + + void track(AnalyticsTracker.Stat stat); + void track(AnalyticsTracker.Stat stat, Map properties); + void track(AnalyticsTracker.Stat stat, String errorContext, String errorType, String errorDescription); } From 71c0a76e77244e2b467883f0466c8ddf869d146f Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Fri, 29 Sep 2017 10:25:24 +0300 Subject: [PATCH 008/888] Import FluxC in login library --- libs/login/build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index d9858a63188..d8c33500b43 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -11,6 +11,7 @@ apply plugin: 'com.android.library' repositories { jcenter() + maven { url "https://jitpack.io" } maven { url "https://dl.bintray.com/wordpress-mobile/maven" } // Drop once analytics lib is added to jcenter } @@ -34,4 +35,8 @@ dependencies { compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:design:25.3.1' + + compile ('com.github.wordpress-mobile.WordPress-FluxC-Android:fluxc:77e383f3e65ce1cee3f9ebad2eac522f29b4e3b8') { + exclude group: "com.android.volley"; + } } From f071a24d0676f125460f54db1091fe2ea022b9f2 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Tue, 10 Oct 2017 09:09:17 +0300 Subject: [PATCH 009/888] Move WordPress service dependencies to host activity --- .../main/java/org/wordpress/android/login/LoginListener.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 740a5945d0b..80d728e1f97 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -54,6 +54,10 @@ void saveCredentials(@NonNull final String username, @NonNull final String passw // Login 2FA screen callbacks void help2FaScreen(String email); + // General post-login callbacks + // TODO This should have a more generic name, it more or less means any kind of login was finished + void startPostLoginServices(); + void setHelpContext(String faqId, String faqSection); void track(AnalyticsTracker.Stat stat); From db6ac27ce88ed266df890ca6f3b016ee9bdabfe7 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Tue, 10 Oct 2017 17:37:17 +0300 Subject: [PATCH 010/888] Move LoginBaseFormFragment to library --- libs/login/build.gradle | 1 + .../android/login/LoginBaseFormFragment.java | 346 ++++++++++++++++++ .../res/drawable/ic_my_sites_white_32dp.xml | 13 + .../src/main/res/layout/login_form_screen.xml | 67 ++++ .../src/main/res/layout/toolbar_login.xml | 21 ++ libs/login/src/main/res/menu/menu_login.xml | 11 + libs/login/src/main/res/values/dimens.xml | 5 + libs/login/src/main/res/values/strings.xml | 6 + libs/login/src/main/res/values/styles.xml | 21 ++ 9 files changed, 491 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java create mode 100644 libs/login/src/main/res/drawable/ic_my_sites_white_32dp.xml create mode 100644 libs/login/src/main/res/layout/login_form_screen.xml create mode 100644 libs/login/src/main/res/layout/toolbar_login.xml create mode 100644 libs/login/src/main/res/menu/menu_login.xml diff --git a/libs/login/build.gradle b/libs/login/build.gradle index d8c33500b43..bd5d2f6a9ae 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -27,6 +27,7 @@ android { versionCode 1 versionName "1.0" + vectorDrawables.useSupportLibrary = true } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java new file mode 100644 index 00000000000..1465f82bd2d --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -0,0 +1,346 @@ +package org.wordpress.android.login; + +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.support.annotation.LayoutRes; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.support.v4.app.Fragment; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewStub; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.wordpress.android.fluxc.Dispatcher; +import org.wordpress.android.fluxc.action.AccountAction; +import org.wordpress.android.fluxc.generated.AccountActionBuilder; +import org.wordpress.android.fluxc.generated.SiteActionBuilder; +import org.wordpress.android.fluxc.store.AccountStore; +import org.wordpress.android.fluxc.store.AccountStore.OnAccountChanged; +import org.wordpress.android.fluxc.store.SiteStore; +import org.wordpress.android.fluxc.store.SiteStore.OnSiteChanged; +import org.wordpress.android.fluxc.store.SiteStore.SiteErrorType; +import org.wordpress.android.util.AppLog; +import org.wordpress.android.util.EditTextUtils; +import org.wordpress.android.util.ToastUtils; + +import javax.inject.Inject; + +public abstract class LoginBaseFormFragment extends Fragment implements TextWatcher { + + private static final String KEY_IN_PROGRESS = "KEY_IN_PROGRESS"; + private static final String KEY_LOGIN_FINISHED = "KEY_LOGIN_FINISHED"; + + private Button mPrimaryButton; + private Button mSecondaryButton; + private ProgressDialog mProgressDialog; + + protected LoginListenerType mLoginListener; + + private boolean mInProgress; + private boolean mLoginFinished; + + protected @Inject Dispatcher mDispatcher; + protected @Inject SiteStore mSiteStore; + protected @Inject AccountStore mAccountStore; + + protected abstract @LayoutRes int getContentLayout(); + protected abstract void setupLabel(TextView label); + protected abstract void setupContent(ViewGroup rootView); + protected abstract void setupBottomButtons(Button secondaryButton, Button primaryButton); + protected abstract @StringRes int getProgressBarText(); + + protected boolean listenForLogin() { + return true; + } + + protected EditText getEditTextToFocusOnStart() { + return null; + } + + protected boolean isInProgress() { + return mInProgress; + } + + protected Button getPrimaryButton() { + return mPrimaryButton; + } + + protected abstract void onHelp(); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setHasOptionsMenu(true); + } + + protected ViewGroup createMainView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.login_form_screen, container, false); + ViewStub form_container = ((ViewStub) rootView.findViewById(R.id.login_form_content_stub)); + form_container.setLayoutResource(getContentLayout()); + form_container.inflate(); + return rootView; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + ViewGroup rootView = createMainView(inflater, container, savedInstanceState); + + setupLabel((TextView) rootView.findViewById(R.id.label)); + + setupContent(rootView); + + mPrimaryButton = (Button) rootView.findViewById(R.id.primary_button); + mSecondaryButton = (Button) rootView.findViewById(R.id.secondary_button); + setupBottomButtons(mSecondaryButton, mPrimaryButton); + + return rootView; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar); + ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); + + ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayShowTitleEnabled(false); + actionBar.setDisplayHomeAsUpEnabled(true); + } + + if (savedInstanceState == null) { + EditTextUtils.showSoftInput(getEditTextToFocusOnStart()); + } + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + if (savedInstanceState != null) { + mInProgress = savedInstanceState.getBoolean(KEY_IN_PROGRESS); + mLoginFinished = savedInstanceState.getBoolean(KEY_LOGIN_FINISHED); + + if (mInProgress) { + startProgress(); + } + } + } + + @Override + @SuppressWarnings("unchecked") + public void onAttach(Context context) { + super.onAttach(context); + + // this will throw if parent activity doesn't implement the login listener interface + mLoginListener = (LoginListenerType) context; + } + + @Override + public void onDetach() { + super.onDetach(); + mLoginListener = null; + } + + @Override + public void onStart() { + super.onStart(); + + if (listenForLogin()) { + mDispatcher.register(this); + } + } + + @Override + public void onStop() { + super.onStop(); + + if (listenForLogin()) { + mDispatcher.unregister(this); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putBoolean(KEY_IN_PROGRESS, mInProgress); + outState.putBoolean(KEY_LOGIN_FINISHED, mLoginFinished); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.menu_login, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.help) { + onHelp(); + return true; + } + + return false; + } + + protected void startProgress() { + mPrimaryButton.setEnabled(false); + mSecondaryButton.setEnabled(false); + + mProgressDialog = + ProgressDialog.show(getActivity(), "", getActivity().getString(getProgressBarText()), true, true, + new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialogInterface) { + if (isInProgress()) { + endProgress(); + } + } + }); + mInProgress = true; + } + + @CallSuper + protected void endProgress() { + mInProgress = false; + + if (mProgressDialog != null) { + mProgressDialog.cancel(); + mProgressDialog = null; + } + + mPrimaryButton.setEnabled(true); + mSecondaryButton.setEnabled(true); + } + + protected void doFinishLogin() { + if (mLoginFinished) { + onLoginFinished(false); + return; + } + + if (mProgressDialog == null) { + startProgress(); + } + + mProgressDialog.setCancelable(false); + mDispatcher.dispatch(AccountActionBuilder.newFetchAccountAction()); + } + + protected void onLoginFinished() { + } + + private void onLoginFinished(boolean success) { + mLoginFinished = true; + + if (!success) { + endProgress(); + return; + } + + if (mLoginListener != null) { + onLoginFinished(); + } + } + + protected void saveCredentialsInSmartLock(LoginListener loginListener, String username, String password) { + // mUsername and mPassword are null when the user log in with a magic link + if (loginListener != null) { + loginListener.saveCredentials(username, password, mAccountStore.getAccount().getDisplayName(), + Uri.parse(mAccountStore.getAccount().getAvatarUrl())); + } + } + + /* + * auto-fill the username and password from BuildConfig/gradle.properties (developer feature, + * only enabled for DEBUG releases) + */ + protected void autoFillFromBuildConfig(String configValueName, TextView textView) { + if (!BuildConfig.DEBUG) return; + + // TODO: Restore pre-filled login for development +// String value = (String) WordPress.getBuildConfigValue(getActivity().getApplication(), configValueName); +// if (!TextUtils.isEmpty(value)) { +// textView.setText(value); +// AppLog.d(AppLog.T.NUX, "Auto-filled from build config: " + configValueName); +// } + } + + // OnChanged events + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onAccountChanged(OnAccountChanged event) { + if (!isAdded() || mLoginFinished) { + return; + } + + if (event.isError()) { + AppLog.e(AppLog.T.API, "onAccountChanged has error: " + event.error.type + " - " + event.error.message); + ToastUtils.showToast(getContext(), R.string.error_fetch_my_profile); + onLoginFinished(false); + return; + } + + if (event.causeOfChange == AccountAction.FETCH_ACCOUNT) { + // The user's account info has been fetched and stored - next, fetch the user's settings + mDispatcher.dispatch(AccountActionBuilder.newFetchSettingsAction()); + } else if (event.causeOfChange == AccountAction.FETCH_SETTINGS) { + // The user's account settings have also been fetched and stored - now we can fetch the user's sites + mDispatcher.dispatch(SiteActionBuilder.newFetchSitesAction()); + } + } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSiteChanged(OnSiteChanged event) { + if (!isAdded() || mLoginFinished) { + return; + } + + if (event.isError()) { + AppLog.e(AppLog.T.API, "onSiteChanged has error: " + event.error.type + " - " + event.error.toString()); + if (!isAdded() || event.error.type != SiteErrorType.DUPLICATE_SITE) { + onLoginFinished(false); + return; + } + + if (event.rowsAffected == 0) { + // If there is a duplicate site and not any site has been added, show an error and + // stop the sign in process + ToastUtils.showToast(getContext(), R.string.cannot_add_duplicate_site); + onLoginFinished(false); + return; + } else { + // If there is a duplicate site, notify the user something could be wrong, + // but continue the sign in process + ToastUtils.showToast(getContext(), R.string.duplicate_site_detected); + } + } + + if (mLoginListener instanceof LoginListener) { + ((LoginListener) mLoginListener).startPostLoginServices(); + } + + onLoginFinished(true); + } +} diff --git a/libs/login/src/main/res/drawable/ic_my_sites_white_32dp.xml b/libs/login/src/main/res/drawable/ic_my_sites_white_32dp.xml new file mode 100644 index 00000000000..50fe7359e50 --- /dev/null +++ b/libs/login/src/main/res/drawable/ic_my_sites_white_32dp.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/libs/login/src/main/res/layout/login_form_screen.xml b/libs/login/src/main/res/layout/login_form_screen.xml new file mode 100644 index 00000000000..6f7b5e8eb39 --- /dev/null +++ b/libs/login/src/main/res/layout/login_form_screen.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + diff --git a/libs/login/src/main/res/layout/toolbar_login.xml b/libs/login/src/main/res/layout/toolbar_login.xml new file mode 100644 index 00000000000..aaa93eb24b1 --- /dev/null +++ b/libs/login/src/main/res/layout/toolbar_login.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/libs/login/src/main/res/menu/menu_login.xml b/libs/login/src/main/res/menu/menu_login.xml new file mode 100644 index 00000000000..84886dd8221 --- /dev/null +++ b/libs/login/src/main/res/menu/menu_login.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/libs/login/src/main/res/values/dimens.xml b/libs/login/src/main/res/values/dimens.xml index 817dd043822..2f63fe9a553 100644 --- a/libs/login/src/main/res/values/dimens.xml +++ b/libs/login/src/main/res/values/dimens.xml @@ -1,5 +1,7 @@ + 72dp + 0dp 24dp 1dp @@ -14,6 +16,9 @@ 32dp 48dp + + 4dp + 20dp 92dp diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 86fe32d0ba7..3f1368c50e1 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -1,4 +1,10 @@ Email address + Next + Help + + This site already exists in the app, you can\'t add it. + A duplicate site has been detected. + Couldn\'t retrieve your profile \ No newline at end of file diff --git a/libs/login/src/main/res/values/styles.xml b/libs/login/src/main/res/values/styles.xml index ff90df93928..7d0a58bb3b2 100644 --- a/libs/login/src/main/res/values/styles.xml +++ b/libs/login/src/main/res/values/styles.xml @@ -1,5 +1,26 @@ + + + + + + + + + + + - - - - - - - + + + + From e482f64c20046ea93923d35ad173c5e36ceba6e4 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Tue, 30 Jan 2018 11:37:09 +1100 Subject: [PATCH 108/888] Use overridable color names in login flow styles --- .../layout/login_magic_link_sent_screen.xml | 2 +- libs/login/src/main/res/values/colors.xml | 17 ++++++++++ libs/login/src/main/res/values/styles.xml | 32 +++++++++---------- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml b/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml index 9e39da7d63c..ea945f7afec 100644 --- a/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml +++ b/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml @@ -47,7 +47,7 @@ android:layout_below="@+id/login_open_email_client" android:layout_marginTop="@dimen/margin_extra_extra_extra_large" android:layout_centerHorizontal="true" - android:textColor="@color/blue_wordpress" + android:textColor="@color/login_secondary_button_text_color" android:text="@string/enter_your_password_instead" /> diff --git a/libs/login/src/main/res/values/colors.xml b/libs/login/src/main/res/values/colors.xml index f4ba1b1df27..939a32e441f 100644 --- a/libs/login/src/main/res/values/colors.xml +++ b/libs/login/src/main/res/values/colors.xml @@ -93,5 +93,22 @@ #ff517188 + @color/blue_medium @color/grey_light + + @color/blue_medium + @color/white + @color/blue_wordpress + @color/blue_wordpress + @color/grey_dark + @color/grey + @color/grey + @color/blue_medium + @color/blue_medium + @color/grey_dark + @color/grey + @color/grey_darken_10 + @color/grey_dark + @color/grey_darken_10 + @color/grey_dark diff --git a/libs/login/src/main/res/values/styles.xml b/libs/login/src/main/res/values/styles.xml index 647cf6236af..f8a502e048e 100644 --- a/libs/login/src/main/res/values/styles.xml +++ b/libs/login/src/main/res/values/styles.xml @@ -2,7 +2,7 @@ From 3dac830d000252beda311b2f2ac9c18d3c6cbf68 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Tue, 30 Jan 2018 11:39:07 +1100 Subject: [PATCH 109/888] Make login toolbar styling overridable --- .../{ic_my_sites_white_32dp.xml => login_toolbar_icon.xml} | 0 libs/login/src/main/res/layout/toolbar_login.xml | 4 ++-- libs/login/src/main/res/values/colors.xml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) rename libs/login/src/main/res/drawable/{ic_my_sites_white_32dp.xml => login_toolbar_icon.xml} (100%) diff --git a/libs/login/src/main/res/drawable/ic_my_sites_white_32dp.xml b/libs/login/src/main/res/drawable/login_toolbar_icon.xml similarity index 100% rename from libs/login/src/main/res/drawable/ic_my_sites_white_32dp.xml rename to libs/login/src/main/res/drawable/login_toolbar_icon.xml diff --git a/libs/login/src/main/res/layout/toolbar_login.xml b/libs/login/src/main/res/layout/toolbar_login.xml index aaa93eb24b1..289d267dd79 100644 --- a/libs/login/src/main/res/layout/toolbar_login.xml +++ b/libs/login/src/main/res/layout/toolbar_login.xml @@ -6,7 +6,7 @@ android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" - android:background="@color/blue_wordpress" + android:background="@color/login_toolbar_color" android:elevation="@dimen/appbar_elevation" app:contentInsetLeft="@dimen/toolbar_content_offset" app:contentInsetStart="@dimen/toolbar_content_offset" @@ -17,5 +17,5 @@ android:layout_width="24dp" android:layout_height="24dp" android:layout_gravity="center" - app:srcCompat="@drawable/ic_my_sites_white_32dp"/> + app:srcCompat="@drawable/login_toolbar_icon"/> diff --git a/libs/login/src/main/res/values/colors.xml b/libs/login/src/main/res/values/colors.xml index 939a32e441f..c403db5a65f 100644 --- a/libs/login/src/main/res/values/colors.xml +++ b/libs/login/src/main/res/values/colors.xml @@ -96,6 +96,7 @@ @color/blue_medium @color/grey_light + @color/blue_wordpress @color/blue_medium @color/white @color/blue_wordpress From a16a93519b1c553dbe58721b94bd3cb07d1aca38 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Wed, 31 Jan 2018 13:52:13 +1100 Subject: [PATCH 110/888] Make login notification styling overridable --- .../wordpress/android/login/LoginNotification.java | 4 ++-- ...y_sites_24dp.png => login_notification_icon.png} | Bin ...y_sites_24dp.png => login_notification_icon.png} | Bin ...y_sites_24dp.png => login_notification_icon.png} | Bin libs/login/src/main/res/values/colors.xml | 2 ++ 5 files changed, 4 insertions(+), 2 deletions(-) rename libs/login/src/main/res/drawable-hdpi/{ic_my_sites_24dp.png => login_notification_icon.png} (100%) rename libs/login/src/main/res/drawable-xhdpi/{ic_my_sites_24dp.png => login_notification_icon.png} (100%) rename libs/login/src/main/res/drawable-xxhdpi/{ic_my_sites_24dp.png => login_notification_icon.png} (100%) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginNotification.java b/libs/login/src/main/java/org/wordpress/android/login/LoginNotification.java index fec1a1bfb0f..db0e1b244c6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginNotification.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginNotification.java @@ -32,8 +32,8 @@ private static NotificationCompat.Builder getNotificationBuilder(Context context .setStyle(bigTextStyle) .setContentTitle(context.getString(title)) .setContentText(context.getString(content)) - .setSmallIcon(R.drawable.ic_my_sites_24dp) - .setColor(context.getResources().getColor(R.color.blue_wordpress)) + .setSmallIcon(R.drawable.login_notification_icon) + .setColor(context.getResources().getColor(R.color.login_notification_accent_color)) .setAutoCancel(true); } diff --git a/libs/login/src/main/res/drawable-hdpi/ic_my_sites_24dp.png b/libs/login/src/main/res/drawable-hdpi/login_notification_icon.png similarity index 100% rename from libs/login/src/main/res/drawable-hdpi/ic_my_sites_24dp.png rename to libs/login/src/main/res/drawable-hdpi/login_notification_icon.png diff --git a/libs/login/src/main/res/drawable-xhdpi/ic_my_sites_24dp.png b/libs/login/src/main/res/drawable-xhdpi/login_notification_icon.png similarity index 100% rename from libs/login/src/main/res/drawable-xhdpi/ic_my_sites_24dp.png rename to libs/login/src/main/res/drawable-xhdpi/login_notification_icon.png diff --git a/libs/login/src/main/res/drawable-xxhdpi/ic_my_sites_24dp.png b/libs/login/src/main/res/drawable-xxhdpi/login_notification_icon.png similarity index 100% rename from libs/login/src/main/res/drawable-xxhdpi/ic_my_sites_24dp.png rename to libs/login/src/main/res/drawable-xxhdpi/login_notification_icon.png diff --git a/libs/login/src/main/res/values/colors.xml b/libs/login/src/main/res/values/colors.xml index c403db5a65f..ca4659edf27 100644 --- a/libs/login/src/main/res/values/colors.xml +++ b/libs/login/src/main/res/values/colors.xml @@ -112,4 +112,6 @@ @color/grey_dark @color/grey_darken_10 @color/grey_dark + + @color/blue_wordpress From 26a4201e2cbd3f38b0874dfe4ba30ccff2c99f69 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 13 Feb 2018 10:49:41 +0100 Subject: [PATCH 111/888] Fix ltr layouts with rtl locale on sdk 17 --- .../ic_arrow_left_white_24dp.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libs/login/src/main/res/{drawable-ldrtl => drawable-ldrtl-v18}/ic_arrow_left_white_24dp.xml (100%) diff --git a/libs/login/src/main/res/drawable-ldrtl/ic_arrow_left_white_24dp.xml b/libs/login/src/main/res/drawable-ldrtl-v18/ic_arrow_left_white_24dp.xml similarity index 100% rename from libs/login/src/main/res/drawable-ldrtl/ic_arrow_left_white_24dp.xml rename to libs/login/src/main/res/drawable-ldrtl-v18/ic_arrow_left_white_24dp.xml From c4b5448afe30eed8946a76fdb6e17e915e3b91c3 Mon Sep 17 00:00:00 2001 From: Klymentiy Haykov Date: Tue, 20 Feb 2018 15:09:11 +0900 Subject: [PATCH 112/888] Added lint check to modules. --- libs/login/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index f8b7f44eb7f..e1017491052 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -56,6 +56,8 @@ dependencies { compileOnly 'org.glassfish:javax.annotation:10.0-b28' implementation 'com.google.dagger:dagger-android-support:2.11' annotationProcessor 'com.google.dagger:dagger-android-processor:2.11' + + lintChecks project(path:':libs:lint:WordPressLint') } // Add properties named "wp.xxx" to our BuildConfig From f1ce0b8df4aa0eedc5cd70b431a830f64c9a2e9d Mon Sep 17 00:00:00 2001 From: theck13 Date: Tue, 20 Feb 2018 10:43:10 -0700 Subject: [PATCH 113/888] Update string resources for site address and username login buttons --- libs/login/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 62bbf552db0..d3d5942afe6 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -18,8 +18,8 @@ Log in to WordPress.com using an email address to manage all your WordPress sites. Next Open mail - Log in to your site by entering your site address instead. - Log in with username instead. + Log in by entering your site address. + Log in with your username. Enter the address of your WordPress site Almost there! Please enter the verification code from your Authenticator app. We sent a text message to the phone number ending in %s. Please enter the verification code in the SMS. From e6f512903ee79a16bf796e7b03c50f751a60889a Mon Sep 17 00:00:00 2001 From: theck13 Date: Tue, 20 Feb 2018 11:02:08 -0700 Subject: [PATCH 114/888] Add vector drawable resources for site address and username login buttons --- .../src/main/res/drawable/ic_domains_grey_24dp.xml | 13 +++++++++++++ .../main/res/drawable/ic_user_circle_grey_24dp.xml | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 libs/login/src/main/res/drawable/ic_domains_grey_24dp.xml create mode 100644 libs/login/src/main/res/drawable/ic_user_circle_grey_24dp.xml diff --git a/libs/login/src/main/res/drawable/ic_domains_grey_24dp.xml b/libs/login/src/main/res/drawable/ic_domains_grey_24dp.xml new file mode 100644 index 00000000000..2b7c41a4024 --- /dev/null +++ b/libs/login/src/main/res/drawable/ic_domains_grey_24dp.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/libs/login/src/main/res/drawable/ic_user_circle_grey_24dp.xml b/libs/login/src/main/res/drawable/ic_user_circle_grey_24dp.xml new file mode 100644 index 00000000000..76eb20d5fbe --- /dev/null +++ b/libs/login/src/main/res/drawable/ic_user_circle_grey_24dp.xml @@ -0,0 +1,13 @@ + + + + + + From cc5bfc323f697f0a0d22e037f2d0cf375fbb121f Mon Sep 17 00:00:00 2001 From: theck13 Date: Tue, 20 Feb 2018 11:15:15 -0700 Subject: [PATCH 115/888] Update email login layout with site address and username buttons --- .../main/res/layout/login_email_screen.xml | 95 +++++++++++++------ 1 file changed, 64 insertions(+), 31 deletions(-) diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index c5f63fbd411..48c85ffe06f 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -35,49 +35,82 @@ tools:ignore="UnusedAttribute" > + + + + android:layout_width="wrap_content" + android:orientation="horizontal" + android:paddingBottom="@dimen/margin_medium" + android:paddingEnd="@dimen/margin_medium" + android:paddingRight="@dimen/margin_medium" + android:paddingTop="@dimen/margin_medium" + tools:ignore="RtlSymmetry" > + + + + android:text="@string/login_google_button_suffix" + style="@style/LoginTheme.Button.Google" > - + - - + - - + + - + + From 366c5111f7d152f87e671880ceb88c47b5a879b9 Mon Sep 17 00:00:00 2001 From: theck13 Date: Tue, 20 Feb 2018 11:24:00 -0700 Subject: [PATCH 116/888] Update email login logic for site address and username buttons --- .../android/login/LoginEmailFragment.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index dd9b513d216..8bc7c881d33 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -17,6 +17,7 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -152,13 +153,11 @@ public void onClick(View view) { } } }); - } - @Override - protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { - secondaryButton.setOnClickListener(new OnClickListener() { + LinearLayout siteLoginButton = rootView.findViewById(R.id.login_site_button); + siteLoginButton.setOnClickListener(new OnClickListener() { @Override - public void onClick(View v) { + public void onClick(View view) { if (mLoginListener != null) { if (mLoginListener.getLoginMode() == LoginMode.JETPACK_STATS) { mLoginListener.loginViaWpcomUsernameInstead(); @@ -169,22 +168,29 @@ public void onClick(View v) { } }); + ImageView siteLoginButtonIcon = rootView.findViewById(R.id.login_site_button_icon); + TextView siteLoginButtonText = rootView.findViewById(R.id.login_site_button_text); + switch (mLoginListener.getLoginMode()) { case FULL: case SHARE_INTENT: - // all features enabled and with typical values - secondaryButton.setText(R.string.enter_site_address_instead); + siteLoginButtonIcon.setImageResource(R.drawable.ic_domains_grey_24dp); + siteLoginButtonText.setText(R.string.enter_site_address_instead); break; case JETPACK_STATS: - secondaryButton.setText(R.string.enter_username_instead); + siteLoginButtonIcon.setImageResource(R.drawable.ic_user_circle_grey_24dp); + siteLoginButtonText.setText(R.string.enter_username_instead); break; case WPCOM_LOGIN_DEEPLINK: - secondaryButton.setVisibility(View.GONE); - break; case WPCOM_REAUTHENTICATE: - secondaryButton.setVisibility(View.GONE); + siteLoginButton.setVisibility(View.GONE); break; } + } + + @Override + protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { + secondaryButton.setVisibility(View.GONE); primaryButton.setOnClickListener(new OnClickListener() { @SuppressWarnings("PrivateMemberAccessBetweenOuterAndInnerClass") From af8f6284ec6ead95ea1f328882680e37d8811057 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 21 Feb 2018 09:24:38 +0100 Subject: [PATCH 117/888] Add contentDescription to image views --- libs/login/src/main/res/layout/toolbar_login.xml | 1 + libs/login/src/main/res/values/strings.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/libs/login/src/main/res/layout/toolbar_login.xml b/libs/login/src/main/res/layout/toolbar_login.xml index aaa93eb24b1..768e844bee0 100644 --- a/libs/login/src/main/res/layout/toolbar_login.xml +++ b/libs/login/src/main/res/layout/toolbar_login.xml @@ -17,5 +17,6 @@ android:layout_width="24dp" android:layout_height="24dp" android:layout_gravity="center" + android:contentDescription="@string/toolbar_login_logo_desc" app:srcCompat="@drawable/ic_my_sites_white_32dp"/> diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 62bbf552db0..5fde70030c0 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -109,4 +109,5 @@ The site address can be found in the navigation bar of your web browser + WordPress logo From 54a17fdf6407ed5848e07e2aee057b9a9ffd00e9 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Thu, 22 Feb 2018 08:52:17 +0100 Subject: [PATCH 118/888] Fix TalkBack support --- libs/login/src/main/res/layout/login_input_row.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/res/layout/login_input_row.xml b/libs/login/src/main/res/layout/login_input_row.xml index aceaf3c1f9e..5fa6915e47e 100644 --- a/libs/login/src/main/res/layout/login_input_row.xml +++ b/libs/login/src/main/res/layout/login_input_row.xml @@ -30,6 +30,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="@dimen/textinputlayout_correction_margin_right" + android:importantForAccessibility="no" android:layout_marginEnd="@dimen/textinputlayout_correction_margin_right" android:hint="@string/email_address"/> From 9e5d10d31d16373295c3d8852dce84625e32f4d0 Mon Sep 17 00:00:00 2001 From: Klymentiy Haykov Date: Thu, 22 Feb 2018 20:06:12 +0900 Subject: [PATCH 119/888] Temporarily commented out dependencies. --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index e1017491052..3048610b603 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -57,7 +57,7 @@ dependencies { implementation 'com.google.dagger:dagger-android-support:2.11' annotationProcessor 'com.google.dagger:dagger-android-processor:2.11' - lintChecks project(path:':libs:lint:WordPressLint') +// lintChecks 'org.wordpress:lint:1.0.0' } // Add properties named "wp.xxx" to our BuildConfig From e56dfeec547d03c619bc5f505541eec2115225f1 Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Thu, 22 Feb 2018 14:08:05 +0200 Subject: [PATCH 120/888] Don't promote to foreground if null state --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 8495eb4fffb..ae185164d94 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -31,7 +31,7 @@ android { } dependencies { - implementation ('org.wordpress:utils:1.20.0-beta6') { + implementation ('org.wordpress:utils:1.20.0-beta7') { exclude group: "com.mcxiaoke.volley" } From 35e2d04dd536a89b438f76c6183eff17f7f3acc9 Mon Sep 17 00:00:00 2001 From: Klymentiy Haykov Date: Thu, 22 Feb 2018 21:30:05 +0900 Subject: [PATCH 121/888] Added bintray dependency to submodules. --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 3048610b603..17abe85c731 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -57,7 +57,7 @@ dependencies { implementation 'com.google.dagger:dagger-android-support:2.11' annotationProcessor 'com.google.dagger:dagger-android-processor:2.11' -// lintChecks 'org.wordpress:lint:1.0.0' + lintChecks 'org.wordpress:lint:1.0.0' } // Add properties named "wp.xxx" to our BuildConfig From 328de19bb06f54a9e531b780e54fdacc002bad15 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Thu, 22 Feb 2018 14:40:30 +0100 Subject: [PATCH 122/888] Fix TalkBack support in My site section --- .../org/wordpress/android/login/widgets/WPLoginInputRow.java | 4 +++- libs/login/src/main/res/layout/login_input_row.xml | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java index c7506c123aa..6980fd7166b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java @@ -88,7 +88,9 @@ private void init(Context context, AttributeSet attrs) { } if (a.hasValue(R.styleable.wpLoginInputRow_android_hint)) { - mTextInputLayout.setHint(a.getString(R.styleable.wpLoginInputRow_android_hint)); + String hint = a.getString(R.styleable.wpLoginInputRow_android_hint); + mTextInputLayout.setHint(hint); + mEditText.setContentDescription(hint); } if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleEnabled)) { diff --git a/libs/login/src/main/res/layout/login_input_row.xml b/libs/login/src/main/res/layout/login_input_row.xml index 5fa6915e47e..31a3877ebb2 100644 --- a/libs/login/src/main/res/layout/login_input_row.xml +++ b/libs/login/src/main/res/layout/login_input_row.xml @@ -21,7 +21,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toRightOf="@+id/icon" - android:layout_toEndOf="@+id/icon"> + android:layout_toEndOf="@+id/icon" + android:importantForAccessibility="no"> From 140821fe2b8e111a28313c6bb7a2d183bfa59dd8 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Fri, 23 Feb 2018 11:58:29 +0100 Subject: [PATCH 123/888] Fix TalkBack support in Login flow --- .../src/main/res/layout-land/login_magic_link_sent_screen.xml | 2 +- .../src/main/res/layout/login_alert_site_address_help.xml | 2 +- .../src/main/res/layout/login_magic_link_sent_screen.xml | 4 ++-- .../src/main/res/layout/login_username_password_screen.xml | 1 + libs/login/src/main/res/layout/toolbar_login.xml | 2 +- libs/login/src/main/res/values/strings.xml | 4 ---- 6 files changed, 6 insertions(+), 9 deletions(-) diff --git a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml index c32de3930b3..40c79c3122d 100644 --- a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml +++ b/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml @@ -20,7 +20,7 @@ android:layout_width="@dimen/magic_link_sent_illustration_sz" android:layout_height="@dimen/magic_link_sent_illustration_sz" android:scaleType="centerInside" - android:contentDescription="@string/login_magic_links_sent_description" + android:contentDescription="@null" app:srcCompat="@drawable/img_email_alert_120dp"/> + android:contentDescription="@null"/> diff --git a/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml b/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml index 9e39da7d63c..2e65225cd70 100644 --- a/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml +++ b/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml @@ -15,7 +15,7 @@ android:layout_below="@+id/toolbar" android:scaleType="centerInside" android:layout_marginTop="@dimen/margin_extra_extra_large" - android:contentDescription="@string/login_magic_links_sent_description" + android:contentDescription="@null" app:srcCompat="@drawable/img_email_alert_120dp"/> diff --git a/libs/login/src/main/res/layout/toolbar_login.xml b/libs/login/src/main/res/layout/toolbar_login.xml index 768e844bee0..9aaf3bd2e79 100644 --- a/libs/login/src/main/res/layout/toolbar_login.xml +++ b/libs/login/src/main/res/layout/toolbar_login.xml @@ -17,6 +17,6 @@ android:layout_width="24dp" android:layout_height="24dp" android:layout_gravity="center" - android:contentDescription="@string/toolbar_login_logo_desc" + android:contentDescription="@null" app:srcCompat="@drawable/ic_my_sites_white_32dp"/> diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index c229f3d2b18..96120e33d17 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -30,7 +30,6 @@ It looks like this password is incorrect. Please double check your information and try again. We\'ll email you a magic link that\'ll log you in instantly, no password needed. Hunt and peck no more! Your magic link is on its way! Check your email on this device and tap the link in the email you received from WordPress.com. - Magic link sent illustration Requesting log-in email Currently unavailable. Please enter your password Enter your WordPress.com password. @@ -110,7 +109,4 @@ This resource will be automatically overwritten in the host project with the real value from google-services.json. --> placeholder - - The site address can be found in the navigation bar of your web browser - WordPress logo From f2d60393e1a9da6385d5c88d4437b9604a38cb6c Mon Sep 17 00:00:00 2001 From: Klymentiy Haykov Date: Tue, 27 Feb 2018 17:52:01 +0900 Subject: [PATCH 124/888] Fixed various lint issues. --- libs/login/src/main/res/layout/login_email_screen.xml | 2 +- libs/login/src/main/res/values/strings.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index bebe7206cb8..ace6dd5b1ec 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -43,7 +43,7 @@ android:layout_marginBottom="@dimen/margin_medium" android:layout_marginTop="@dimen/margin_extra_large" android:layout_width="wrap_content" - android:text="Alternatively:" + android:text="@string/alternatively" style="@style/LoginTheme.TextLabel" > diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 04946eccab4..84509070c10 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -18,6 +18,7 @@ Log in to WordPress.com using an email address to manage all your WordPress sites. Next Open mail + Alternatively: Log in by entering your site address. Log in with your username. Enter the address of your WordPress site From 2adfa9feee01c55f4c91cf8aaf8d79a0d5c94be1 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 27 Feb 2018 10:47:18 +0100 Subject: [PATCH 125/888] Fix inputLoginRow in accessibility mode (TalkBack) --- .../org/wordpress/android/login/widgets/WPLoginInputRow.java | 4 +++- libs/login/src/main/res/layout/login_input_row.xml | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java index 6980fd7166b..a246d18c6fe 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java @@ -90,7 +90,9 @@ private void init(Context context, AttributeSet attrs) { if (a.hasValue(R.styleable.wpLoginInputRow_android_hint)) { String hint = a.getString(R.styleable.wpLoginInputRow_android_hint); mTextInputLayout.setHint(hint); - mEditText.setContentDescription(hint); + mEditText.setHint(hint); + // Makes the hint transparent, so the TalkBack can read it, when the field is prefilled + mEditText.setHintTextColor(getResources().getColor(android.R.color.transparent)); } if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleEnabled)) { diff --git a/libs/login/src/main/res/layout/login_input_row.xml b/libs/login/src/main/res/layout/login_input_row.xml index 31a3877ebb2..9f56240d4f5 100644 --- a/libs/login/src/main/res/layout/login_input_row.xml +++ b/libs/login/src/main/res/layout/login_input_row.xml @@ -1,6 +1,7 @@ @@ -32,6 +33,6 @@ android:layout_height="wrap_content" android:layout_marginRight="@dimen/textinputlayout_correction_margin_right" android:layout_marginEnd="@dimen/textinputlayout_correction_margin_right" - android:hint="@string/email_address"/> + tools:hint="@string/email_address"/> From 514fe5ff3f6e93dd32d88598b12cc9921ad4688b Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 27 Feb 2018 10:57:09 +0100 Subject: [PATCH 126/888] Fix accessibility issues in login and sign up screens --- libs/login/src/main/res/layout/login_email_password_screen.xml | 3 ++- .../src/main/res/layout/login_username_password_screen.xml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/res/layout/login_email_password_screen.xml b/libs/login/src/main/res/layout/login_email_password_screen.xml index 48cd9ece620..aaa66ffbdd5 100644 --- a/libs/login/src/main/res/layout/login_email_password_screen.xml +++ b/libs/login/src/main/res/layout/login_email_password_screen.xml @@ -40,7 +40,8 @@ android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginLeft="@dimen/margin_extra_large" - android:layout_marginStart="@dimen/margin_extra_large"> + android:layout_marginStart="@dimen/margin_extra_large" + android:focusable="true"> + android:orientation="vertical" + android:focusable="true"> Date: Tue, 27 Feb 2018 22:21:30 -0700 Subject: [PATCH 127/888] Order Details - Customer Info View - Action Icons and listeners, updated icon assets * Add the ability to click to dial customer phone * Add the ability to click to email customer * Add the ability to click to sms customer Ticket #137 --- libs/login/src/main/res/values/colors.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/res/values/colors.xml b/libs/login/src/main/res/values/colors.xml index f4ba1b1df27..e128d6036c3 100644 --- a/libs/login/src/main/res/values/colors.xml +++ b/libs/login/src/main/res/values/colors.xml @@ -37,7 +37,7 @@ #87a6bc #f3f6f8 - #2e4453 + #3c3c3c @color/grey_darken_10 From 5c32ebc9f2c473fa2a1506f3f2a92d0c2404e734 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 28 Feb 2018 12:32:50 +0100 Subject: [PATCH 128/888] Fix cut off text on the login with email screen --- libs/login/src/main/res/layout/login_email_screen.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index ace6dd5b1ec..61f7d839d1f 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -59,6 +59,7 @@ android:paddingEnd="@dimen/margin_medium" android:paddingRight="@dimen/margin_medium" android:paddingTop="@dimen/margin_medium" + android:gravity="center_vertical" tools:ignore="RtlSymmetry" > @@ -93,6 +94,7 @@ android:paddingEnd="@dimen/margin_medium" android:paddingRight="@dimen/margin_medium" android:paddingTop="@dimen/margin_medium" + android:gravity="center_vertical" tools:ignore="RtlSymmetry" > From d5d754f4e4518dddc47af4797fc885ad2274c3bf Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 2 Mar 2018 16:56:57 +0200 Subject: [PATCH 129/888] Fix copy/paste error --- .../wordpress/android/login/LoginUsernamePasswordFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index ffacc41d86e..c76e177adaf 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -252,7 +252,7 @@ public void onSaveInstanceState(Bundle outState) { outState.putBoolean(KEY_LOGIN_FINISHED, mLoginFinished); outState.putString(KEY_REQUESTED_USERNAME, mRequestedUsername); outState.putString(KEY_REQUESTED_PASSWORD, mRequestedPassword); - outState.putIntegerArrayList(KEY_REQUESTED_PASSWORD, mOldSitesIDs); + outState.putIntegerArrayList(KEY_OLD_SITES_IDS, mOldSitesIDs); } protected void next() { From f69200a8ae315e4742f6ffce2060a82fcb420541 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Sun, 4 Mar 2018 12:54:32 +0100 Subject: [PATCH 130/888] Fix login input row in accessibility mode --- libs/login/src/main/res/layout/login_input_row.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/res/layout/login_input_row.xml b/libs/login/src/main/res/layout/login_input_row.xml index 6cc4ab24425..ced90853adc 100644 --- a/libs/login/src/main/res/layout/login_input_row.xml +++ b/libs/login/src/main/res/layout/login_input_row.xml @@ -3,7 +3,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:accessibilityLiveRegion="assertive"> Date: Tue, 6 Mar 2018 07:59:14 -0500 Subject: [PATCH 131/888] When email isn't registered, hide the keyboard to ensure the link to login using the site address is visible --- .../java/org/wordpress/android/login/LoginEmailFragment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 8c4df75932a..92071885997 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -37,8 +37,10 @@ import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; +import org.wordpress.android.util.ActivityUtils; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; +import org.wordpress.android.util.DisplayUtils; import org.wordpress.android.util.EditTextUtils; import org.wordpress.android.util.NetworkUtils; @@ -346,6 +348,8 @@ public void onAvailabilityChecked(OnAvailabilityChecked event) { if (event.isError()) { // report the error but don't bail yet. AppLog.e(T.API, "OnAvailabilityChecked has error: " + event.error.type + " - " + event.error.message); + // hide the keyboard to ensure the link to login using the site address is visible + ActivityUtils.hideKeyboardForced(mEmailInput); showEmailError(R.string.email_not_registered_wpcom); return; } From 150f3b5f927a799d7c1b6c2cd50a38170b3ac532 Mon Sep 17 00:00:00 2001 From: Masked Pony Date: Tue, 6 Mar 2018 16:59:17 +0100 Subject: [PATCH 132/888] Revert some newlines after annotated return types --- .../android/login/LoginEmailPasswordFragment.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index b5b91bda967..1528a403650 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -103,7 +103,7 @@ public void onResume() { // connect to the Service. We'll receive updates via EventBus. mServiceEventConnection = new AutoForeground.ServiceEventConnection(getContext(), - LoginWpcomService.class, this); + LoginWpcomService.class, this); // install the change listener as late as possible so the UI can be setup (updated from the Service state) // before triggering the state cleanup happening in the change listener. @@ -124,8 +124,7 @@ protected boolean listenForLogin() { } @Override - protected @LayoutRes - int getContentLayout() { + protected @LayoutRes int getContentLayout() { return R.layout.login_email_password_screen; } @@ -214,7 +213,7 @@ protected void next() { mRequestedPassword = mPasswordInput.getEditText().getText().toString(); LoginWpcomService.loginWithEmailAndPassword(getContext(), mEmailAddress, mRequestedPassword, mIdToken, mService, - mIsSocialLogin); + mIsSocialLogin); mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); } From ee87ea1abfe1fbbace75db4571b4a7813e13fd36 Mon Sep 17 00:00:00 2001 From: Nick Bradbury Date: Tue, 6 Mar 2018 13:42:56 -0500 Subject: [PATCH 133/888] Removed unused import --- .../java/org/wordpress/android/login/LoginEmailFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 92071885997..dac6b051967 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -40,7 +40,6 @@ import org.wordpress.android.util.ActivityUtils; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; -import org.wordpress.android.util.DisplayUtils; import org.wordpress.android.util.EditTextUtils; import org.wordpress.android.util.NetworkUtils; From d39beaa08f340eefa6a56d9bddc00508172fc2e6 Mon Sep 17 00:00:00 2001 From: Nick Bradbury Date: Tue, 6 Mar 2018 13:51:10 -0500 Subject: [PATCH 134/888] Always use ActivityUtils.hideKeyboardForced --- .../org/wordpress/android/login/LoginEmailFragment.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index dac6b051967..b06c34615e9 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -140,7 +140,7 @@ public void onClick(View view) { @Override public void onClick(View view) { mAnalyticsListener.trackSocialButtonClick(); - EditTextUtils.hideSoftInput(mEmailInput.getEditText()); + ActivityUtils.hideKeyboardForced(mEmailInput.getEditText()); if (NetworkUtils.checkConnection(getActivity())) { if (isAdded()) { @@ -357,9 +357,10 @@ public void onAvailabilityChecked(OnAvailabilityChecked event) { case EMAIL: if (event.isAvailable) { // email address is available on wpcom, so apparently the user can't login with that one. + ActivityUtils.hideKeyboardForced(mEmailInput); showEmailError(R.string.email_not_registered_wpcom); } else if (mLoginListener != null) { - EditTextUtils.hideSoftInput(mEmailInput.getEditText()); + ActivityUtils.hideKeyboardForced(mEmailInput); mLoginListener.gotWpcomEmail(event.value); } break; @@ -430,7 +431,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { @Override public void run() { if (isAdded()) { - EditTextUtils.showSoftInput(mEmailInput.getEditText()); + ActivityUtils.showKeyboard(mEmailInput.getEditText()); } } }, getResources().getInteger(android.R.integer.config_mediumAnimTime)); From fdfad6edd6a6e9dc98cbb90fc95ae7acb2d8ca7e Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Mar 2018 11:29:47 +0100 Subject: [PATCH 135/888] Fix layout inflation without a parent lint issue --- .../org/wordpress/android/login/LoginHttpAuthDialogFragment.java | 1 + .../android/login/LoginSiteAddressHelpDialogFragment.java | 1 + 2 files changed, 2 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java index 24e767d2f8e..216a5f3a5d2 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java @@ -50,6 +50,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setTitle(R.string.http_authorization_required); + //noinspection InflateParams View httpAuth = getActivity().getLayoutInflater().inflate(R.layout.login_alert_http_auth, null); alert.setView(httpAuth); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java index b06b433293a..456dfc66ad8 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java @@ -42,6 +42,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setTitle(R.string.login_site_address_help_title); + //noinspection InflateParams alert.setView(getActivity().getLayoutInflater().inflate(R.layout.login_alert_site_address_help, null)); alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { From 6266a0d2dc6bdb62d9aa9a48f6916ecca005f422 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Mar 2018 12:29:36 +0100 Subject: [PATCH 136/888] Fix inconsistent layouts lint issue --- .../res/layout-land/login_magic_link_request_screen.xml | 6 ++++-- .../main/res/layout-land/login_magic_link_sent_screen.xml | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml index 791d43dc0f0..1e9b5488473 100644 --- a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml +++ b/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml @@ -1,6 +1,7 @@ + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools"> + android:clipToPadding="false" + tools:ignore="InconsistentLayout"> + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools"> + android:clipToPadding="false" + tools:ignore="InconsistentLayout"> Date: Wed, 7 Mar 2018 14:25:13 +0100 Subject: [PATCH 137/888] Fix style violations in the login subtree --- .../org/wordpress/android/login/widgets/WPLoginInputRow.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java index 8bb6fc79d5a..21251de5390 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java @@ -25,7 +25,6 @@ * Compound view composed of an icon and an EditText */ public class WPLoginInputRow extends RelativeLayout { - private static final String KEY_SUPER_STATE = "wplogin_input_row_super_state"; public interface OnEditorCommitListener { @@ -108,7 +107,6 @@ private void init(Context context, AttributeSet attrs) { a.recycle(); } } - } @@ -190,7 +188,6 @@ public void setError(@Nullable final CharSequence error) { } private static class SavedState extends BaseSavedState { - private Parcelable mEditTextState; SavedState(Parcelable superState, Parcelable editTextState) { From e35af5c7e01574dc8f8f5d31a7e02fb57542370b Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 7 Mar 2018 16:26:17 +0100 Subject: [PATCH 138/888] Fix checkstyle issues --- .../wordpress/android/login/LoginHttpAuthDialogFragment.java | 2 +- .../android/login/LoginSiteAddressHelpDialogFragment.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java index 216a5f3a5d2..89e6fc396d2 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java @@ -50,7 +50,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setTitle(R.string.http_authorization_required); - //noinspection InflateParams + // noinspection InflateParams View httpAuth = getActivity().getLayoutInflater().inflate(R.layout.login_alert_http_auth, null); alert.setView(httpAuth); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java index 456dfc66ad8..5d6306ff5f2 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java @@ -42,7 +42,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setTitle(R.string.login_site_address_help_title); - //noinspection InflateParams + // noinspection InflateParams alert.setView(getActivity().getLayoutInflater().inflate(R.layout.login_alert_site_address_help, null)); alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { From 0d35ec5238c3ec57ceaec13194f469e9dc238fc7 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Thu, 8 Mar 2018 10:20:03 +0100 Subject: [PATCH 139/888] Remove space in front of noinspection comments --- .../wordpress/android/login/LoginHttpAuthDialogFragment.java | 2 +- .../android/login/LoginSiteAddressHelpDialogFragment.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java index 89e6fc396d2..216a5f3a5d2 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java @@ -50,7 +50,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setTitle(R.string.http_authorization_required); - // noinspection InflateParams + //noinspection InflateParams View httpAuth = getActivity().getLayoutInflater().inflate(R.layout.login_alert_http_auth, null); alert.setView(httpAuth); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java index 5d6306ff5f2..456dfc66ad8 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java @@ -42,7 +42,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setTitle(R.string.login_site_address_help_title); - // noinspection InflateParams + //noinspection InflateParams alert.setView(getActivity().getLayoutInflater().inflate(R.layout.login_alert_site_address_help, null)); alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { From 29856051ee8505cfe3e76b0be58b0cc28d4f3d14 Mon Sep 17 00:00:00 2001 From: Masked Pony Date: Thu, 8 Mar 2018 10:30:52 +0100 Subject: [PATCH 140/888] Fix style violations for @Inject annotations --- .../wordpress/android/login/LoginBaseFormFragment.java | 8 ++++---- .../android/login/LoginMagicLinkRequestFragment.java | 4 ++-- .../android/login/LoginMagicLinkSentFragment.java | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index b510d3bcc6d..5985d6064bf 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -56,11 +56,11 @@ public abstract class LoginBaseFormFragment extends Fragment private boolean mInProgress; private boolean mLoginFinished; - protected @Inject Dispatcher mDispatcher; - protected @Inject SiteStore mSiteStore; - protected @Inject AccountStore mAccountStore; + @Inject protected Dispatcher mDispatcher; + @Inject protected SiteStore mSiteStore; + @Inject protected AccountStore mAccountStore; - protected @Inject LoginAnalyticsListener mAnalyticsListener; + @Inject protected LoginAnalyticsListener mAnalyticsListener; protected abstract @LayoutRes int getContentLayout(); protected abstract void setupLabel(@NonNull TextView label); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index b2908780cb9..9eb2144d78f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -62,9 +62,9 @@ public class LoginMagicLinkRequestFragment extends Fragment { private boolean mInProgress; - protected @Inject Dispatcher mDispatcher; + @Inject protected Dispatcher mDispatcher; - protected @Inject LoginAnalyticsListener mAnalyticsListener; + @Inject protected LoginAnalyticsListener mAnalyticsListener; public static LoginMagicLinkRequestFragment newInstance(String email) { LoginMagicLinkRequestFragment fragment = new LoginMagicLinkRequestFragment(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java index f36d03f4e8b..d1d7af40f54 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java @@ -27,7 +27,7 @@ public class LoginMagicLinkSentFragment extends Fragment { private String mEmail; - protected @Inject LoginAnalyticsListener mAnalyticsListener; + @Inject protected LoginAnalyticsListener mAnalyticsListener; public static LoginMagicLinkSentFragment newInstance(String email) { LoginMagicLinkSentFragment fragment = new LoginMagicLinkSentFragment(); From 116dc90044e7dacbd3d7a8027e27e655fa871b0b Mon Sep 17 00:00:00 2001 From: theck13 Date: Mon, 5 Mar 2018 18:04:57 -0700 Subject: [PATCH 141/888] Add Calypso style as theme to login HTTP authentication dialog --- .../wordpress/android/login/LoginHttpAuthDialogFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java index 24e767d2f8e..d9031e4e0f8 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java @@ -11,6 +11,7 @@ import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.TextWatcher; +import android.view.ContextThemeWrapper; import android.view.KeyEvent; import android.view.View; import android.widget.EditText; @@ -47,7 +48,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); + AlertDialog.Builder alert = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)); alert.setTitle(R.string.http_authorization_required); View httpAuth = getActivity().getLayoutInflater().inflate(R.layout.login_alert_http_auth, null); From a05c73de981dcc39386d86331a7cd96e27ec2f4f Mon Sep 17 00:00:00 2001 From: theck13 Date: Tue, 6 Mar 2018 10:01:11 -0700 Subject: [PATCH 142/888] Add login style as theme to site address help dialog --- .../android/login/LoginSiteAddressHelpDialogFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java index b06b433293a..484c9a8df3f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java @@ -7,6 +7,7 @@ import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; +import android.view.ContextThemeWrapper; import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.SiteStore; @@ -39,7 +40,7 @@ public void onAttach(Context context) { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); + AlertDialog.Builder alert = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)); alert.setTitle(R.string.login_site_address_help_title); alert.setView(getActivity().getLayoutInflater().inflate(R.layout.login_alert_site_address_help, null)); From 7531d089b92b6be2fb8695751484579217983ca6 Mon Sep 17 00:00:00 2001 From: Nick Bradbury Date: Thu, 8 Mar 2018 13:05:56 -0500 Subject: [PATCH 143/888] Changed onAvailabilityChecked to show generic error when response is an error --- .../java/org/wordpress/android/login/LoginEmailFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index b06c34615e9..222bf457997 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -349,7 +349,7 @@ public void onAvailabilityChecked(OnAvailabilityChecked event) { AppLog.e(T.API, "OnAvailabilityChecked has error: " + event.error.type + " - " + event.error.message); // hide the keyboard to ensure the link to login using the site address is visible ActivityUtils.hideKeyboardForced(mEmailInput); - showEmailError(R.string.email_not_registered_wpcom); + showEmailError(R.string.error_generic_network); return; } From 2c7bfcf939bab402ba79ddb3822a5313ef872914 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Fri, 9 Mar 2018 07:32:53 -0500 Subject: [PATCH 144/888] Use non-beta version of utils in login library --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 0b1a1fe8a53..612d1a42fe1 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -31,7 +31,7 @@ android { } dependencies { - implementation ('org.wordpress:utils:1.20.0-beta7') { + implementation ('org.wordpress:utils:1.20.0') { exclude group: "com.mcxiaoke.volley" } From 8fa354c2aaa56e0cb0075f91e0a5d0744f2da18f Mon Sep 17 00:00:00 2001 From: Nick Bradbury Date: Fri, 9 Mar 2018 13:08:56 -0500 Subject: [PATCH 145/888] Handle IsAvailableErrorType.INVALID and show a dialog for network errors --- .../org/wordpress/android/login/LoginEmailFragment.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 222bf457997..133709d4de2 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -33,6 +33,7 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.fluxc.generated.AccountActionBuilder; +import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.AccountStore.OnAvailabilityChecked; import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.widgets.WPLoginInputRow; @@ -349,7 +350,12 @@ public void onAvailabilityChecked(OnAvailabilityChecked event) { AppLog.e(T.API, "OnAvailabilityChecked has error: " + event.error.type + " - " + event.error.message); // hide the keyboard to ensure the link to login using the site address is visible ActivityUtils.hideKeyboardForced(mEmailInput); - showEmailError(R.string.error_generic_network); + // we validate the email prior to making the request, but just to be safe... + if (event.error.type == AccountStore.IsAvailableErrorType.INVALID) { + showEmailError(R.string.email_invalid); + } else { + showErrorDialog(getString(R.string.error_generic_network)); + } return; } From c03db1800832122e88dc562fce89e6fbb5437c9c Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 17:57:08 -0600 Subject: [PATCH 146/888] Move WordPress bottom sheet dialog to login library --- .../login/widgets/WPBottomSheetDialog.java | 32 +++++++++++++++++++ libs/login/src/main/res/values/dimens.xml | 6 ++++ 2 files changed, 38 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialog.java diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialog.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialog.java new file mode 100644 index 00000000000..24b2da03361 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialog.java @@ -0,0 +1,32 @@ +package org.wordpress.android.login.widgets; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomSheetDialog; +import android.view.WindowManager; + +import org.wordpress.android.login.R; +import org.wordpress.android.util.DisplayUtils; + +public class WPBottomSheetDialog extends BottomSheetDialog { + public WPBottomSheetDialog(@NonNull Context context) { + super(context); + } + + @Override + public void show() { + super.show(); + + // Limit width of bottom sheet on wide screens; non-zero width defined only for sw600dp. + int dp = (int) getContext().getResources().getDimension(R.dimen.bottom_sheet_dialog_width); + + if (dp > 0) { + int px = DisplayUtils.dpToPx(getContext(), dp); + WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); + layoutParams.copyFrom(getWindow().getAttributes()); + layoutParams.width = px; + layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; + getWindow().setAttributes(layoutParams); + } + } +} diff --git a/libs/login/src/main/res/values/dimens.xml b/libs/login/src/main/res/values/dimens.xml index d5d45007c33..daaf6ff0d2b 100644 --- a/libs/login/src/main/res/values/dimens.xml +++ b/libs/login/src/main/res/values/dimens.xml @@ -1,5 +1,7 @@ + + 72dp 0dp @@ -37,4 +39,8 @@ 120dp 24dp 9dp + + + 0dp + From f842485b60d092b1e40f2975de3118b8445108c0 Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 18:05:17 -0600 Subject: [PATCH 147/888] Move signup bottom sheet dialog to login library --- .../login/SignupBottomSheetDialog.java | 73 +++++++++++++++++++ .../signup_bottom_sheet_dialog.xml | 57 +++++++++++++++ .../res/layout/signup_bottom_sheet_dialog.xml | 45 ++++++++++++ libs/login/src/main/res/values/strings.xml | 3 + 4 files changed, 178 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/SignupBottomSheetDialog.java create mode 100644 libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml create mode 100644 libs/login/src/main/res/layout/signup_bottom_sheet_dialog.xml diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupBottomSheetDialog.java b/libs/login/src/main/java/org/wordpress/android/login/SignupBottomSheetDialog.java new file mode 100644 index 00000000000..03f6b579815 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupBottomSheetDialog.java @@ -0,0 +1,73 @@ +package org.wordpress.android.login; + +import android.content.Context; +import android.content.DialogInterface; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomSheetBehavior; +import android.text.Html; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; + +import org.wordpress.android.login.widgets.WPBottomSheetDialog; + +public class SignupBottomSheetDialog extends WPBottomSheetDialog { + public SignupBottomSheetDialog(@NonNull final Context context, + @NonNull final SignupSheetListener signupSheetListener) { + super(context); + //noinspection InflateParams + final View layout = LayoutInflater.from(context).inflate(R.layout.signup_bottom_sheet_dialog, null); + + Button termsOfServiceText = layout.findViewById(R.id.signup_tos); + termsOfServiceText.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + signupSheetListener.onSignupSheetTermsOfServiceClicked(); + } + }); + termsOfServiceText.setText(Html.fromHtml(String.format( + context.getResources().getString(R.string.signup_terms_of_service_text), "", ""))); + + Button signupWithEmailButton = layout.findViewById(R.id.signup_email); + signupWithEmailButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + signupSheetListener.onSignupSheetEmailClicked(); + } + }); + + Button signupWithGoogleButton = layout.findViewById(R.id.signup_google); + signupWithGoogleButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + signupSheetListener.onSignupSheetGoogleClicked(); + } + }); + + setOnCancelListener(new OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + signupSheetListener.onSignupSheetCanceled(); + } + }); + + setContentView(layout); + + // Set peek height to full height of view to avoid signup buttons being off screen when + // bottom sheet is shown with small screen height (e.g. landscape orientation). + final BottomSheetBehavior behavior = BottomSheetBehavior.from((View) layout.getParent()); + setOnShowListener(new OnShowListener() { + @Override + public void onShow(DialogInterface dialog) { + behavior.setPeekHeight(layout.getHeight()); + } + }); + } + + public interface SignupSheetListener { + void onSignupSheetCanceled(); + void onSignupSheetEmailClicked(); + void onSignupSheetGoogleClicked(); + void onSignupSheetTermsOfServiceClicked(); + } +} diff --git a/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml b/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml new file mode 100644 index 00000000000..a9775e52879 --- /dev/null +++ b/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + diff --git a/libs/login/src/main/res/layout/signup_bottom_sheet_dialog.xml b/libs/login/src/main/res/layout/signup_bottom_sheet_dialog.xml new file mode 100644 index 00000000000..3504ebcb233 --- /dev/null +++ b/libs/login/src/main/res/layout/signup_bottom_sheet_dialog.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 84509070c10..2e8f699ab76 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -65,6 +65,9 @@ There was some trouble connecting with the Google account. Google login could not be started. \nMaybe try a different account? + By signing up, you agree to our %1$sTerms of Service%2$s. + Sign Up with Email + Sign Up with Google Google took too long to respond. You may need to wait until you have a stronger internet connection. From 0e3de54e705ebf15838494e1a2fa1cba5aa4b60d Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 18:17:50 -0600 Subject: [PATCH 148/888] Add signup email tracking to login analytics listener interface --- .../java/org/wordpress/android/login/LoginAnalyticsListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java index ec84e686b11..7960a4978f6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java @@ -15,6 +15,7 @@ public interface LoginAnalyticsListener { void trackMagicLinkRequested(); void trackMagicLinkRequestFormViewed(); void trackPasswordFormViewed(); + void trackSignupEmailToLogin(); void trackSocialAccountsNeedConnecting(); void trackSocialButtonClick(); void trackSocialButtonFailure(); From a7fa66e840bf7b91a96aaa8ff4e1fbce6bc29087 Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 18:35:41 -0600 Subject: [PATCH 149/888] Add sign email fragment to login fragment module --- .../org/wordpress/android/login/di/LoginFragmentModule.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java b/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java index 9aa1eb0b415..5228ce3a683 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java +++ b/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java @@ -9,6 +9,7 @@ import org.wordpress.android.login.LoginSiteAddressFragment; import org.wordpress.android.login.LoginSiteAddressHelpDialogFragment; import org.wordpress.android.login.LoginUsernamePasswordFragment; +import org.wordpress.android.login.SignupEmailFragment; import dagger.Module; import dagger.android.ContributesAndroidInjector; @@ -41,4 +42,7 @@ public abstract class LoginFragmentModule { @ContributesAndroidInjector abstract LoginUsernamePasswordFragment loginUsernamePasswordFragment(); + + @ContributesAndroidInjector + abstract SignupEmailFragment signupEmailFragment(); } From af27318a1e7abd03992da0e786efa286dc0e517a Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 18:43:55 -0600 Subject: [PATCH 150/888] Move signup email fragment to login library --- .../android/login/SignupEmailFragment.java | 337 ++++++++++++++++++ .../main/res/layout/signup_email_fragment.xml | 38 ++ libs/login/src/main/res/values/strings.xml | 2 + 3 files changed, 377 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java create mode 100644 libs/login/src/main/res/layout/signup_email_fragment.xml diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java new file mode 100644 index 00000000000..a9f2535d26f --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java @@ -0,0 +1,337 @@ +package org.wordpress.android.login; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.IntentSender; +import android.os.Bundle; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.app.AlertDialog; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Patterns; +import android.view.ContextThemeWrapper; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.google.android.gms.auth.api.Auth; +import com.google.android.gms.auth.api.credentials.Credential; +import com.google.android.gms.auth.api.credentials.CredentialPickerConfig; +import com.google.android.gms.auth.api.credentials.HintRequest; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; +import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; + +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.wordpress.android.fluxc.generated.AccountActionBuilder; +import org.wordpress.android.fluxc.store.AccountStore.OnAvailabilityChecked; +import org.wordpress.android.login.widgets.WPLoginInputRow; +import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; +import org.wordpress.android.util.ActivityUtils; +import org.wordpress.android.util.AppLog; +import org.wordpress.android.util.AppLog.T; +import org.wordpress.android.util.EditTextUtils; +import org.wordpress.android.util.NetworkUtils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import dagger.android.support.AndroidSupportInjection; + +import static android.app.Activity.RESULT_OK; + +public class SignupEmailFragment extends LoginBaseFormFragment implements TextWatcher, + OnEditorCommitListener, ConnectionCallbacks, OnConnectionFailedListener { + private static final String KEY_HAS_DISMISSED_EMAIL_HINTS = "KEY_HAS_DISMISSED_EMAIL_HINTS"; + private static final String KEY_IS_DISPLAYING_EMAIL_HINTS = "KEY_IS_DISPLAYING_EMAIL_HINTS"; + private static final String KEY_REQUESTED_EMAIL = "KEY_REQUESTED_EMAIL"; + private static final String LOG_TAG = SignupEmailFragment.class.getSimpleName(); + private static final int EMAIL_CREDENTIALS_REQUEST_CODE = 25100; + private static final int GOOGLE_API_CLIENT_ID = 1001; + + public static final String TAG = "signup_email_fragment_tag"; + public static final int MAX_EMAIL_LENGTH = 100; + + private GoogleApiClient mGoogleApiClient; + private String mRequestedEmail; + + protected Button mPrimaryButton; + protected WPLoginInputRow mEmailInput; + protected boolean mHasDismissedEmailHints; + protected boolean mIsDisplayingEmailHints; + + @Override + protected @LayoutRes int getContentLayout() { + return R.layout.signup_email_fragment; + } + + @Override + protected @LayoutRes int getProgressBarText() { + return R.string.checking_email; + } + + @Override + protected void setupLabel(@NonNull TextView label) { + label.setText(R.string.signup_email_header); + } + + @Override + protected void setupContent(ViewGroup rootView) { + mEmailInput = rootView.findViewById(R.id.login_email_row); + + if (BuildConfig.DEBUG) { + mEmailInput.getEditText().setText(BuildConfig.DEBUG_WPCOM_LOGIN_EMAIL); + } + + mEmailInput.addTextChangedListener(this); + mEmailInput.setOnEditorCommitListener(this); + mEmailInput.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View view, boolean hasFocus) { + if (hasFocus && !mIsDisplayingEmailHints && !mHasDismissedEmailHints) { + mIsDisplayingEmailHints = true; + getEmailHints(); + } + } + }); + mEmailInput.getEditText().setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if (!mIsDisplayingEmailHints && !mHasDismissedEmailHints) { + mIsDisplayingEmailHints = true; + getEmailHints(); + } + } + }); + } + + @Override + protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { + secondaryButton.setVisibility(View.GONE); + + mPrimaryButton = primaryButton; + mPrimaryButton.setEnabled(false); + mPrimaryButton.setOnClickListener(new OnClickListener() { + @SuppressWarnings("PrivateMemberAccessBetweenOuterAndInnerClass") + public void onClick(View view) { + next(getCleanedEmail()); + } + }); + } + + @Override + protected void onHelp() { + if (mLoginListener != null) { + mLoginListener.helpSignupEmailScreen(EditTextUtils.getText(mEmailInput.getEditText())); + } + } + + @Override + public void onAttach(Context context) { + AndroidSupportInjection.inject(this); + super.onAttach(context); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) + .addConnectionCallbacks(SignupEmailFragment.this) + .enableAutoManage(getActivity(), GOOGLE_API_CLIENT_ID, SignupEmailFragment.this) + .addApi(Auth.CREDENTIALS_API) + .build(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + if (savedInstanceState != null) { + mRequestedEmail = savedInstanceState.getString(KEY_REQUESTED_EMAIL); + mIsDisplayingEmailHints = savedInstanceState.getBoolean(KEY_IS_DISPLAYING_EMAIL_HINTS); + mHasDismissedEmailHints = savedInstanceState.getBoolean(KEY_HAS_DISMISSED_EMAIL_HINTS); + } else { + mAnalyticsListener.trackEmailFormViewed(); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(KEY_REQUESTED_EMAIL, mRequestedEmail); + outState.putBoolean(KEY_IS_DISPLAYING_EMAIL_HINTS, mIsDisplayingEmailHints); + outState.putBoolean(KEY_HAS_DISMISSED_EMAIL_HINTS, mHasDismissedEmailHints); + } + + protected void next(String email) { + if (NetworkUtils.checkConnection(getActivity())) { + if (isValidEmail(email)) { + startProgress(); + mRequestedEmail = email; + mDispatcher.dispatch(AccountActionBuilder.newIsAvailableEmailAction(email)); + } else { + showErrorEmail(getString(R.string.email_invalid)); + } + } + } + + @Override + public void onDetach() { + super.onDetach(); + mLoginListener = null; + + if (mGoogleApiClient.isConnected()) { + mGoogleApiClient.stopAutoManage(getActivity()); + mGoogleApiClient.disconnect(); + } + } + + private String getCleanedEmail() { + return EditTextUtils.getText(mEmailInput.getEditText()).trim(); + } + + private boolean isValidEmail(String email) { + Pattern emailRegExPattern = Patterns.EMAIL_ADDRESS; + Matcher matcher = emailRegExPattern.matcher(email); + return matcher.find() && email.length() <= MAX_EMAIL_LENGTH; + } + + @Override + public void onEditorCommit() { + next(getCleanedEmail()); + } + + @Override + public void afterTextChanged(Editable s) { + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mEmailInput.setError(null); + mPrimaryButton.setEnabled(!s.toString().trim().isEmpty()); + } + + protected void showErrorDialog(String message) { + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) + .setMessage(message) + .setPositiveButton(R.string.login_error_button, null) + .create(); + dialog.show(); + } + + private void showErrorEmail(String message) { + mEmailInput.setError(message); + } + + @Override + protected void endProgress() { + super.endProgress(); + mRequestedEmail = null; + } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onAvailabilityChecked(OnAvailabilityChecked event) { + if (mRequestedEmail != null && mRequestedEmail.equalsIgnoreCase(event.value)) { + if (isInProgress()) { + endProgress(); + } + + if (event.isError()) { + AppLog.e(T.API, "OnAvailabilityChecked error: " + event.error.type + " - " + event.error.message); + showErrorDialog(getString(R.string.signup_email_error_generic)); + } else { + switch (event.type) { + case EMAIL: + ActivityUtils.hideKeyboard(getActivity()); + + if (mLoginListener != null) { + if (event.isAvailable) { + mLoginListener.showSignupMagicLink(event.value); + } else { + mAnalyticsListener.trackAnalyticsSignIn(mAccountStore, mSiteStore, true); + mLoginListener.showSignupToLoginMessage(); + mLoginListener.gotWpcomEmail(event.value); + // Kill connections with FluxC and this fragment since the flow is changing to login. + mDispatcher.unregister(this); + getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit(); + } + } + + break; + default: + AppLog.e(T.API, "OnAvailabilityChecked unhandled event: " + event.error.type); + break; + } + } + } + } + + @Override + public void onConnected(Bundle bundle) { + AppLog.d(T.NUX, LOG_TAG + ": Google API client connected"); + } + + @Override + public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { + AppLog.d(T.NUX, LOG_TAG + ": Google API connection result: " + connectionResult); + } + + @Override + public void onConnectionSuspended(int i) { + AppLog.d(T.NUX, LOG_TAG + ": Google API client connection suspended"); + } + + public void getEmailHints() { + HintRequest hintRequest = new HintRequest.Builder() + .setHintPickerConfig(new CredentialPickerConfig.Builder() + .setShowCancelButton(true) + .build()) + .setEmailAddressIdentifierSupported(true) + .build(); + + PendingIntent intent = Auth.CredentialsApi.getHintPickerIntent(mGoogleApiClient, hintRequest); + + try { + 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); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == EMAIL_CREDENTIALS_REQUEST_CODE) { + if (resultCode == RESULT_OK) { + Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY); + mEmailInput.getEditText().setText(credential.getId()); + next(getCleanedEmail()); + } else { + mHasDismissedEmailHints = true; + mEmailInput.getEditText().postDelayed(new Runnable() { + @Override + public void run() { + if (isAdded()) { + EditTextUtils.showSoftInput(mEmailInput.getEditText()); + } + } + }, getResources().getInteger(android.R.integer.config_mediumAnimTime)); + } + + mIsDisplayingEmailHints = false; + } + } +} diff --git a/libs/login/src/main/res/layout/signup_email_fragment.xml b/libs/login/src/main/res/layout/signup_email_fragment.xml new file mode 100644 index 00000000000..6a5d3110628 --- /dev/null +++ b/libs/login/src/main/res/layout/signup_email_fragment.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 2e8f699ab76..f84d5ea572f 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -65,6 +65,8 @@ There was some trouble connecting with the Google account. Google login could not be started. \nMaybe try a different account? + There was some trouble checking the email address. + To create your new WordPress.com account, please enter your email address. By signing up, you agree to our %1$sTerms of Service%2$s. Sign Up with Email Sign Up with Google From eb576ca01fd7ea742c2fad5f3e86ff590af0b489 Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 18:45:50 -0600 Subject: [PATCH 151/888] Update deprecated show keyboard method in signup email fragment --- .../java/org/wordpress/android/login/SignupEmailFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java index a9f2535d26f..5a6485c3acb 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java @@ -325,7 +325,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { @Override public void run() { if (isAdded()) { - EditTextUtils.showSoftInput(mEmailInput.getEditText()); + ActivityUtils.showKeyboard(mEmailInput.getEditText()); } } }, getResources().getInteger(android.R.integer.config_mediumAnimTime)); From a00a0320df7367bcb36f09793635e93cd84bdb32 Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 20:55:53 -0600 Subject: [PATCH 152/888] Add signup Google tracking to login analytics listener interface --- .../org/wordpress/android/login/LoginAnalyticsListener.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java index 7960a4978f6..793749a0de7 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java @@ -16,6 +16,10 @@ public interface LoginAnalyticsListener { void trackMagicLinkRequestFormViewed(); void trackPasswordFormViewed(); void trackSignupEmailToLogin(); + void trackSignupSocial2faNeeded(); + void trackSignupSocialAccountsNeedConnecting(); + void trackSignupSocialButtonFailure(); + void trackSignupSocialToLogin(); void trackSocialAccountsNeedConnecting(); void trackSocialButtonClick(); void trackSocialButtonFailure(); From b04a5a4f6094797fce5dee1da468380e6fcdc576 Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 20:56:31 -0600 Subject: [PATCH 153/888] Add sign email fragment to login fragment module --- .../org/wordpress/android/login/di/LoginFragmentModule.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java b/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java index 5228ce3a683..0c2c922a388 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java +++ b/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java @@ -10,6 +10,7 @@ import org.wordpress.android.login.LoginSiteAddressHelpDialogFragment; import org.wordpress.android.login.LoginUsernamePasswordFragment; import org.wordpress.android.login.SignupEmailFragment; +import org.wordpress.android.login.SignupGoogleFragment; import dagger.Module; import dagger.android.ContributesAndroidInjector; @@ -45,4 +46,7 @@ public abstract class LoginFragmentModule { @ContributesAndroidInjector abstract SignupEmailFragment signupEmailFragment(); + + @ContributesAndroidInjector + abstract SignupGoogleFragment signupGoogleFragment(); } From 69fea4925e682eef0278b6c0024f7296bcdd67db Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 20:56:55 -0600 Subject: [PATCH 154/888] Move signup Google fragment to login library --- .../android/login/SignupGoogleFragment.java | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java new file mode 100644 index 00000000000..5175434dd3e --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java @@ -0,0 +1,200 @@ +package org.wordpress.android.login; + +import android.content.Intent; +import android.os.Bundle; + +import com.google.android.gms.auth.api.Auth; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.auth.api.signin.GoogleSignInResult; +import com.google.android.gms.auth.api.signin.GoogleSignInStatusCodes; + +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.wordpress.android.fluxc.generated.AccountActionBuilder; +import org.wordpress.android.fluxc.store.AccountStore; +import org.wordpress.android.fluxc.store.AccountStore.PushSocialPayload; +import org.wordpress.android.login.util.SiteUtils; +import org.wordpress.android.util.AppLog; +import org.wordpress.android.util.AppLog.T; + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import dagger.android.support.AndroidSupportInjection; + +import static android.app.Activity.RESULT_CANCELED; +import static android.app.Activity.RESULT_OK; + +public class SignupGoogleFragment extends GoogleFragment { + private ArrayList mOldSitesIds; + + private static final int REQUEST_SIGNUP = 1002; + + public static final String TAG = "signup_google_fragment_tag"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + AndroidSupportInjection.inject(this); + } + + @Override + public void onActivityResult(int request, int result, Intent data) { + super.onActivityResult(request, result, data); + + switch (request) { + case REQUEST_SIGNUP: + if (result == RESULT_OK) { + GoogleSignInResult signInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data); + + if (signInResult.isSuccess()) { + try { + GoogleSignInAccount account = signInResult.getSignInAccount(); + + if (account != null) { + mDisplayName = account.getDisplayName() != null ? account.getDisplayName() : ""; + mGoogleEmail = account.getEmail() != null ? account.getEmail() : ""; + mIdToken = account.getIdToken() != null ? account.getIdToken() : ""; + mPhotoUrl = removeScaleFromGooglePhotoUrl( + account.getPhotoUrl() != null ? account.getPhotoUrl().toString() : ""); + } + + PushSocialPayload payload = new PushSocialPayload(mIdToken, SERVICE_TYPE_GOOGLE); + mDispatcher.dispatch(AccountActionBuilder.newPushSocialSignupAction(payload)); + mOldSitesIds = SiteUtils.getCurrentSiteIds(mSiteStore, false); + } catch (NullPointerException exception) { + disconnectGoogleClient(); + AppLog.e(T.NUX, "Cannot get ID token from Google signup account.", exception); + showErrorDialog(getString(R.string.login_error_generic)); + } + } else { + mAnalyticsListener.trackSignupSocialButtonFailure(); + switch (signInResult.getStatus().getStatusCode()) { + // Internal error. + case GoogleSignInStatusCodes.INTERNAL_ERROR: + AppLog.e(T.NUX, "Google Signup Failed: internal error."); + showErrorDialog(getString(R.string.login_error_generic)); + break; + // Attempted to connect with an invalid account name specified. + case GoogleSignInStatusCodes.INVALID_ACCOUNT: + AppLog.e(T.NUX, "Google Signup Failed: invalid account name."); + showErrorDialog(getString(R.string.login_error_generic) + + getString(R.string.login_error_suffix)); + break; + // Network error. + case GoogleSignInStatusCodes.NETWORK_ERROR: + AppLog.e(T.NUX, "Google Signup Failed: network error."); + showErrorDialog(getString(R.string.error_generic_network)); + break; + // Cancelled by the user. + case GoogleSignInStatusCodes.SIGN_IN_CANCELLED: + AppLog.e(T.NUX, "Google Signup Failed: cancelled by user."); + break; + // Attempt didn't succeed with the current account. + case GoogleSignInStatusCodes.SIGN_IN_FAILED: + AppLog.e(T.NUX, "Google Signup Failed: current account failed."); + showErrorDialog(getString(R.string.login_error_generic)); + break; + // Attempted to connect, but the user is not signed in. + case GoogleSignInStatusCodes.SIGN_IN_REQUIRED: + AppLog.e(T.NUX, "Google Signup Failed: user is not signed in."); + showErrorDialog(getString(R.string.login_error_generic)); + break; + // Timeout error. + case GoogleSignInStatusCodes.TIMEOUT: + AppLog.e(T.NUX, "Google Signup Failed: timeout error."); + showErrorDialog(getString(R.string.google_error_timeout)); + break; + // Unknown error. + default: + AppLog.e(T.NUX, "Google Signup Failed: unknown error."); + showErrorDialog(getString(R.string.login_error_generic)); + break; + } + } + } else if (result == RESULT_CANCELED) { + mAnalyticsListener.trackSignupSocialButtonFailure(); + AppLog.e(T.NUX, "Google Signup Failed: result was CANCELED."); + } else { + mAnalyticsListener.trackSignupSocialButtonFailure(); + AppLog.e(T.NUX, "Google Signup Failed: result was not OK or CANCELED."); + showErrorDialog(getString(R.string.login_error_generic)); + } + + break; + } + } + + @Override + protected void showAccountDialog() { + Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); + startActivityForResult(signInIntent, REQUEST_SIGNUP); + } + + // Remove scale from photo URL path string. Current URL matches /s96-c, which returns a 96 x 96 + // pixel image. Removing /s96-c from the string returns a 512 x 512 pixel image. Using regular + // expressions may help if the photo URL scale value in the returned path changes. + private String removeScaleFromGooglePhotoUrl(String photoUrl) { + Pattern pattern = Pattern.compile("(/s[0-9]+-c)"); + Matcher matcher = pattern.matcher(photoUrl); + return matcher.find() ? photoUrl.replace(matcher.group(1), "") : photoUrl; + } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onAuthenticationChanged(AccountStore.OnAuthenticationChanged event) { + if (event.isError()) { + AppLog.e(T.API, + "SignupGoogleFragment.onAuthenticationChanged: " + event.error.type + " - " + event.error.message); + // Continue with signup since account was created. + } else if (event.createdAccount) { + mGoogleListener.onGoogleSignupFinished(mDisplayName, mGoogleEmail, mPhotoUrl, event.userName); + // Continue with login since existing account was selected. + } else { + mAnalyticsListener.trackSignupSocialToLogin(); + mLoginListener.loggedInViaSocialAccount(mOldSitesIds, true); + } + } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSocialChanged(AccountStore.OnSocialChanged event) { + if (event.isError()) { + AppLog.e(T.API, "SignupGoogleFragment.onSocialChanged: " + event.error.type + " - " + event.error.message); + + switch (event.error.type) { + // WordPress account exists with input email address, and two-factor authentication is required. + case TWO_STEP_ENABLED: + mAnalyticsListener.trackSignupSocial2faNeeded(); + mAnalyticsListener.trackSignupSocialToLogin(); + mLoginListener.showSignupToLoginMessage(); + // Dispatch social login action to retrieve data required for two-factor authentication. + PushSocialPayload payload = new PushSocialPayload(mIdToken, SERVICE_TYPE_GOOGLE); + mDispatcher.dispatch(AccountActionBuilder.newPushSocialLoginAction(payload)); + break; + // WordPress account exists with input email address, but not connected. + case USER_EXISTS: + mAnalyticsListener.trackSignupSocialAccountsNeedConnecting(); + mAnalyticsListener.trackSignupSocialToLogin(); + mLoginListener.showSignupToLoginMessage(); + mLoginListener.loginViaSocialAccount(mGoogleEmail, mIdToken, SERVICE_TYPE_GOOGLE, true); + // Kill connections with FluxC and this fragment since the flow is changing to login. + mDispatcher.unregister(this); + getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit(); + break; + default: + showErrorDialog(getString(R.string.login_error_generic)); + break; + } + // Response does not return error when two-factor authentication is required. + } else if (event.requiresTwoStepAuth) { + mAnalyticsListener.trackSignupSocialToLogin(); + mLoginListener.needs2faSocial(mGoogleEmail, event.userId, event.nonceAuthenticator, event.nonceBackup, + event.nonceSms); + // Kill connections with FluxC and this fragment since the flow is changing to login. + mDispatcher.unregister(this); + getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit(); + } + } +} From 5902669964f3c6ce79c85bbbadd86c51e2884fcc Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 21:09:59 -0600 Subject: [PATCH 155/888] Add signup magic link tracking to login analytics listener interface --- .../org/wordpress/android/login/LoginAnalyticsListener.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java index 793749a0de7..b58c1fd2863 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java @@ -16,6 +16,8 @@ public interface LoginAnalyticsListener { void trackMagicLinkRequestFormViewed(); void trackPasswordFormViewed(); void trackSignupEmailToLogin(); + void trackSignupMagicLinkFailed(); + void trackSignupMagicLinkSucceeded(); void trackSignupSocial2faNeeded(); void trackSignupSocialAccountsNeedConnecting(); void trackSignupSocialButtonFailure(); From d451a438c48034b5c8825f920656f0c44c56b45d Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 21:10:30 -0600 Subject: [PATCH 156/888] Add sign magic link fragment to login fragment module --- .../org/wordpress/android/login/di/LoginFragmentModule.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java b/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java index 0c2c922a388..85799f5c65e 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java +++ b/libs/login/src/main/java/org/wordpress/android/login/di/LoginFragmentModule.java @@ -11,6 +11,7 @@ import org.wordpress.android.login.LoginUsernamePasswordFragment; import org.wordpress.android.login.SignupEmailFragment; import org.wordpress.android.login.SignupGoogleFragment; +import org.wordpress.android.login.SignupMagicLinkFragment; import dagger.Module; import dagger.android.ContributesAndroidInjector; @@ -49,4 +50,7 @@ public abstract class LoginFragmentModule { @ContributesAndroidInjector abstract SignupGoogleFragment signupGoogleFragment(); + + @ContributesAndroidInjector + abstract SignupMagicLinkFragment signupMagicLinkFragment(); } From 510e3ee5417cc3e299f15ab43bbd8b0b09c62324 Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 21:12:32 -0600 Subject: [PATCH 157/888] Move signup magic link fragment to login library --- .../login/SignupMagicLinkFragment.java | 217 ++++++++++++++++++ .../res/layout-land/signup_magic_link.xml | 75 ++++++ .../src/main/res/layout/signup_magic_link.xml | 59 +++++ libs/login/src/main/res/values/strings.xml | 5 + 4 files changed, 356 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java create mode 100644 libs/login/src/main/res/layout-land/signup_magic_link.xml create mode 100644 libs/login/src/main/res/layout/signup_magic_link.xml diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java new file mode 100644 index 00000000000..51a5e358767 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java @@ -0,0 +1,217 @@ +package org.wordpress.android.login; + +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; + +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.wordpress.android.fluxc.Dispatcher; +import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder; +import org.wordpress.android.fluxc.store.AccountStore; +import org.wordpress.android.util.AppLog; +import org.wordpress.android.util.AppLog.T; +import org.wordpress.android.util.NetworkUtils; + +import javax.inject.Inject; + +import dagger.android.support.AndroidSupportInjection; + +public class SignupMagicLinkFragment extends Fragment { + private static final String ARG_EMAIL_ADDRESS = "ARG_EMAIL_ADDRESS"; + + public static final String TAG = "signup_magic_link_fragment_tag"; + + private Button mOpenMailButton; + private ProgressDialog mProgressDialog; + + @Inject protected Dispatcher mDispatcher; + @Inject protected LoginAnalyticsListener mAnalyticsListener; + protected LoginListener mLoginListener; + protected String mEmail; + protected boolean mInProgress; + + public static SignupMagicLinkFragment newInstance(String email) { + SignupMagicLinkFragment fragment = new SignupMagicLinkFragment(); + Bundle args = new Bundle(); + args.putString(ARG_EMAIL_ADDRESS, email); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (getArguments() != null) { + mEmail = getArguments().getString(ARG_EMAIL_ADDRESS); + } + + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View layout = inflater.inflate(R.layout.signup_magic_link, container, false); + + mOpenMailButton = layout.findViewById(R.id.signup_magic_link_button); + mOpenMailButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mLoginListener != null) { + mLoginListener.openEmailClient(); + } + } + }); + + if (savedInstanceState == null) { + sendMagicLinkEmail(); + } + + return layout; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + Toolbar toolbar = view.findViewById(R.id.toolbar); + ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); + ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); + + if (actionBar != null) { + actionBar.setDisplayShowTitleEnabled(false); + actionBar.setDisplayHomeAsUpEnabled(true); + } + + if (savedInstanceState == null) { + mAnalyticsListener.trackMagicLinkOpenEmailClientViewed(); + } + } + + @Override + public void onAttach(Context context) { + AndroidSupportInjection.inject(this); + super.onAttach(context); + + if (context instanceof LoginListener) { + mLoginListener = (LoginListener) context; + } else { + throw new RuntimeException(context.toString() + " must implement LoginListener"); + } + + mDispatcher.register(this); + } + + @Override + public void onDetach() { + super.onDetach(); + mLoginListener = null; + mDispatcher.unregister(this); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.menu_login, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.help) { + if (mLoginListener != null) { + mLoginListener.helpSignupMagicLinkScreen(mEmail); + } + + return true; + } + + return false; + } + + protected void startProgress(String message) { + mOpenMailButton.setEnabled(false); + + mProgressDialog = ProgressDialog.show(getActivity(), "", message, true, true, + new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + if (mInProgress) { + endProgress(); + } + } + }); + + mInProgress = true; + } + + protected void endProgress() { + mInProgress = false; + + if (mProgressDialog != null) { + mProgressDialog.cancel(); + } + + mProgressDialog = null; + mOpenMailButton.setEnabled(true); + } + + protected void sendMagicLinkEmail() { + if (NetworkUtils.checkConnection(getActivity())) { + startProgress(getString(R.string.signup_magic_link_progress)); + AccountStore.AuthEmailPayload authEmailPayload = new AccountStore.AuthEmailPayload(mEmail, true); + mDispatcher.dispatch(AuthenticationActionBuilder.newSendAuthEmailAction(authEmailPayload)); + } + } + + protected void showErrorDialog(String message) { + DialogInterface.OnClickListener dialogListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + sendMagicLinkEmail(); + break; + // DialogInterface.BUTTON_NEGATIVE is intentionally ignored. Just dismiss dialog. + } + } + }; + + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) + .setMessage(message) + .setNegativeButton(R.string.signup_magic_link_error_button_negative, dialogListener) + .setPositiveButton(R.string.signup_magic_link_error_button_positive, dialogListener) + .create(); + dialog.show(); + } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onAuthEmailSent(AccountStore.OnAuthEmailSent event) { + if (mInProgress) { + endProgress(); + + if (event.isError()) { + mAnalyticsListener.trackSignupMagicLinkFailed(); + AppLog.e(T.API, "OnAuthEmailSent error: " + event.error.type + " - " + event.error.message); + showErrorDialog(getString(R.string.signup_magic_link_error)); + } else { + mAnalyticsListener.trackSignupMagicLinkSucceeded(); + } + } + } +} diff --git a/libs/login/src/main/res/layout-land/signup_magic_link.xml b/libs/login/src/main/res/layout-land/signup_magic_link.xml new file mode 100644 index 00000000000..1c2d8d82f5e --- /dev/null +++ b/libs/login/src/main/res/layout-land/signup_magic_link.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/login/src/main/res/layout/signup_magic_link.xml b/libs/login/src/main/res/layout/signup_magic_link.xml new file mode 100644 index 00000000000..61979fda84c --- /dev/null +++ b/libs/login/src/main/res/layout/signup_magic_link.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index f84d5ea572f..5e3490bb3d4 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -67,6 +67,11 @@ \nMaybe try a different account? There was some trouble checking the email address. To create your new WordPress.com account, please enter your email address. + There was some trouble sending the email. You can retry now or close and try again later. + Close + Retry + We sent you a magic signup link! Check your email on this device, and tap the link in the email to finish signing up. + Sending email By signing up, you agree to our %1$sTerms of Service%2$s. Sign Up with Email Sign Up with Google From 5154f180540e56b82a809d3859a82bd1d87f39bd Mon Sep 17 00:00:00 2001 From: theck13 Date: Sun, 11 Mar 2018 21:21:09 -0600 Subject: [PATCH 158/888] Update signup magic link text views from WordPress to standard widget --- libs/login/src/main/res/layout-land/signup_magic_link.xml | 5 ++--- libs/login/src/main/res/layout/signup_magic_link.xml | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libs/login/src/main/res/layout-land/signup_magic_link.xml b/libs/login/src/main/res/layout-land/signup_magic_link.xml index 1c2d8d82f5e..2fd3a7da099 100644 --- a/libs/login/src/main/res/layout-land/signup_magic_link.xml +++ b/libs/login/src/main/res/layout-land/signup_magic_link.xml @@ -27,7 +27,7 @@ app:srcCompat="@drawable/img_email_alert_120dp" > - - + diff --git a/libs/login/src/main/res/layout/signup_magic_link.xml b/libs/login/src/main/res/layout/signup_magic_link.xml index 61979fda84c..2f635a126ed 100644 --- a/libs/login/src/main/res/layout/signup_magic_link.xml +++ b/libs/login/src/main/res/layout/signup_magic_link.xml @@ -25,7 +25,7 @@ app:srcCompat="@drawable/img_email_alert_120dp" > - - + + android:text="@string/open_mail" /> - + diff --git a/libs/login/src/main/res/layout/toolbar_login.xml b/libs/login/src/main/res/layout/toolbar_login.xml index bac5435ba1b..695c90671df 100644 --- a/libs/login/src/main/res/layout/toolbar_login.xml +++ b/libs/login/src/main/res/layout/toolbar_login.xml @@ -1,24 +1,23 @@ - + android:layout_height="wrap_content"> - - + + + + + + + diff --git a/libs/login/src/main/res/values/attrs.xml b/libs/login/src/main/res/values/attrs.xml index 3914e5cd5ec..3f5b74b856c 100644 --- a/libs/login/src/main/res/values/attrs.xml +++ b/libs/login/src/main/res/values/attrs.xml @@ -5,13 +5,10 @@ WPLoginInputRow --> - - - diff --git a/libs/login/src/main/res/values/styles.xml b/libs/login/src/main/res/values/styles.xml index c35b06ba84a..31b6b44225c 100644 --- a/libs/login/src/main/res/values/styles.xml +++ b/libs/login/src/main/res/values/styles.xml @@ -1,47 +1,65 @@ - - - + + - - - - - - - - - - - + + From acc9027ad38ecd4012a7f9b125b05f3748e0337a Mon Sep 17 00:00:00 2001 From: Klymentiy Haykov Date: Fri, 20 Mar 2020 13:04:38 -0700 Subject: [PATCH 400/888] Revert "Feature/material theme and Dark Theme support (#11469)" (#11486) --- libs/login/build.gradle | 2 +- .../android/login/Login2FaFragment.java | 9 +- .../android/login/LoginEmailFragment.java | 4 +- .../login/LoginHttpAuthDialogFragment.java | 5 +- .../login/LoginMagicLinkRequestFragment.java | 5 + .../LoginSiteAddressHelpDialogFragment.java | 5 +- .../android/login/SignupEmailFragment.java | 4 +- .../login/SignupMagicLinkFragment.java | 5 +- .../widgets/WPBottomSheetDialogFragment.java | 5 + .../login/widgets/WPLoginInputRow.java | 43 ++++++- .../login_magic_link_request_screen.xml | 88 +++++++------- .../login_magic_link_sent_screen.xml | 90 +++++++-------- .../signup_bottom_sheet_dialog.xml | 47 ++++---- .../res/layout-land/signup_magic_link.xml | 85 +++++++------- .../src/main/res/layout/login_2fa_screen.xml | 2 +- .../main/res/layout/login_alert_http_auth.xml | 18 +-- .../layout/login_alert_site_address_help.xml | 14 +-- .../layout/login_email_password_screen.xml | 43 +++---- .../main/res/layout/login_email_screen.xml | 108 ++++++++++-------- .../src/main/res/layout/login_form_screen.xml | 76 ++++++------ .../src/main/res/layout/login_input_row.xml | 28 ++++- .../login_magic_link_request_screen.xml | 46 ++++---- .../layout/login_magic_link_sent_screen.xml | 37 +++--- .../res/layout/login_site_address_screen.xml | 22 ++-- .../layout/login_username_password_screen.xml | 71 ++++++------ .../res/layout/signup_bottom_sheet_dialog.xml | 43 ++++--- .../main/res/layout/signup_email_fragment.xml | 30 ++--- .../src/main/res/layout/signup_magic_link.xml | 58 ++++++---- .../src/main/res/layout/toolbar_login.xml | 39 ++++--- libs/login/src/main/res/values/attrs.xml | 3 + libs/login/src/main/res/values/styles.xml | 57 +++------ 31 files changed, 588 insertions(+), 504 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 2023cec713d..41ddc07efb7 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -40,7 +40,7 @@ dependencies { implementation 'androidx.media:media:1.0.1' implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' - implementation 'com.google.android.material:material:1.1.0' + implementation 'com.google.android.material:material:1.0.0' api 'com.google.android.gms:play-services-auth:15.0.1' diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 96b2baab5a1..d68880dfae2 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -7,6 +7,7 @@ import android.text.TextUtils; import android.text.TextWatcher; import android.text.method.DigitsKeyListener; +import android.view.ContextThemeWrapper; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -20,8 +21,6 @@ import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.fluxc.generated.AccountActionBuilder; @@ -45,10 +44,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static android.content.Context.CLIPBOARD_SERVICE; - import dagger.android.support.AndroidSupportInjection; +import static android.content.Context.CLIPBOARD_SERVICE; + public class Login2FaFragment extends LoginBaseFormFragment implements TextWatcher, OnEditorCommitListener { private static final String KEY_2FA_TYPE = "KEY_2FA_TYPE"; @@ -397,7 +396,7 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) } private void showErrorDialog(String message) { - AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity()) + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) .setMessage(message) .setPositiveButton(R.string.login_error_button, null) .create(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 8a74bbb3059..400c5fb1d15 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -10,6 +10,7 @@ import android.text.Html; import android.text.TextWatcher; import android.util.Patterns; +import android.view.ContextThemeWrapper; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -32,7 +33,6 @@ import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -383,7 +383,7 @@ private void showEmailError(int messageId) { } private void showErrorDialog(String message) { - AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity()) + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) .setMessage(message) .setPositiveButton(R.string.login_error_button, null) .create(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java index b006931af0c..66b1151b9dd 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java @@ -7,6 +7,7 @@ import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; +import android.view.ContextThemeWrapper; import android.view.KeyEvent; import android.view.View; import android.widget.EditText; @@ -17,8 +18,6 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - import org.wordpress.android.util.EditTextUtils; public class LoginHttpAuthDialogFragment extends DialogFragment { @@ -50,7 +49,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder alert = new MaterialAlertDialogBuilder(getActivity()); + AlertDialog.Builder alert = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)); alert.setTitle(R.string.http_authorization_required); //noinspection InflateParams diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index fd554f05545..7d56878202e 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -54,6 +54,7 @@ public class LoginMagicLinkRequestFragment extends Fragment { public static final String TAG = "login_magic_link_request_fragment_tag"; private static final String KEY_IN_PROGRESS = "KEY_IN_PROGRESS"; + private static final String KEY_GRAVATAR_IN_PROGRESS = "KEY_GRAVATAR_IN_PROGRESS"; private static final String ARG_EMAIL_ADDRESS = "ARG_EMAIL_ADDRESS"; private static final String ARG_MAGIC_LINK_SCHEME = "ARG_MAGIC_LINK_SCHEME"; private static final String ARG_IS_JETPACK_CONNECT = "ARG_IS_JETPACK_CONNECT"; @@ -223,6 +224,9 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { if (mInProgress) { showMagicLinkRequestProgressDialog(); } + + boolean gravatarInProgress = savedInstanceState.getBoolean(KEY_GRAVATAR_IN_PROGRESS); + mAvatarProgressBar.setVisibility(gravatarInProgress ? View.VISIBLE : View.GONE); } // important for accessibility - talkback getActivity().setTitle(R.string.magic_link_login_title); @@ -239,6 +243,7 @@ public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(KEY_IN_PROGRESS, mInProgress); + outState.putBoolean(KEY_GRAVATAR_IN_PROGRESS, mAvatarProgressBar.getVisibility() == View.VISIBLE); } @Override diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java index c9a36a95d88..98722cbaf0a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java @@ -4,13 +4,12 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; +import android.view.ContextThemeWrapper; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.SiteStore; @@ -47,7 +46,7 @@ public void onAttach(Context context) { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder alert = new MaterialAlertDialogBuilder(getActivity()); + AlertDialog.Builder alert = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)); alert.setTitle(R.string.login_site_address_help_title); //noinspection InflateParams diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java index a492701f015..ce49fd618c1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java @@ -8,6 +8,7 @@ import android.text.Editable; import android.text.TextWatcher; import android.util.Patterns; +import android.view.ContextThemeWrapper; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -28,7 +29,6 @@ import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -232,7 +232,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { } protected void showErrorDialog(String message) { - AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity()) + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) .setMessage(message) .setPositiveButton(R.string.login_error_button, null) .create(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java index 910cd28db95..b8305d18db5 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; +import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -19,8 +20,6 @@ import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.fluxc.Dispatcher; @@ -232,7 +231,7 @@ public void onClick(DialogInterface dialog, int which) { } }; - AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity()) + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) .setMessage(message) .setNegativeButton(R.string.signup_magic_link_error_button_negative, dialogListener) .setPositiveButton(R.string.signup_magic_link_error_button_positive, dialogListener) diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialogFragment.java index bf25fcf95bb..7bab90d2234 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialogFragment.java @@ -16,6 +16,11 @@ import org.wordpress.android.login.R; public class WPBottomSheetDialogFragment extends BottomSheetDialogFragment { + @Override + public int getTheme() { + return R.style.LoginTheme_BottomSheetDialogStyle; + } + @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java index c17d99bb528..1cb90f8b2f8 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java @@ -1,7 +1,10 @@ package org.wordpress.android.login.widgets; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.TypedArray; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.os.Parcel; @@ -10,12 +13,16 @@ import android.util.AttributeSet; import android.util.SparseArray; import android.view.KeyEvent; +import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.EditText; +import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.drawable.DrawableCompat; import com.google.android.material.textfield.TextInputLayout; @@ -31,9 +38,14 @@ public interface OnEditorCommitListener { void onEditorCommit(); } + private ImageView mIcon; private TextInputLayout mTextInputLayout; private EditText mEditText; + public ImageView getIcon() { + return mIcon; + } + public EditText getEditText() { return mEditText; } @@ -56,6 +68,7 @@ public WPLoginInputRow(Context context, AttributeSet attrs, int defStyle) { private void init(Context context, AttributeSet attrs) { inflate(context, R.layout.login_input_row, this); + mIcon = findViewById(R.id.icon); mTextInputLayout = findViewById(R.id.input_layout); mEditText = findViewById(R.id.input); @@ -63,6 +76,27 @@ private void init(Context context, AttributeSet attrs) { TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.wpLoginInputRow, 0, 0); try { + if (a.hasValue(R.styleable.wpLoginInputRow_wpIconDrawable)) { + int iconResId = a.getResourceId(R.styleable.wpLoginInputRow_wpIconDrawable, + R.drawable.ic_user_grey_24dp); + int tintResId = a.getResourceId(R.styleable.wpLoginInputRow_wpIconDrawableTint, + R.color.login_input_icon_color); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mIcon.setImageTintList(ColorStateList.valueOf(ContextCompat.getColor(context, tintResId))); + mIcon.setImageResource(iconResId); + } else { + Drawable drawable = context.getResources().getDrawable(iconResId); + DrawableCompat.setTint(drawable, context.getResources().getColor(tintResId)); + DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_IN); + mIcon.setImageDrawable(drawable); + } + + mIcon.setVisibility(View.VISIBLE); + } else { + mIcon.setVisibility(View.GONE); + } + if (a.hasValue(R.styleable.wpLoginInputRow_android_inputType)) { mEditText.setInputType(a.getInteger(R.styleable.wpLoginInputRow_android_inputType, 0)); } @@ -78,11 +112,16 @@ private void init(Context context, AttributeSet attrs) { // Makes the hint transparent, so the TalkBack can read it, when the field is prefilled mEditText.setHintTextColor(getResources().getColor(android.R.color.transparent)); } + if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleEnabled)) { mTextInputLayout.setPasswordVisibilityToggleEnabled( a.getBoolean(R.styleable.wpLoginInputRow_passwordToggleEnabled, false)); } + if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleTint)) { + mTextInputLayout.setPasswordVisibilityToggleTintList( + a.getColorStateList(R.styleable.wpLoginInputRow_passwordToggleTint)); + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (a.hasValue(R.styleable.wpLoginInputRow_android_textAlignment)) { mEditText.setTextAlignment( @@ -145,8 +184,8 @@ public void setOnEditorCommitListener(final OnEditorCommitListener listener) { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE - || actionId == EditorInfo.IME_ACTION_NEXT - || (event != null + || actionId == EditorInfo.IME_ACTION_NEXT + || (event != null && event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { listener.onEditorCommit(); diff --git a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml index 29877bd2aff..060cdce6451 100644 --- a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml +++ b/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml @@ -1,9 +1,11 @@ + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools"> - + + android:layout_height="wrap_content"/> + android:indeterminate="true"/> - + android:text="@string/login_magic_links_label"/> - + android:background="@color/login_background_color" + android:paddingStart="@dimen/margin_small_medium" + android:paddingEnd="@dimen/margin_medium_large" + android:paddingTop="@dimen/margin_medium_large" + android:paddingBottom="@dimen/margin_medium_large" + android:layout_alignParentBottom="true" + android:clipToPadding="false" + tools:ignore="InconsistentLayout"> - - - + android:layout_marginEnd="@dimen/margin_extra_large" + android:gravity="start|center_vertical" + android:text="@string/enter_your_password_instead"/> - - - + + diff --git a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml index 1933c757144..7cf5f68af62 100644 --- a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml +++ b/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml @@ -1,77 +1,73 @@ + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools"> - + + android:layout_centerInParent="true" + android:orientation="vertical" + android:gravity="center_horizontal"> + android:contentDescription="@null" + app:srcCompat="@drawable/login_email_alert"/> - + android:text="@string/login_magic_links_sent_label"/> - + android:background="@color/login_background_color" + android:paddingStart="@dimen/margin_small_medium" + android:paddingEnd="@dimen/margin_medium_large" + android:paddingTop="@dimen/margin_medium_large" + android:paddingBottom="@dimen/margin_medium_large" + android:layout_alignParentBottom="true" + android:clipToPadding="false" + tools:ignore="InconsistentLayout"> - - - + android:layout_marginEnd="@dimen/margin_extra_large" + android:gravity="start|center_vertical" + android:text="@string/enter_your_password_instead"/> - - - - + + diff --git a/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml b/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml index a05807f5a9f..0f5a6453734 100644 --- a/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml +++ b/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml @@ -1,50 +1,55 @@ - + android:paddingTop="@dimen/margin_medium" > - + android:text="@string/signup_terms_of_service_text" + style="@style/LoginTheme.Button.Secondary" > + + android:layout_marginTop="@dimen/margin_extra_small" + android:layout_width="match_parent" + android:orientation="horizontal" > - + android:layout_width="wrap_content" + android:text="@string/signup_with_email_button" + android:theme="@style/LoginTheme.Button" > + - + android:layout_width="wrap_content" + android:text="@string/signup_with_google_button" + android:theme="@style/LoginTheme.Button" > + diff --git a/libs/login/src/main/res/layout-land/signup_magic_link.xml b/libs/login/src/main/res/layout-land/signup_magic_link.xml index 290d3e3f026..1917679299a 100644 --- a/libs/login/src/main/res/layout-land/signup_magic_link.xml +++ b/libs/login/src/main/res/layout-land/signup_magic_link.xml @@ -1,68 +1,71 @@ - + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools"> - + + + android:layout_width="match_parent" + android:orientation="vertical" > + app:srcCompat="@drawable/login_email_alert" > + + android:paddingStart="@dimen/margin_extra_extra_large" + android:paddingTop="@dimen/margin_extra_large" + android:text="@string/signup_magic_link_message" + style="@style/Base.TextAppearance.AppCompat.Body1" > + - + android:layout_width="match_parent" + android:paddingBottom="@dimen/margin_medium_large" + android:paddingEnd="@dimen/margin_medium_large" + android:paddingStart="@dimen/margin_small_medium" + android:paddingTop="@dimen/margin_medium_large" + tools:ignore="InconsistentLayout"> - + android:layout_width="wrap_content" + android:text="@string/open_mail" + style="@style/LoginTheme.Button.Primary" > + - + - - diff --git a/libs/login/src/main/res/layout/login_2fa_screen.xml b/libs/login/src/main/res/layout/login_2fa_screen.xml index de326ff7841..9d32b8352b4 100644 --- a/libs/login/src/main/res/layout/login_2fa_screen.xml +++ b/libs/login/src/main/res/layout/login_2fa_screen.xml @@ -9,7 +9,7 @@ android:paddingEnd="@dimen/margin_extra_large" android:layout_marginBottom="@dimen/margin_extra_large"> - + android:layout_height="wrap_content"> + android:singleLine="true" + android:hint="@string/httpuser"/> + app:passwordToggleTint="@color/login_input_password_icon_color"> + android:inputType="textPassword" + android:hint="@string/httppassword"/> diff --git a/libs/login/src/main/res/layout/login_alert_site_address_help.xml b/libs/login/src/main/res/layout/login_alert_site_address_help.xml index 2ab69b3277c..933c2ea8f74 100644 --- a/libs/login/src/main/res/layout/login_alert_site_address_help.xml +++ b/libs/login/src/main/res/layout/login_alert_site_address_help.xml @@ -3,24 +3,24 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:gravity="top" android:orientation="vertical" + android:gravity="top" android:padding="?attr/dialogPreferredPadding"> - + android:text="@string/login_site_address_help_content"/> + android:contentDescription="@null"/> diff --git a/libs/login/src/main/res/layout/login_email_password_screen.xml b/libs/login/src/main/res/layout/login_email_password_screen.xml index 8053752cf6e..ad8b4987b60 100644 --- a/libs/login/src/main/res/layout/login_email_password_screen.xml +++ b/libs/login/src/main/res/layout/login_email_password_screen.xml @@ -1,25 +1,25 @@ + android:layout_marginBottom="@dimen/margin_extra_large"> - + android:tint="@color/login_input_icon_color" + app:srcCompat="@drawable/ic_user_grey_24dp"/> + android:focusable="true"> - + android:text="@string/email_address"/> - + android:gravity="start" + tools:text="s@b.com"/> @@ -69,12 +69,15 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/margin_extra_large" android:layout_marginBottom="@dimen/margin_extra_extra_large" - android:gravity="start" android:hint="@string/password" android:importantForAutofill="noExcludeDescendants" android:inputType="textPassword" android:textAlignment="viewStart" + android:gravity="start" app:passwordToggleEnabled="true" - tools:ignore="UnusedAttribute" /> + app:passwordToggleTint="@color/login_input_password_icon_color" + app:wpIconDrawable="@drawable/ic_lock_grey_24dp" + tools:ignore="UnusedAttribute" > + diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index 53e8e305001..30dbc62535d 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -1,108 +1,116 @@ - + android:paddingEnd="@dimen/margin_extra_large" + android:paddingStart="@dimen/margin_extra_large" > - + android:gravity="start" + tools:text="@string/enter_email_wordpress_com" + style="@style/LoginTheme.TextLabel" > + + android:gravity="start" + tools:ignore="UnusedAttribute" > + - + android:layout_marginTop="@dimen/margin_extra_large" + android:layout_width="wrap_content" + android:text="@string/alternatively" + style="@style/LoginTheme.TextLabel" > + + android:paddingEnd="@dimen/margin_medium" + android:paddingTop="@dimen/margin_medium" + android:gravity="center_vertical" + tools:ignore="RtlSymmetry" > + android:layout_width="@dimen/google_button_icon_sz" + app:srcCompat="@drawable/ic_google_60dp" > + - + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:text="@string/login_google_button_suffix" + style="@style/LoginTheme.Button.Google" > + + android:paddingEnd="@dimen/margin_medium" + android:paddingTop="@dimen/margin_medium" + android:gravity="center_vertical" + tools:ignore="RtlSymmetry" > + android:layout_width="@dimen/google_button_icon_sz" + app:srcCompat="@drawable/ic_domains_grey_24dp" > + - + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:text="@string/enter_site_address_instead" + style="@style/LoginTheme.Button.Google" > + diff --git a/libs/login/src/main/res/layout/login_form_screen.xml b/libs/login/src/main/res/layout/login_form_screen.xml index 0621b1cc49c..4ed2340b3d4 100644 --- a/libs/login/src/main/res/layout/login_form_screen.xml +++ b/libs/login/src/main/res/layout/login_form_screen.xml @@ -5,64 +5,58 @@ android:layout_height="match_parent"> + android:layout_below="@+id/toolbar" + android:layout_above="@+id/bottom_buttons"> + android:layout_marginBottom="@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/src/main/res/layout/login_input_row.xml b/libs/login/src/main/res/layout/login_input_row.xml index d39dcbb868e..eb238712df3 100644 --- a/libs/login/src/main/res/layout/login_input_row.xml +++ b/libs/login/src/main/res/layout/login_input_row.xml @@ -1,24 +1,40 @@ - + + - + android:layout_marginEnd="@dimen/textinputlayout_correction_margin_right" + android:paddingEnd="@dimen/textinputlayout_correction_padding_right" + tools:hint="@string/email_address"/> + diff --git a/libs/login/src/main/res/layout/login_magic_link_request_screen.xml b/libs/login/src/main/res/layout/login_magic_link_request_screen.xml index ce7ae44a4c2..5b87de6b893 100644 --- a/libs/login/src/main/res/layout/login_magic_link_request_screen.xml +++ b/libs/login/src/main/res/layout/login_magic_link_request_screen.xml @@ -1,13 +1,16 @@ - + android:layout_height="match_parent"> - + + android:layout_marginBottom="@dimen/margin_extra_large" + android:layout_marginTop="@dimen/margin_extra_extra_large"> + android:layout_height="wrap_content"/> + android:padding="@dimen/margin_large"/> - + android:text="@string/login_magic_links_label"/> - + android:theme="@style/LoginTheme.Button"/> - + android:paddingStart="@dimen/margin_medium_large" + android:text="@string/enter_your_password_instead"/> - + diff --git a/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml b/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml index 53f833f75bb..4b97edaf36e 100644 --- a/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml +++ b/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml @@ -1,44 +1,53 @@ - + android:layout_height="match_parent"> - + + app:srcCompat="@drawable/login_email_alert"/> - + android:text="@string/login_magic_links_sent_label"/> - - - + diff --git a/libs/login/src/main/res/layout/login_site_address_screen.xml b/libs/login/src/main/res/layout/login_site_address_screen.xml index 596cd8e6f07..305760d03a1 100644 --- a/libs/login/src/main/res/layout/login_site_address_screen.xml +++ b/libs/login/src/main/res/layout/login_site_address_screen.xml @@ -1,33 +1,35 @@ + android:layout_marginBottom="@dimen/margin_extra_large"> - + android:imeOptions="actionNext" + android:textAlignment="viewStart" + android:gravity="start" + app:wpIconDrawable="@drawable/ic_globe_grey_24dp"/> diff --git a/libs/login/src/main/res/layout/login_username_password_screen.xml b/libs/login/src/main/res/layout/login_username_password_screen.xml index f2b142305cc..d1829689dfb 100644 --- a/libs/login/src/main/res/layout/login_username_password_screen.xml +++ b/libs/login/src/main/res/layout/login_username_password_screen.xml @@ -1,34 +1,34 @@ + android:layout_marginBottom="@dimen/margin_extra_large"> - @@ -61,40 +61,40 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="@dimen/margin_extra_large" - android:focusable="true" - android:orientation="vertical"> + android:orientation="vertical" + android:focusable="true"> - + tools:visibility="visible" + android:textAlignment="viewStart" + android:gravity="start"/> - + android:gravity="start" + tools:text="Arround the World with Pam"/> - + android:gravity="start" + tools:text="pamelanguyyen.wordpress.com"/> @@ -102,11 +102,12 @@ android:id="@+id/login_username_row" android:layout_width="match_parent" android:layout_height="wrap_content" - android:gravity="start" android:hint="@string/username" - android:imeOptions="actionNext" android:inputType="textPersonName" - android:textAlignment="viewStart" /> + android:imeOptions="actionNext" + android:textAlignment="viewStart" + android:gravity="start" + app:wpIconDrawable="@drawable/ic_user_grey_24dp"/> + app:passwordToggleTint="@color/login_input_password_icon_color" + android:textAlignment="viewStart" + android:gravity="start" + android:accessibilityLiveRegion="assertive" + app:wpIconDrawable="@drawable/ic_lock_grey_24dp" + tools:ignore="UnusedAttribute"/> diff --git a/libs/login/src/main/res/layout/signup_bottom_sheet_dialog.xml b/libs/login/src/main/res/layout/signup_bottom_sheet_dialog.xml index 87605487db4..f0408261cdd 100644 --- a/libs/login/src/main/res/layout/signup_bottom_sheet_dialog.xml +++ b/libs/login/src/main/res/layout/signup_bottom_sheet_dialog.xml @@ -1,41 +1,46 @@ - + android:paddingTop="@dimen/margin_medium" > - + android:text="@string/signup_terms_of_service_text" + style="@style/LoginTheme.Button.Secondary" > + - + android:layout_marginTop="@dimen/margin_extra_small" + android:layout_width="match_parent" + android:text="@string/signup_with_email_button" + android:theme="@style/LoginTheme.Button" > + - + android:layout_width="match_parent" + android:text="@string/signup_with_google_button" + android:theme="@style/LoginTheme.Button" > + diff --git a/libs/login/src/main/res/layout/signup_email_fragment.xml b/libs/login/src/main/res/layout/signup_email_fragment.xml index 50061cf17ec..6a5d3110628 100644 --- a/libs/login/src/main/res/layout/signup_email_fragment.xml +++ b/libs/login/src/main/res/layout/signup_email_fragment.xml @@ -1,34 +1,38 @@ - + android:paddingLeft="@dimen/margin_extra_large" + android:paddingRight="@dimen/margin_extra_large" + android:paddingStart="@dimen/margin_extra_large" > - + android:layout_marginTop="@dimen/margin_extra_large" + android:layout_width="match_parent" + tools:text="@string/signup_email_header" + style="@style/LoginTheme.TextLabel" > + + android:layout_height="wrap_content" + android:layout_width="match_parent" + app:wpIconDrawable="@drawable/ic_user_grey_24dp" + tools:ignore="UnusedAttribute" > + diff --git a/libs/login/src/main/res/layout/signup_magic_link.xml b/libs/login/src/main/res/layout/signup_magic_link.xml index 92e11f33799..e4c2e65c448 100644 --- a/libs/login/src/main/res/layout/signup_magic_link.xml +++ b/libs/login/src/main/res/layout/signup_magic_link.xml @@ -1,50 +1,58 @@ - + android:layout_width="match_parent" > - + + + android:layout_width="match_parent" > + app:srcCompat="@drawable/login_email_alert" > + + android:paddingStart="@dimen/margin_extra_extra_large" + android:paddingTop="@dimen/margin_extra_large" + android:text="@string/signup_magic_link_message" + style="@style/Base.TextAppearance.AppCompat.Body1" > + - + android:layout_width="wrap_content" + android:text="@string/open_mail" + android:theme="@style/LoginTheme.Button" + style="@style/Widget.AppCompat.Button.Colored" > + - + diff --git a/libs/login/src/main/res/layout/toolbar_login.xml b/libs/login/src/main/res/layout/toolbar_login.xml index 695c90671df..bac5435ba1b 100644 --- a/libs/login/src/main/res/layout/toolbar_login.xml +++ b/libs/login/src/main/res/layout/toolbar_login.xml @@ -1,23 +1,24 @@ - + android:layout_height="?attr/actionBarSize" + android:background="@color/login_toolbar_color" + android:elevation="@dimen/appbar_elevation" + app:contentInsetLeft="@dimen/toolbar_content_offset" + app:contentInsetStart="@dimen/toolbar_content_offset" + app:contentInsetRight="@dimen/toolbar_content_offset_end" + app:contentInsetEnd="@dimen/toolbar_content_offset_end" + app:theme="@style/LoginTheme.Toolbar" + tools:targetApi="LOLLIPOP"> - - - - - - - + + diff --git a/libs/login/src/main/res/values/attrs.xml b/libs/login/src/main/res/values/attrs.xml index 3f5b74b856c..3914e5cd5ec 100644 --- a/libs/login/src/main/res/values/attrs.xml +++ b/libs/login/src/main/res/values/attrs.xml @@ -5,10 +5,13 @@ WPLoginInputRow --> + + + diff --git a/libs/login/src/main/res/values/styles.xml b/libs/login/src/main/res/values/styles.xml index 31b6b44225c..c35b06ba84a 100644 --- a/libs/login/src/main/res/values/styles.xml +++ b/libs/login/src/main/res/values/styles.xml @@ -1,65 +1,47 @@ - - - - - - - - - - - - - - - - - - - - From 01dc0242ff540177613f86f0f331bf6f1dda2268 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 20 Mar 2020 20:12:09 -0400 Subject: [PATCH 401/888] Ignore onDiscoverySucceeded events if LoginBaseDiscoveryFragment is detached --- .../wordpress/android/login/LoginBaseDiscoveryFragment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseDiscoveryFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseDiscoveryFragment.java index 1ef6bb5d260..4390ab57d39 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseDiscoveryFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseDiscoveryFragment.java @@ -38,6 +38,10 @@ void initiateDiscovery() { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onDiscoverySucceeded(OnDiscoveryResponse event) { + if (mLoginBaseDiscoveryListener == null) { + // Ignore the event if the fragment is detached + return; + } // hold the URL in a variable to use below otherwise it gets cleared up by endProgress // bail if user canceled String mRequestedSiteAddress = mLoginBaseDiscoveryListener.getRequestedSiteAddress(); From 6807c3c3a8c7401765864106e3215dea0a59a011 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Thu, 26 Mar 2020 16:13:35 -0500 Subject: [PATCH 402/888] Fixed config change issues. --- .../wordpress/android/login/LoginEmailFragment.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 9ad2f6c4f27..76da552319c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -64,7 +64,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private static final String KEY_IS_SOCIAL = "KEY_IS_SOCIAL"; private static final String KEY_OLD_SITES_IDS = "KEY_OLD_SITES_IDS"; private static final String KEY_REQUESTED_EMAIL = "KEY_REQUESTED_EMAIL"; - private static final String VALIDITY_EMAIL = "VALIDITY_EMAIL"; + private static final String VALIDITY_EMAIL = "KEY_VALIDITY_EMAIL"; private static final String LOG_TAG = LoginEmailFragment.class.getSimpleName(); private static final int GOOGLE_API_CLIENT_ID = 1002; private static final int EMAIL_CREDENTIALS_REQUEST_CODE = 25100; @@ -79,7 +79,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private String mGoogleEmail; private String mRequestedEmail; private boolean mIsSocialLogin; - private Boolean mIsValidEmail; + private Boolean mIsValidEmail = null; protected WPLoginInputRow mEmailInput; protected boolean mHasDismissedEmailHints; @@ -315,11 +315,8 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { mIsSocialLogin = savedInstanceState.getBoolean(KEY_IS_SOCIAL); mIsDisplayingEmailHints = savedInstanceState.getBoolean(KEY_IS_DISPLAYING_EMAIL_HINTS); mHasDismissedEmailHints = savedInstanceState.getBoolean(KEY_HAS_DISMISSED_EMAIL_HINTS); - if (savedInstanceState.getBoolean(VALIDITY_EMAIL) || !(savedInstanceState - .getBoolean(VALIDITY_EMAIL))) { + if (savedInstanceState.containsKey(VALIDITY_EMAIL)) { mIsValidEmail = savedInstanceState.getBoolean(VALIDITY_EMAIL); - } else { - mIsValidEmail = null; } } else { mAnalyticsListener.trackEmailFormViewed(); @@ -358,7 +355,7 @@ protected void next(String email) { private void showErrorIfEmailInvalid() { if (mIsValidEmail != null && !mIsValidEmail) { - showEmailError(R.string.email_invalid); + showEmailError(R.string.email_invalid); } } @@ -395,6 +392,7 @@ public void beforeTextChanged(CharSequence s, int start, int count, int after) { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { mEmailInput.setError(null); + mIsValidEmail = null; mIsSocialLogin = false; } From da89c295ca5eb3c42ccfa56917c51ca2f0fa567b Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Fri, 27 Mar 2020 12:31:25 -0500 Subject: [PATCH 403/888] removed clearing in text watcher. --- .../java/org/wordpress/android/login/LoginEmailFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 76da552319c..d265f462069 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -392,7 +392,6 @@ public void beforeTextChanged(CharSequence s, int start, int count, int after) { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { mEmailInput.setError(null); - mIsValidEmail = null; mIsSocialLogin = false; } From f2059aade8d8bf4d4f8e1c8b1938230ff76b8579 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 1 Apr 2020 10:30:05 -0500 Subject: [PATCH 404/888] utilized runnable that's posted when the UI has been drawn. --- .../org/wordpress/android/login/LoginEmailFragment.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index d265f462069..43386bb8644 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -137,7 +137,12 @@ protected void setupContent(ViewGroup rootView) { if (BuildConfig.DEBUG) { mEmailInput.getEditText().setText(BuildConfig.DEBUG_WPCOM_LOGIN_EMAIL); } - mEmailInput.addTextChangedListener(this); + mEmailInput.post(new Runnable() { + @Override public void run() { + mEmailInput.addTextChangedListener(LoginEmailFragment.this); + } + }); + mEmailInput.setOnEditorCommitListener(this); mEmailInput.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override @@ -393,6 +398,7 @@ public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void onTextChanged(CharSequence s, int start, int before, int count) { mEmailInput.setError(null); mIsSocialLogin = false; + mIsValidEmail = null; } private void showEmailError(int messageId) { From e1708e5b85093f771a31ee7d3789396462cf5f0a Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Wed, 1 Apr 2020 10:48:53 -0500 Subject: [PATCH 405/888] store the res id instead of the boolean so it supports multiple errors. --- .../android/login/LoginEmailFragment.java | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 43386bb8644..7d2a038bee6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -64,7 +64,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private static final String KEY_IS_SOCIAL = "KEY_IS_SOCIAL"; private static final String KEY_OLD_SITES_IDS = "KEY_OLD_SITES_IDS"; private static final String KEY_REQUESTED_EMAIL = "KEY_REQUESTED_EMAIL"; - private static final String VALIDITY_EMAIL = "KEY_VALIDITY_EMAIL"; + private static final String KEY_EMAIL_ERROR_RES = "KEY_EMAIL_ERROR_RES"; private static final String LOG_TAG = LoginEmailFragment.class.getSimpleName(); private static final int GOOGLE_API_CLIENT_ID = 1002; private static final int EMAIL_CREDENTIALS_REQUEST_CODE = 25100; @@ -79,7 +79,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private String mGoogleEmail; private String mRequestedEmail; private boolean mIsSocialLogin; - private Boolean mIsValidEmail = null; + private Integer mCurrentEmailErrorRes = null; protected WPLoginInputRow mEmailInput; protected boolean mHasDismissedEmailHints; @@ -295,7 +295,7 @@ public void onStart() { .enableAutoManage(getActivity(), GOOGLE_API_CLIENT_ID, LoginEmailFragment.this) .addApi(Auth.CREDENTIALS_API) .build(); - showErrorIfEmailInvalid(); + showEmailError(); } @Override @@ -320,8 +320,8 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { mIsSocialLogin = savedInstanceState.getBoolean(KEY_IS_SOCIAL); mIsDisplayingEmailHints = savedInstanceState.getBoolean(KEY_IS_DISPLAYING_EMAIL_HINTS); mHasDismissedEmailHints = savedInstanceState.getBoolean(KEY_HAS_DISMISSED_EMAIL_HINTS); - if (savedInstanceState.containsKey(VALIDITY_EMAIL)) { - mIsValidEmail = savedInstanceState.getBoolean(VALIDITY_EMAIL); + if (savedInstanceState.containsKey(KEY_EMAIL_ERROR_RES)) { + mCurrentEmailErrorRes = savedInstanceState.getInt(KEY_EMAIL_ERROR_RES); } } else { mAnalyticsListener.trackEmailFormViewed(); @@ -337,8 +337,8 @@ public void onSaveInstanceState(Bundle outState) { outState.putBoolean(KEY_IS_SOCIAL, mIsSocialLogin); outState.putBoolean(KEY_IS_DISPLAYING_EMAIL_HINTS, mIsDisplayingEmailHints); outState.putBoolean(KEY_HAS_DISMISSED_EMAIL_HINTS, mHasDismissedEmailHints); - if (mIsValidEmail != null) { - outState.putBoolean(VALIDITY_EMAIL, mIsValidEmail); + if (mCurrentEmailErrorRes != null) { + outState.putInt(KEY_EMAIL_ERROR_RES, mCurrentEmailErrorRes); } } @@ -348,19 +348,26 @@ protected void next(String email) { } if (isValidEmail(email)) { - mIsValidEmail = true; + clearEmailError(); startProgress(); mRequestedEmail = email; mDispatcher.dispatch(AccountActionBuilder.newIsAvailableEmailAction(email)); } else { - mIsValidEmail = false; showEmailError(R.string.email_invalid); } } - private void showErrorIfEmailInvalid() { - if (mIsValidEmail != null && !mIsValidEmail) { - showEmailError(R.string.email_invalid); + /** + * This is cleared every time the text is changed or the email is valid so that if the user rotates the device, they + * don't receive an unnecessary warning from a previous error. + */ + private void clearEmailError() { + mCurrentEmailErrorRes = null; + } + + private void showEmailError() { + if (mCurrentEmailErrorRes != null) { + showEmailError(mCurrentEmailErrorRes); } } @@ -398,10 +405,11 @@ public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void onTextChanged(CharSequence s, int start, int before, int count) { mEmailInput.setError(null); mIsSocialLogin = false; - mIsValidEmail = null; + clearEmailError(); } private void showEmailError(int messageId) { + mCurrentEmailErrorRes = messageId; mEmailInput.setError(getString(messageId)); } From a2e9e4aab055687427d17ffd0dd73e872bda654a Mon Sep 17 00:00:00 2001 From: Stefanos Togoulidis Date: Fri, 3 Apr 2020 17:52:37 +0300 Subject: [PATCH 406/888] Gutenberg/integrate release 1.25.0 with dark mode (#11580) --- libs/login/build.gradle | 2 +- .../android/login/Login2FaFragment.java | 9 +- .../android/login/LoginEmailFragment.java | 4 +- .../login/LoginHttpAuthDialogFragment.java | 5 +- .../login/LoginMagicLinkRequestFragment.java | 5 - .../LoginSiteAddressHelpDialogFragment.java | 5 +- .../android/login/SignupEmailFragment.java | 4 +- .../login/SignupMagicLinkFragment.java | 5 +- .../widgets/WPBottomSheetDialogFragment.java | 5 - .../login/widgets/WPLoginInputRow.java | 43 +------ .../login_magic_link_request_screen.xml | 88 +++++++------- .../login_magic_link_sent_screen.xml | 90 ++++++++------- .../signup_bottom_sheet_dialog.xml | 47 ++++---- .../res/layout-land/signup_magic_link.xml | 85 +++++++------- .../src/main/res/layout/login_2fa_screen.xml | 2 +- .../main/res/layout/login_alert_http_auth.xml | 18 +-- .../layout/login_alert_site_address_help.xml | 14 +-- .../layout/login_email_password_screen.xml | 43 ++++--- .../main/res/layout/login_email_screen.xml | 108 ++++++++---------- .../src/main/res/layout/login_form_screen.xml | 76 ++++++------ .../src/main/res/layout/login_input_row.xml | 28 +---- .../login_magic_link_request_screen.xml | 46 ++++---- .../layout/login_magic_link_sent_screen.xml | 37 +++--- .../res/layout/login_site_address_screen.xml | 22 ++-- .../layout/login_username_password_screen.xml | 71 ++++++------ .../res/layout/signup_bottom_sheet_dialog.xml | 43 +++---- .../main/res/layout/signup_email_fragment.xml | 30 +++-- .../src/main/res/layout/signup_magic_link.xml | 58 ++++------ .../src/main/res/layout/toolbar_login.xml | 39 +++---- libs/login/src/main/res/values/attrs.xml | 3 - libs/login/src/main/res/values/styles.xml | 57 ++++++--- 31 files changed, 504 insertions(+), 588 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 41ddc07efb7..2023cec713d 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -40,7 +40,7 @@ dependencies { implementation 'androidx.media:media:1.0.1' implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' - implementation 'com.google.android.material:material:1.0.0' + implementation 'com.google.android.material:material:1.1.0' api 'com.google.android.gms:play-services-auth:15.0.1' diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index d68880dfae2..96b2baab5a1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -7,7 +7,6 @@ import android.text.TextUtils; import android.text.TextWatcher; import android.text.method.DigitsKeyListener; -import android.view.ContextThemeWrapper; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -21,6 +20,8 @@ import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; + import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.fluxc.generated.AccountActionBuilder; @@ -44,10 +45,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import dagger.android.support.AndroidSupportInjection; - import static android.content.Context.CLIPBOARD_SERVICE; +import dagger.android.support.AndroidSupportInjection; + public class Login2FaFragment extends LoginBaseFormFragment implements TextWatcher, OnEditorCommitListener { private static final String KEY_2FA_TYPE = "KEY_2FA_TYPE"; @@ -396,7 +397,7 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) } private void showErrorDialog(String message) { - AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) + AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity()) .setMessage(message) .setPositiveButton(R.string.login_error_button, null) .create(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 7d2a038bee6..5cd2f9b675e 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -10,7 +10,6 @@ import android.text.Html; import android.text.TextWatcher; import android.util.Patterns; -import android.view.ContextThemeWrapper; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -33,6 +32,7 @@ import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -414,7 +414,7 @@ private void showEmailError(int messageId) { } private void showErrorDialog(String message) { - AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) + AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity()) .setMessage(message) .setPositiveButton(R.string.login_error_button, null) .create(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java index 66b1151b9dd..b006931af0c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginHttpAuthDialogFragment.java @@ -7,7 +7,6 @@ import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; -import android.view.ContextThemeWrapper; import android.view.KeyEvent; import android.view.View; import android.widget.EditText; @@ -18,6 +17,8 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; + import org.wordpress.android.util.EditTextUtils; public class LoginHttpAuthDialogFragment extends DialogFragment { @@ -49,7 +50,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder alert = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)); + AlertDialog.Builder alert = new MaterialAlertDialogBuilder(getActivity()); alert.setTitle(R.string.http_authorization_required); //noinspection InflateParams diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index 7d56878202e..fd554f05545 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -54,7 +54,6 @@ public class LoginMagicLinkRequestFragment extends Fragment { public static final String TAG = "login_magic_link_request_fragment_tag"; private static final String KEY_IN_PROGRESS = "KEY_IN_PROGRESS"; - private static final String KEY_GRAVATAR_IN_PROGRESS = "KEY_GRAVATAR_IN_PROGRESS"; private static final String ARG_EMAIL_ADDRESS = "ARG_EMAIL_ADDRESS"; private static final String ARG_MAGIC_LINK_SCHEME = "ARG_MAGIC_LINK_SCHEME"; private static final String ARG_IS_JETPACK_CONNECT = "ARG_IS_JETPACK_CONNECT"; @@ -224,9 +223,6 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { if (mInProgress) { showMagicLinkRequestProgressDialog(); } - - boolean gravatarInProgress = savedInstanceState.getBoolean(KEY_GRAVATAR_IN_PROGRESS); - mAvatarProgressBar.setVisibility(gravatarInProgress ? View.VISIBLE : View.GONE); } // important for accessibility - talkback getActivity().setTitle(R.string.magic_link_login_title); @@ -243,7 +239,6 @@ public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(KEY_IN_PROGRESS, mInProgress); - outState.putBoolean(KEY_GRAVATAR_IN_PROGRESS, mAvatarProgressBar.getVisibility() == View.VISIBLE); } @Override diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java index 98722cbaf0a..c9a36a95d88 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java @@ -4,12 +4,13 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; -import android.view.ContextThemeWrapper; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; + import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.SiteStore; @@ -46,7 +47,7 @@ public void onAttach(Context context) { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder alert = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)); + AlertDialog.Builder alert = new MaterialAlertDialogBuilder(getActivity()); alert.setTitle(R.string.login_site_address_help_title); //noinspection InflateParams diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java index ce49fd618c1..a492701f015 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java @@ -8,7 +8,6 @@ import android.text.Editable; import android.text.TextWatcher; import android.util.Patterns; -import android.view.ContextThemeWrapper; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -29,6 +28,7 @@ import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -232,7 +232,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { } protected void showErrorDialog(String message) { - AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) + AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity()) .setMessage(message) .setPositiveButton(R.string.login_error_button, null) .create(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java index b8305d18db5..910cd28db95 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java @@ -4,7 +4,6 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; -import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -20,6 +19,8 @@ import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; + import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.fluxc.Dispatcher; @@ -231,7 +232,7 @@ public void onClick(DialogInterface dialog, int which) { } }; - AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.LoginTheme)) + AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity()) .setMessage(message) .setNegativeButton(R.string.signup_magic_link_error_button_negative, dialogListener) .setPositiveButton(R.string.signup_magic_link_error_button_positive, dialogListener) diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialogFragment.java index 7bab90d2234..bf25fcf95bb 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPBottomSheetDialogFragment.java @@ -16,11 +16,6 @@ import org.wordpress.android.login.R; public class WPBottomSheetDialogFragment extends BottomSheetDialogFragment { - @Override - public int getTheme() { - return R.style.LoginTheme_BottomSheetDialogStyle; - } - @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java index 1cb90f8b2f8..c17d99bb528 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java @@ -1,10 +1,7 @@ package org.wordpress.android.login.widgets; import android.content.Context; -import android.content.res.ColorStateList; import android.content.res.TypedArray; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.os.Parcel; @@ -13,16 +10,12 @@ import android.util.AttributeSet; import android.util.SparseArray; import android.view.KeyEvent; -import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.EditText; -import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; -import androidx.core.graphics.drawable.DrawableCompat; import com.google.android.material.textfield.TextInputLayout; @@ -38,14 +31,9 @@ public interface OnEditorCommitListener { void onEditorCommit(); } - private ImageView mIcon; private TextInputLayout mTextInputLayout; private EditText mEditText; - public ImageView getIcon() { - return mIcon; - } - public EditText getEditText() { return mEditText; } @@ -68,7 +56,6 @@ public WPLoginInputRow(Context context, AttributeSet attrs, int defStyle) { private void init(Context context, AttributeSet attrs) { inflate(context, R.layout.login_input_row, this); - mIcon = findViewById(R.id.icon); mTextInputLayout = findViewById(R.id.input_layout); mEditText = findViewById(R.id.input); @@ -76,27 +63,6 @@ private void init(Context context, AttributeSet attrs) { TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.wpLoginInputRow, 0, 0); try { - if (a.hasValue(R.styleable.wpLoginInputRow_wpIconDrawable)) { - int iconResId = a.getResourceId(R.styleable.wpLoginInputRow_wpIconDrawable, - R.drawable.ic_user_grey_24dp); - int tintResId = a.getResourceId(R.styleable.wpLoginInputRow_wpIconDrawableTint, - R.color.login_input_icon_color); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - mIcon.setImageTintList(ColorStateList.valueOf(ContextCompat.getColor(context, tintResId))); - mIcon.setImageResource(iconResId); - } else { - Drawable drawable = context.getResources().getDrawable(iconResId); - DrawableCompat.setTint(drawable, context.getResources().getColor(tintResId)); - DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_IN); - mIcon.setImageDrawable(drawable); - } - - mIcon.setVisibility(View.VISIBLE); - } else { - mIcon.setVisibility(View.GONE); - } - if (a.hasValue(R.styleable.wpLoginInputRow_android_inputType)) { mEditText.setInputType(a.getInteger(R.styleable.wpLoginInputRow_android_inputType, 0)); } @@ -112,16 +78,11 @@ private void init(Context context, AttributeSet attrs) { // Makes the hint transparent, so the TalkBack can read it, when the field is prefilled mEditText.setHintTextColor(getResources().getColor(android.R.color.transparent)); } - if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleEnabled)) { mTextInputLayout.setPasswordVisibilityToggleEnabled( a.getBoolean(R.styleable.wpLoginInputRow_passwordToggleEnabled, false)); } - if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleTint)) { - mTextInputLayout.setPasswordVisibilityToggleTintList( - a.getColorStateList(R.styleable.wpLoginInputRow_passwordToggleTint)); - } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (a.hasValue(R.styleable.wpLoginInputRow_android_textAlignment)) { mEditText.setTextAlignment( @@ -184,8 +145,8 @@ public void setOnEditorCommitListener(final OnEditorCommitListener listener) { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE - || actionId == EditorInfo.IME_ACTION_NEXT - || (event != null + || actionId == EditorInfo.IME_ACTION_NEXT + || (event != null && event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { listener.onEditorCommit(); diff --git a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml index 060cdce6451..29877bd2aff 100644 --- a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml +++ b/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml @@ -1,11 +1,9 @@ + android:layout_height="match_parent"> - + + android:layout_height="wrap_content" + android:importantForAccessibility="no" /> + android:indeterminate="true" + android:padding="@dimen/margin_large" /> - + android:text="@string/login_magic_links_label" /> - + android:layout_alignParentBottom="true"> - + android:paddingBottom="@dimen/margin_medium_large" + tools:ignore="InconsistentLayout"> - - + + + + + diff --git a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml index 7cf5f68af62..1933c757144 100644 --- a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml +++ b/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml @@ -1,73 +1,77 @@ + android:layout_height="match_parent"> - + + android:layout_marginTop="@dimen/margin_extra_large" + android:gravity="center_horizontal" + android:orientation="vertical"> + android:scaleType="centerInside" + app:srcCompat="@drawable/login_email_alert" /> - + android:text="@string/login_magic_links_sent_label" /> - + android:layout_alignParentBottom="true"> - + android:paddingBottom="@dimen/margin_medium_large" + tools:ignore="InconsistentLayout"> - - + + + + + + diff --git a/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml b/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml index 0f5a6453734..a05807f5a9f 100644 --- a/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml +++ b/libs/login/src/main/res/layout-land/signup_bottom_sheet_dialog.xml @@ -1,55 +1,50 @@ - + android:paddingBottom="@dimen/margin_extra_large"> - - + android:text="@string/signup_terms_of_service_text" /> + android:layout_marginBottom="@dimen/margin_extra_small" + android:orientation="horizontal"> - - + android:text="@string/signup_with_email_button" /> - - + android:text="@string/signup_with_google_button" /> diff --git a/libs/login/src/main/res/layout-land/signup_magic_link.xml b/libs/login/src/main/res/layout-land/signup_magic_link.xml index 1917679299a..290d3e3f026 100644 --- a/libs/login/src/main/res/layout-land/signup_magic_link.xml +++ b/libs/login/src/main/res/layout-land/signup_magic_link.xml @@ -1,71 +1,68 @@ - + android:layout_height="match_parent"> - - + + android:gravity="center_horizontal" + android:orientation="vertical"> - + app:srcCompat="@drawable/login_email_alert" /> - + android:paddingEnd="@dimen/margin_extra_extra_large" + android:paddingRight="@dimen/margin_extra_extra_large" + android:paddingBottom="@dimen/margin_extra_large" + android:text="@string/signup_magic_link_message" /> - + android:layout_height="wrap_content" + android:layout_alignParentBottom="true"> - - + android:layout_alignParentBottom="true" + android:clipToPadding="false" + android:paddingStart="@dimen/margin_small_medium" + android:paddingTop="@dimen/margin_medium_large" + android:paddingEnd="@dimen/margin_medium_large" + android:paddingBottom="@dimen/margin_medium_large" + tools:ignore="InconsistentLayout"> - + + + diff --git a/libs/login/src/main/res/layout/login_2fa_screen.xml b/libs/login/src/main/res/layout/login_2fa_screen.xml index 9d32b8352b4..de326ff7841 100644 --- a/libs/login/src/main/res/layout/login_2fa_screen.xml +++ b/libs/login/src/main/res/layout/login_2fa_screen.xml @@ -9,7 +9,7 @@ android:paddingEnd="@dimen/margin_extra_large" android:layout_marginBottom="@dimen/margin_extra_large"> - + android:layout_height="wrap_content" + app:theme="@style/LoginTheme.EditText"> + android:hint="@string/httpuser" + android:singleLine="true" /> + app:theme="@style/LoginTheme.EditText"> + android:hint="@string/httppassword" + android:inputType="textPassword" /> diff --git a/libs/login/src/main/res/layout/login_alert_site_address_help.xml b/libs/login/src/main/res/layout/login_alert_site_address_help.xml index 933c2ea8f74..2ab69b3277c 100644 --- a/libs/login/src/main/res/layout/login_alert_site_address_help.xml +++ b/libs/login/src/main/res/layout/login_alert_site_address_help.xml @@ -3,24 +3,24 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical" android:gravity="top" + android:orientation="vertical" android:padding="?attr/dialogPreferredPadding"> - + android:text="@string/login_site_address_help_content" /> + android:scaleType="fitCenter" + app:srcCompat="@drawable/login_site_address_help" /> diff --git a/libs/login/src/main/res/layout/login_email_password_screen.xml b/libs/login/src/main/res/layout/login_email_password_screen.xml index ad8b4987b60..8053752cf6e 100644 --- a/libs/login/src/main/res/layout/login_email_password_screen.xml +++ b/libs/login/src/main/res/layout/login_email_password_screen.xml @@ -1,25 +1,25 @@ + android:paddingRight="@dimen/margin_extra_large"> - + app:srcCompat="@drawable/ic_user_grey_24dp" /> + android:focusable="true" + android:orientation="vertical"> - + android:text="@string/email_address" + android:textAlignment="viewStart" /> - + android:textAlignment="viewStart" + tools:text="s@b.com" /> @@ -69,15 +69,12 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/margin_extra_large" android:layout_marginBottom="@dimen/margin_extra_extra_large" + android:gravity="start" android:hint="@string/password" android:importantForAutofill="noExcludeDescendants" android:inputType="textPassword" android:textAlignment="viewStart" - android:gravity="start" app:passwordToggleEnabled="true" - app:passwordToggleTint="@color/login_input_password_icon_color" - app:wpIconDrawable="@drawable/ic_lock_grey_24dp" - tools:ignore="UnusedAttribute" > - + tools:ignore="UnusedAttribute" /> diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index 30dbc62535d..53e8e305001 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -1,116 +1,108 @@ - + android:paddingStart="@dimen/margin_extra_large" + android:paddingEnd="@dimen/margin_extra_large"> - - + android:textAlignment="viewStart" + tools:text="@string/enter_email_wordpress_com" /> - + tools:ignore="UnusedAttribute" /> - - + android:layout_marginBottom="@dimen/margin_medium" + android:gravity="center_vertical" + android:text="@string/alternatively" /> + android:paddingEnd="@dimen/margin_medium" + android:paddingBottom="@dimen/margin_medium" + tools:ignore="RtlSymmetry"> - + android:importantForAccessibility="no" + app:srcCompat="@drawable/ic_google_60dp" /> - - + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:text="@string/login_google_button_suffix" /> + android:paddingEnd="@dimen/margin_medium" + android:paddingBottom="@dimen/margin_medium" + tools:ignore="RtlSymmetry"> - + android:importantForAccessibility="no" + app:srcCompat="@drawable/ic_domains_grey_24dp" /> - - + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:text="@string/enter_site_address_instead" /> diff --git a/libs/login/src/main/res/layout/login_form_screen.xml b/libs/login/src/main/res/layout/login_form_screen.xml index 4ed2340b3d4..0621b1cc49c 100644 --- a/libs/login/src/main/res/layout/login_form_screen.xml +++ b/libs/login/src/main/res/layout/login_form_screen.xml @@ -5,58 +5,64 @@ android:layout_height="match_parent"> + android:layout_above="@+id/bottom_buttons" + android:layout_below="@+id/toolbar_container"> + android:layout_marginBottom="@dimen/margin_extra_large" /> - - - + + - - - + android:paddingBottom="@dimen/margin_medium_large"> + + + + + + diff --git a/libs/login/src/main/res/layout/login_input_row.xml b/libs/login/src/main/res/layout/login_input_row.xml index eb238712df3..d39dcbb868e 100644 --- a/libs/login/src/main/res/layout/login_input_row.xml +++ b/libs/login/src/main/res/layout/login_input_row.xml @@ -1,40 +1,24 @@ - - - - + android:drawablePadding="10dp" + tools:hint="@string/email_address" /> + diff --git a/libs/login/src/main/res/layout/login_magic_link_request_screen.xml b/libs/login/src/main/res/layout/login_magic_link_request_screen.xml index 5b87de6b893..ce7ae44a4c2 100644 --- a/libs/login/src/main/res/layout/login_magic_link_request_screen.xml +++ b/libs/login/src/main/res/layout/login_magic_link_request_screen.xml @@ -1,16 +1,13 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> - + + android:layout_marginTop="@dimen/margin_extra_extra_large" + android:layout_marginBottom="@dimen/margin_extra_large"> + android:layout_height="wrap_content" + android:importantForAccessibility="no" /> + android:padding="@dimen/margin_large" /> - + android:text="@string/login_magic_links_label" /> - + android:text="@string/open_mail" /> - + diff --git a/libs/login/src/main/res/layout/toolbar_login.xml b/libs/login/src/main/res/layout/toolbar_login.xml index bac5435ba1b..695c90671df 100644 --- a/libs/login/src/main/res/layout/toolbar_login.xml +++ b/libs/login/src/main/res/layout/toolbar_login.xml @@ -1,24 +1,23 @@ - + android:layout_height="wrap_content"> - - + + + + + + + diff --git a/libs/login/src/main/res/values/attrs.xml b/libs/login/src/main/res/values/attrs.xml index 3914e5cd5ec..3f5b74b856c 100644 --- a/libs/login/src/main/res/values/attrs.xml +++ b/libs/login/src/main/res/values/attrs.xml @@ -5,13 +5,10 @@ WPLoginInputRow --> - - - diff --git a/libs/login/src/main/res/values/styles.xml b/libs/login/src/main/res/values/styles.xml index c35b06ba84a..31b6b44225c 100644 --- a/libs/login/src/main/res/values/styles.xml +++ b/libs/login/src/main/res/values/styles.xml @@ -1,47 +1,65 @@ - - - + + - - - - - - - - - - - + + From 5cf3d1ef3588c6bdbebbb72f521866eb3a6034ea Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Fri, 17 Apr 2020 00:54:13 -0700 Subject: [PATCH 407/888] Use wrap_content for image width so wider images will scale better --- .../wordpress/android/login/LoginMagicLinkRequestFragment.java | 2 +- .../src/main/res/layout-land/login_magic_link_sent_screen.xml | 2 +- libs/login/src/main/res/layout-land/signup_magic_link.xml | 2 +- libs/login/src/main/res/layout/login_magic_link_sent_screen.xml | 2 +- libs/login/src/main/res/layout/signup_magic_link.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index fd554f05545..bb199bf19c0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -156,7 +156,7 @@ public void onClick(View v) { View avatarContainerView = view.findViewById(R.id.avatar_container); LayoutParams lp = avatarContainerView.getLayoutParams(); - lp.width = getContext().getResources().getDimensionPixelSize(R.dimen.magic_link_sent_illustration_sz); + lp.width = LayoutParams.WRAP_CONTENT; lp.height = getContext().getResources().getDimensionPixelSize(R.dimen.magic_link_sent_illustration_sz); avatarContainerView.setLayoutParams(lp); diff --git a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml index 1933c757144..ebe1186db58 100644 --- a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml +++ b/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml @@ -16,7 +16,7 @@ Date: Mon, 20 Apr 2020 19:09:52 -0300 Subject: [PATCH 408/888] Update LoginEmailFragment so it supports sign-up from login --- .../android/login/LoginEmailFragment.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 5cd2f9b675e..0ff9790be81 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -80,6 +80,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private String mRequestedEmail; private boolean mIsSocialLogin; private Integer mCurrentEmailErrorRes = null; + private boolean mIsSignupFromLoginEnabled = true; protected WPLoginInputRow mEmailInput; protected boolean mHasDismissedEmailHints; @@ -227,7 +228,8 @@ public void onClick(View view) { @Override protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { - if (mLoginListener.getLoginMode() == LoginMode.JETPACK_STATS) { + // Show Sign-Up button if login mode is Jetpack and signup from login is not enabled + if (mLoginListener.getLoginMode() == LoginMode.JETPACK_STATS && !mIsSignupFromLoginEnabled) { secondaryButton.setText(Html.fromHtml(String.format(getResources().getString( R.string.login_email_button_signup), "", ""))); secondaryButton.setOnClickListener(new OnClickListener() { @@ -458,9 +460,13 @@ public void onAvailabilityChecked(OnAvailabilityChecked event) { switch (event.type) { case EMAIL: if (event.isAvailable) { - // email address is available on wpcom, so apparently the user can't login with that one. - ActivityUtils.hideKeyboardForced(mEmailInput); - showEmailError(R.string.email_not_registered_wpcom); + if (mIsSignupFromLoginEnabled) { + mLoginListener.showSignupMagicLink(event.value); + } else { + // email address is available on wpcom, so apparently the user can't login with that one. + ActivityUtils.hideKeyboardForced(mEmailInput); + showEmailError(R.string.email_not_registered_wpcom); + } } else if (mLoginListener != null) { ActivityUtils.hideKeyboardForced(mEmailInput); mLoginListener.gotWpcomEmail(event.value, false); From b3ac2871a0cf0abbce1e49e53f3399573cdea6f7 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Mon, 20 Apr 2020 19:14:16 -0300 Subject: [PATCH 409/888] Add flag to turn the sign-up from login functionality on --- .../wordpress/android/login/LoginEmailFragment.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 0ff9790be81..e0cf4231c22 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -70,6 +70,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private static final int EMAIL_CREDENTIALS_REQUEST_CODE = 25100; private static final String ARG_LOGIN_SITE_URL = "ARG_LOGIN_SITE_URL"; + private static final String ARG_SIGNUP_FROM_LOGIN_ENABLED = "ARG_SIGNUP_FROM_LOGIN_ENABLED"; public static final String TAG = "login_email_fragment_tag"; public static final int MAX_EMAIL_LENGTH = 100; @@ -80,7 +81,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private String mRequestedEmail; private boolean mIsSocialLogin; private Integer mCurrentEmailErrorRes = null; - private boolean mIsSignupFromLoginEnabled = true; + private boolean mIsSignupFromLoginEnabled; protected WPLoginInputRow mEmailInput; protected boolean mHasDismissedEmailHints; @@ -95,6 +96,14 @@ public static LoginEmailFragment newInstance(String url) { return fragment; } + public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled) { + LoginEmailFragment fragment = new LoginEmailFragment(); + Bundle args = new Bundle(); + args.putBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, isSignupFromLoginEnabled); + fragment.setArguments(args); + return fragment; + } + @Override protected @LayoutRes int getContentLayout() { return R.layout.login_email_screen; @@ -286,6 +295,7 @@ public void onCreate(Bundle savedInstanceState) { Bundle args = getArguments(); if (args != null) { mLoginSiteUrl = args.getString(ARG_LOGIN_SITE_URL, ""); + mIsSignupFromLoginEnabled = args.getBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, false); } } From 351b5ab7c0346a526a4a8039859d6511a77e854a Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Tue, 21 Apr 2020 12:18:40 +0200 Subject: [PATCH 410/888] Introduce kotlin to LoginFlow and bump libraries --- libs/login/build.gradle | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 2023cec713d..0810ad8950b 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -5,10 +5,14 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.5.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' +apply plugin: 'kotlin-android-extensions' repositories { google() @@ -31,18 +35,21 @@ android { } dependencies { - implementation ('org.wordpress:utils:1.20.3') { + implementation ('org.wordpress:utils:1.22') { exclude group: "com.android.volley" } - implementation 'androidx.appcompat:appcompat:1.0.2' - implementation 'androidx.vectordrawable:vectordrawable-animated:1.0.0' - implementation 'androidx.media:media:1.0.1' + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0' + implementation 'androidx.media:media:1.1.0' implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'com.google.android.material:material:1.1.0' - api 'com.google.android.gms:play-services-auth:15.0.1' + implementation "androidx.core:core-ktx:1.2.0" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + + api 'com.google.android.gms:play-services-auth:18.0.0' // Share FluxC version from host project if defined, otherwise fallback to default if (project.hasProperty("fluxCVersion")) { @@ -70,9 +77,9 @@ dependencies { lintChecks 'org.wordpress:lint:1.0.1' testImplementation 'junit:junit:4.12' - testImplementation 'org.mockito:mockito-core:2.27.0' - testImplementation 'androidx.arch.core:core-testing:2.0.1' - testImplementation 'org.robolectric:robolectric:4.3' + testImplementation 'org.mockito:mockito-core:2.28.2' + testImplementation 'androidx.arch.core:core-testing:2.1.0' + testImplementation 'org.robolectric:robolectric:4.3.1' testImplementation 'org.assertj:assertj-core:3.11.1' } From 6341698adb95c4c68506e273c50ad5188f394052 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Tue, 21 Apr 2020 14:13:08 +0200 Subject: [PATCH 411/888] Use correct versions to fix build --- libs/login/build.gradle | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 0810ad8950b..f912c7e35d7 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -39,17 +39,17 @@ dependencies { exclude group: "com.android.volley" } - implementation 'androidx.appcompat:appcompat:1.1.0' + implementation "androidx.appcompat:appcompat:$appCompatVersion" implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0' implementation 'androidx.media:media:1.1.0' implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'com.google.android.material:material:1.1.0' - implementation "androidx.core:core-ktx:1.2.0" + implementation "androidx.core:core-ktx:$kotlin_ktx_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - api 'com.google.android.gms:play-services-auth:18.0.0' + api 'com.google.android.gms:play-services-auth:15.0.1' // Share FluxC version from host project if defined, otherwise fallback to default if (project.hasProperty("fluxCVersion")) { @@ -65,14 +65,14 @@ dependencies { } implementation 'com.github.bumptech.glide:glide:4.10.0' - annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0' + kapt 'com.github.bumptech.glide:compiler:4.10.0' // Dagger - implementation 'com.google.dagger:dagger:2.22.1' - annotationProcessor 'com.google.dagger:dagger-compiler:2.22.1' + implementation "com.google.dagger:dagger:$daggerVersion" + kapt "com.google.dagger:dagger-compiler:$daggerVersion" compileOnly 'org.glassfish:javax.annotation:10.0-b28' - implementation 'com.google.dagger:dagger-android-support:2.22.1' - annotationProcessor 'com.google.dagger:dagger-android-processor:2.22.1' + implementation "com.google.dagger:dagger-android-support:$daggerVersion" + kapt "com.google.dagger:dagger-android-processor:$daggerVersion" lintChecks 'org.wordpress:lint:1.0.1' From 7fdb9aa446056f80d7087c430157eca8d3b66594 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 21 Apr 2020 19:17:25 -0300 Subject: [PATCH 412/888] Update LoginGoogleFragment so it supports sign-up from login --- .../android/login/GoogleFragment.java | 12 ++++++++ .../android/login/LoginGoogleFragment.java | 30 +++++++++++++++---- .../android/login/SignupGoogleFragment.java | 15 ++-------- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/GoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/GoogleFragment.java index 1d41c8d4559..dad815405aa 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/GoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/GoogleFragment.java @@ -22,6 +22,9 @@ import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import javax.inject.Inject; import static android.app.Activity.RESULT_OK; @@ -246,4 +249,13 @@ public void onActivityResult(int request, int result, Intent data) { break; } } + + // Remove scale from photo URL path string. Current URL matches /s96-c, which returns a 96 x 96 + // pixel image. Removing /s96-c from the string returns a 512 x 512 pixel image. Using regular + // expressions may help if the photo URL scale value in the returned path changes. + protected String removeScaleFromGooglePhotoUrl(String photoUrl) { + Pattern pattern = Pattern.compile("(/s[0-9]+-c)"); + Matcher matcher = pattern.matcher(photoUrl); + return matcher.find() ? photoUrl.replace(matcher.group(1), "") : photoUrl; + } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index 112bef05a8a..c543ec2b062 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -18,14 +18,15 @@ import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; -import dagger.android.support.AndroidSupportInjection; - import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; +import dagger.android.support.AndroidSupportInjection; + public class LoginGoogleFragment extends GoogleFragment { private static final int REQUEST_LOGIN = 1001; private boolean mLoginRequested = false; + private boolean mIsSignupFromLoginEnabled = true; public static final String TAG = "login_google_fragment_tag"; @@ -64,9 +65,12 @@ public void onActivityResult(int request, int result, Intent data) { GoogleSignInAccount account = loginResult.getSignInAccount(); if (account != null) { + mDisplayName = account.getDisplayName() != null ? account.getDisplayName() : ""; mGoogleEmail = account.getEmail() != null ? account.getEmail() : ""; mGoogleListener.onGoogleEmailSelected(mGoogleEmail); mIdToken = account.getIdToken() != null ? account.getIdToken() : ""; + mPhotoUrl = removeScaleFromGooglePhotoUrl( + account.getPhotoUrl() != null ? account.getPhotoUrl().toString() : ""); } AppLog.d(T.MAIN, @@ -155,6 +159,12 @@ public void onAuthenticationChanged(OnAuthenticationChanged event) { event.error.type.toString(), event.error.message); showError(getString(R.string.login_error_generic)); + } else if (event.createdAccount) { + AppLog.d(T.MAIN, + "GOOGLE SIGNUP: onAuthenticationChanged - new wordpress account created"); + mAnalyticsListener.trackCreatedAccount(event.userName, mGoogleEmail); + mAnalyticsListener.trackAnalyticsSignIn(true); + mGoogleListener.onGoogleSignupFinished(mDisplayName, mGoogleEmail, mPhotoUrl, event.userName); } else { AppLog.d(T.MAIN, "GOOGLE LOGIN: onAuthenticationChanged - success"); AppLog.i(T.NUX, "LoginGoogleFragment.onAuthenticationChanged: " + event.toString()); @@ -184,12 +194,19 @@ public void onSocialChanged(OnSocialChanged event) { AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - wordpress acount exists but not connected"); mAnalyticsListener.trackSocialAccountsNeedConnecting(); mLoginListener.loginViaSocialAccount(mGoogleEmail, mIdToken, SERVICE_TYPE_GOOGLE, true); + finishFlow(); break; // WordPress account does not exist with input email address. case UNKNOWN_USER: - AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - wordpress acount doesn't exist"); - mAnalyticsListener.trackSocialErrorUnknownUser(); - showError(getString(R.string.login_error_email_not_found_v2)); + if (mIsSignupFromLoginEnabled) { + PushSocialPayload payload = new PushSocialPayload(mIdToken, SERVICE_TYPE_GOOGLE); + AppLog.d(T.MAIN, "GOOGLE SIGNUP: sign up result returned - dispatching SocialSignupAction"); + mDispatcher.dispatch(AccountActionBuilder.newPushSocialSignupAction(payload)); + } else { + AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - wordpress acount doesn't exist"); + mAnalyticsListener.trackSocialErrorUnknownUser(); + showError(getString(R.string.login_error_email_not_found_v2)); + } break; // Too many attempts on sending SMS verification code. The user has to wait before they try again case SMS_CODE_THROTTLED: @@ -209,10 +226,11 @@ public void onSocialChanged(OnSocialChanged event) { AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - needs 2fa"); mLoginListener.needs2faSocial(mGoogleEmail, event.userId, event.nonceAuthenticator, event.nonceBackup, event.nonceSms); + finishFlow(); } else { AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - success"); mGoogleListener.onGoogleLoginFinished(); + finishFlow(); } - finishFlow(); } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java index 94e30dcb158..4ea231d94e6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java @@ -23,14 +23,12 @@ import org.wordpress.android.util.AppLog.T; import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import dagger.android.support.AndroidSupportInjection; import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; +import dagger.android.support.AndroidSupportInjection; + public class SignupGoogleFragment extends GoogleFragment { private static final String OLD_SITES_IDS = "old_sites_ids"; private static final String SIGN_UP_REQUESTED = "sign_up_requested"; @@ -183,15 +181,6 @@ private void dismissProgressDialog() { } } - // Remove scale from photo URL path string. Current URL matches /s96-c, which returns a 96 x 96 - // pixel image. Removing /s96-c from the string returns a 512 x 512 pixel image. Using regular - // expressions may help if the photo URL scale value in the returned path changes. - private String removeScaleFromGooglePhotoUrl(String photoUrl) { - Pattern pattern = Pattern.compile("(/s[0-9]+-c)"); - Matcher matcher = pattern.matcher(photoUrl); - return matcher.find() ? photoUrl.replace(matcher.group(1), "") : photoUrl; - } - @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onAuthenticationChanged(OnAuthenticationChanged event) { From 1de13e012df6a2011087b2c78524b37432a33f5b Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 21 Apr 2020 20:28:10 -0300 Subject: [PATCH 413/888] Add loading dialog to LoginGoogleFragment --- .../android/login/LoginGoogleFragment.java | 18 ++++++++++++++++++ libs/login/src/main/res/values/strings.xml | 1 + 2 files changed, 19 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index c543ec2b062..edddae60f32 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -1,5 +1,6 @@ package org.wordpress.android.login; +import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; @@ -27,15 +28,26 @@ public class LoginGoogleFragment extends GoogleFragment { private static final int REQUEST_LOGIN = 1001; private boolean mLoginRequested = false; private boolean mIsSignupFromLoginEnabled = true; + private ProgressDialog mProgressDialog; public static final String TAG = "login_google_fragment_tag"; @Override public void onAttach(Context context) { AndroidSupportInjection.inject(this); + if (mIsSignupFromLoginEnabled) { + mProgressDialog = ProgressDialog.show( + getActivity(), null, getString(R.string.signin_with_google_progress), true, false, null); + } super.onAttach(context); } + @Override + public void onDetach() { + dismissProgressDialog(); + super.onDetach(); + } + @Override protected void startFlow() { if (!mLoginRequested) { @@ -233,4 +245,10 @@ public void onSocialChanged(OnSocialChanged event) { finishFlow(); } } + + private void dismissProgressDialog() { + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.dismiss(); + } + } } diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 0ba710774ac..4999ffaef73 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -80,6 +80,7 @@ Sign Up with Email Sign Up with Google Signing up with Google… + Signing in with Google… Google took too long to respond. You may need to wait until you have a stronger internet connection. From ba4bc3abd234c2bf6459e163a72f7e465aa46982 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 21 Apr 2020 20:40:38 -0300 Subject: [PATCH 414/888] Add flag to turn the sign-up from login functionality on --- .../android/login/LoginGoogleFragment.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index edddae60f32..3c0d642efac 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -3,6 +3,7 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; +import android.os.Bundle; import com.google.android.gms.auth.api.Auth; import com.google.android.gms.auth.api.signin.GoogleSignInAccount; @@ -25,27 +26,45 @@ import dagger.android.support.AndroidSupportInjection; public class LoginGoogleFragment extends GoogleFragment { + private static final String ARG_SIGNUP_FROM_LOGIN_ENABLED = "ARG_SIGNUP_FROM_LOGIN_ENABLED"; private static final int REQUEST_LOGIN = 1001; private boolean mLoginRequested = false; - private boolean mIsSignupFromLoginEnabled = true; + private boolean mIsSignupFromLoginEnabled; private ProgressDialog mProgressDialog; public static final String TAG = "login_google_fragment_tag"; + public static LoginGoogleFragment newInstance(boolean isSignupFromLoginEnabled) { + LoginGoogleFragment fragment = new LoginGoogleFragment(); + Bundle args = new Bundle(); + args.putBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, isSignupFromLoginEnabled); + fragment.setArguments(args); + return fragment; + } + @Override public void onAttach(Context context) { AndroidSupportInjection.inject(this); + super.onAttach(context); + } + + @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Bundle args = getArguments(); + if (args != null) { + mIsSignupFromLoginEnabled = args.getBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, false); + } + if (mIsSignupFromLoginEnabled) { mProgressDialog = ProgressDialog.show( getActivity(), null, getString(R.string.signin_with_google_progress), true, false, null); } - super.onAttach(context); } - @Override - public void onDetach() { + @Override public void onDestroy() { dismissProgressDialog(); - super.onDetach(); + super.onDestroy(); } @Override From a27408168882ae094bbea4db5727a74fda5130db Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 21 Apr 2020 20:42:01 -0300 Subject: [PATCH 415/888] Update log messages for sign-up from login functionality --- .../org/wordpress/android/login/LoginGoogleFragment.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index 3c0d642efac..fbbc575d368 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -192,7 +192,7 @@ public void onAuthenticationChanged(OnAuthenticationChanged event) { showError(getString(R.string.login_error_generic)); } else if (event.createdAccount) { AppLog.d(T.MAIN, - "GOOGLE SIGNUP: onAuthenticationChanged - new wordpress account created"); + "GOOGLE LOGIN: onAuthenticationChanged - new wordpress account created"); mAnalyticsListener.trackCreatedAccount(event.userName, mGoogleEmail); mAnalyticsListener.trackAnalyticsSignIn(true); mGoogleListener.onGoogleSignupFinished(mDisplayName, mGoogleEmail, mPhotoUrl, event.userName); @@ -231,10 +231,12 @@ public void onSocialChanged(OnSocialChanged event) { case UNKNOWN_USER: if (mIsSignupFromLoginEnabled) { PushSocialPayload payload = new PushSocialPayload(mIdToken, SERVICE_TYPE_GOOGLE); - AppLog.d(T.MAIN, "GOOGLE SIGNUP: sign up result returned - dispatching SocialSignupAction"); + AppLog.d(T.MAIN, + "GOOGLE LOGIN: onSocialChanged - wordpress account doesn't exist - dispatching " + + "SocialSignupAction"); mDispatcher.dispatch(AccountActionBuilder.newPushSocialSignupAction(payload)); } else { - AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - wordpress acount doesn't exist"); + AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - wordpress account doesn't exist"); mAnalyticsListener.trackSocialErrorUnknownUser(); showError(getString(R.string.login_error_email_not_found_v2)); } From de8d02bf69d67fecdfa333e9e0ad652d8038f2ee Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 21 Apr 2020 21:37:43 -0300 Subject: [PATCH 416/888] Move progress dialog to better handle configuration changes --- .../org/wordpress/android/login/LoginGoogleFragment.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index fbbc575d368..d46214c82b5 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -55,16 +55,19 @@ public void onAttach(Context context) { if (args != null) { mIsSignupFromLoginEnabled = args.getBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, false); } + } + @Override public void onStart() { + super.onStart(); if (mIsSignupFromLoginEnabled) { mProgressDialog = ProgressDialog.show( getActivity(), null, getString(R.string.signin_with_google_progress), true, false, null); } } - @Override public void onDestroy() { + @Override public void onStop() { dismissProgressDialog(); - super.onDestroy(); + super.onStop(); } @Override From e14e00084f685308f54a0071c1c959522674cde9 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Wed, 22 Apr 2020 09:55:29 +0200 Subject: [PATCH 417/888] Add library version locally to the login library --- libs/login/build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index f912c7e35d7..9f2f4a3c3ec 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -1,4 +1,10 @@ buildscript { + ext { + kotlin_version = '1.3.61' + kotlin_ktx_version = '1.2.0' + daggerVersion = '2.22.1' + appCompatVersion = '1.0.2' + } repositories { google() jcenter() From c4c105b65d1b3cdda945a1c74543c685c65040ca Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 24 Apr 2020 16:13:44 -0300 Subject: [PATCH 418/888] Move @Override annotation to conform with the current code style --- .../org/wordpress/android/login/LoginGoogleFragment.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index d46214c82b5..99a07dd7532 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -48,7 +48,8 @@ public void onAttach(Context context) { super.onAttach(context); } - @Override public void onCreate(Bundle savedInstanceState) { + @Override + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle args = getArguments(); @@ -57,7 +58,8 @@ public void onAttach(Context context) { } } - @Override public void onStart() { + @Override + public void onStart() { super.onStart(); if (mIsSignupFromLoginEnabled) { mProgressDialog = ProgressDialog.show( @@ -65,7 +67,8 @@ public void onAttach(Context context) { } } - @Override public void onStop() { + @Override + public void onStop() { dismissProgressDialog(); super.onStop(); } From 1d30f97271f6118e40fba874cfed22a66523b488 Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Mon, 27 Apr 2020 21:22:27 -0700 Subject: [PATCH 419/888] Add title to the layout override for the site help dialog --- .../android/login/LoginSiteAddressHelpDialogFragment.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java index c9a36a95d88..b85d4dbd3a4 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressHelpDialogFragment.java @@ -48,7 +48,11 @@ public void onAttach(Context context) { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder alert = new MaterialAlertDialogBuilder(getActivity()); - alert.setTitle(R.string.login_site_address_help_title); + if (mLoginListener.getLoginMode() != LoginMode.WOO_LOGIN_MODE) { + // Only set the title if not the woo app, since the woo app specifies an override + // layout that includes the title. + alert.setTitle(R.string.login_site_address_help_title); + } //noinspection InflateParams alert.setView(getActivity().getLayoutInflater().inflate(R.layout.login_alert_site_address_help, null)); From d5e9b8c7d4b8fb36eb21c035c059a0b8396d17ad Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Wed, 29 Apr 2020 18:45:03 -0300 Subject: [PATCH 420/888] Add ability to disable login via site address from the email screen --- .../org/wordpress/android/login/LoginEmailFragment.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index e0cf4231c22..c656e2ffd0c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -71,6 +71,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private static final String ARG_LOGIN_SITE_URL = "ARG_LOGIN_SITE_URL"; private static final String ARG_SIGNUP_FROM_LOGIN_ENABLED = "ARG_SIGNUP_FROM_LOGIN_ENABLED"; + private static final String ARG_SITE_LOGIN_ENABLED = "ARG_SITE_LOGIN_ENABLED"; public static final String TAG = "login_email_fragment_tag"; public static final int MAX_EMAIL_LENGTH = 100; @@ -82,6 +83,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private boolean mIsSocialLogin; private Integer mCurrentEmailErrorRes = null; private boolean mIsSignupFromLoginEnabled; + private boolean mIsSiteLoginEnabled; protected WPLoginInputRow mEmailInput; protected boolean mHasDismissedEmailHints; @@ -96,10 +98,11 @@ public static LoginEmailFragment newInstance(String url) { return fragment; } - public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled) { + public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled) { LoginEmailFragment fragment = new LoginEmailFragment(); Bundle args = new Bundle(); args.putBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, isSignupFromLoginEnabled); + args.putBoolean(ARG_SITE_LOGIN_ENABLED, isSiteLoginEnabled); fragment.setArguments(args); return fragment; } @@ -221,6 +224,7 @@ public void onClick(View view) { case FULL: case WPCOM_LOGIN_ONLY: case SHARE_INTENT: + siteLoginButton.setVisibility(mIsSiteLoginEnabled ? View.VISIBLE : View.GONE); siteLoginButtonIcon.setImageResource(R.drawable.ic_domains_grey_24dp); siteLoginButtonText.setText(R.string.enter_site_address_instead); break; @@ -296,6 +300,7 @@ public void onCreate(Bundle savedInstanceState) { if (args != null) { mLoginSiteUrl = args.getString(ARG_LOGIN_SITE_URL, ""); mIsSignupFromLoginEnabled = args.getBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, false); + mIsSiteLoginEnabled = args.getBoolean(ARG_SITE_LOGIN_ENABLED, true); } } From 8ff96c1970e243c79335d0b548ac412ff3152869 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Wed, 29 Apr 2020 18:46:42 -0300 Subject: [PATCH 421/888] Add ability to enable login via site address from the prologue screen --- libs/login/src/main/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 4999ffaef73..fe07fe00057 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -81,6 +81,8 @@ Sign Up with Google Signing up with Google… Signing in with Google… + Continue with WordPress.com + Enter your site address Google took too long to respond. You may need to wait until you have a stronger internet connection. From 772f4f8b1672ff8035bcbe0b97e2e235d660a44c Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 8 May 2020 22:33:04 -0300 Subject: [PATCH 422/888] Remove unused strings from the login library --- libs/login/src/main/res/values/strings.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index fe07fe00057..c29307aa80c 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -10,11 +10,6 @@ Password Help Log In - Publish from the park. Blog from the bus. Comment from the café. WordPress goes where you go. - Watch readers from around the world read and interact with your site — in realtime. - Catch up with your favorite sites and join the conversation anywhere, any time. - 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 Log in with your %1$s site credentials From ca486af96042c96f85591bbd0dbab486694ae4f9 Mon Sep 17 00:00:00 2001 From: Siobhan Bamber Date: Wed, 13 May 2020 08:45:25 +0100 Subject: [PATCH 423/888] Gradle updates. --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 9051314a8ed..622385173fa 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -4,7 +4,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:3.6.3' } } From a08e6c41fd8454ac39fee1ea8a4552628872fa52 Mon Sep 17 00:00:00 2001 From: Siobhan Bamber Date: Thu, 14 May 2020 08:51:18 +0100 Subject: [PATCH 424/888] Revert changes to gradle Revert changes to gradle that were made in previous commit. --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 622385173fa..9051314a8ed 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -4,7 +4,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.3' + classpath 'com.android.tools.build:gradle:3.5.3' } } From da593e947f9ad437e2375583a9b5238026cfe42b Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Thu, 14 May 2020 12:26:19 -0300 Subject: [PATCH 425/888] fixed lint error and replaced all observers owner parameter with viewLifecycleOwner --- .../org/wordpress/android/login/LoginSiteAddressFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index a1b47247241..e6b653cb69d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -141,12 +141,12 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { mLoginSiteAddressValidator = new LoginSiteAddressValidator(); - mLoginSiteAddressValidator.getIsValid().observe(this, new Observer() { + mLoginSiteAddressValidator.getIsValid().observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(Boolean enabled) { getPrimaryButton().setEnabled(enabled); } }); - mLoginSiteAddressValidator.getErrorMessageResId().observe(this, new Observer() { + mLoginSiteAddressValidator.getErrorMessageResId().observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(Integer resId) { if (resId != null) { showError(resId); From 82c511b9297e48c534bd7f9e41d256757b7ebeb4 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 14 May 2020 13:11:20 -0300 Subject: [PATCH 426/888] Update signup epilogue primary button string --- libs/login/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index c29307aa80c..ea5b31567bc 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -36,6 +36,7 @@ Connect Another Site Connect Site Continue + Done Already logged in to WordPress.com \@%s Enter the address of the WordPress site you\'d like to connect. From ecb06a568525db1bee6b03fb2378ac4779a97d16 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Mon, 18 May 2020 13:14:17 -0300 Subject: [PATCH 427/888] Update login epilogue secondary button strings --- libs/login/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index ea5b31567bc..52d1a3ae68f 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -33,8 +33,8 @@ Currently unavailable. Please enter your password Enter your WordPress.com password. To proceed with this Google account, please provide the matching WordPress.com password. This will be asked only once. - Connect Another Site - Connect Site + Connect another site + Connect a site Continue Done Already logged in to WordPress.com From 22fb6867a4b3fe72ecc855a269ee4b22b4c1ce3e Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 19 May 2020 12:35:17 -0300 Subject: [PATCH 428/888] Remove unused resources --- libs/login/src/main/res/values/strings.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 52d1a3ae68f..35a838c0f96 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -38,7 +38,6 @@ Continue Done Already logged in to WordPress.com - \@%s Enter the address of the WordPress site you\'d like to connect. Enter the address of your WordPress site you\'d like to share the content to. Site address @@ -56,7 +55,6 @@ Please enter a verification code Don\'t have an account? %1$sSign up%2$s Can\'t detect your email client app - Logged in as Log in with Google. Close There\'s no WordPress.com account matching this Google account. From 69824a2c21c7aee0a429224ec63e7dda075d0ca2 Mon Sep 17 00:00:00 2001 From: Marko Savic Date: Thu, 21 May 2020 15:01:53 +0200 Subject: [PATCH 429/888] Fix wrong password icon --- .../drawable-xhdpi/ic_password_visibility.png | Bin 970 -> 593 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/libs/login/src/main/res/drawable-xhdpi/ic_password_visibility.png b/libs/login/src/main/res/drawable-xhdpi/ic_password_visibility.png index 62f5d6a3433050d098a93cc61bfc3526de0b03a5..1f7b4cc8f24b2f7632cd7568f236c7d765d8e352 100644 GIT binary patch delta 579 zcmV-J0=)go2hjwO8Gi%-008|9F$@3z0vJg|K~#7F?bb_6e03NH@XrJ~LR!*AWX1;F zMzslwc1a3CJMn_+K&`baZsw4+G|`+jF7f|J$m#uxH(zXMf$%6Uz48NaAwiTkq)8 zmZyBEB59(oe4t-Ta^Ci*q=mY)Ag4(MUrE}iFAZwKYkmvDH5(?Cbm>wuX;Uqj`qitl zdDFi^@KXh8MLWS{)r1TauG0~9i(-`3ga36*%uD_Xo@r5*a*(KaAwKgzg^L5wW7V;m znj9G5~oCe+qhc*Fur@<-d25g7f*MFsa5?-_-py(v^=L>*Rc+ozR zrq7ST;Aa5xmL009I%KPcad-5LS!;HkyYk;{T{-uKH8Y;p(a~`qJOBkY@4uS@ R#NYq`002ovPDHLkV1ilQ7bgG! delta 959 zcmV;w13>)I1j+}H8Gi-<00374`G)`i02y>eSaefwW^{L9a%BKPWN%_+AW3auXJt}l zVPtu6$z?nM00V4EL_t(|+T>b|v70aqPP#zZpmc)A2yBpS@YtYqf|3bnCrB~@$poYm zkW4^20oj0xt4Up*B+KBupR4b5TmrIX=|g{Jv3TcW8ET@w?|)Oc4Dy@K%>P%Q4OnIOXpN^pEvHGKSTRQ| zSgtite2DNRTC4*qG(tNzQ<%BzQHB&e0&4IA!~cQTzzS++uR#dkJzR#}IK%E9ye6?>5L9E>=Su@rGNc&vK-y6-I zK^xaGAQ>wS*DqEQhsSrIUnZG5qqVni$tGJtsr_z-Cx7Xs#LYxyY1Gs_AFMf6iexM@ zc$darxVK`n%0JfJDCb>KLCa3e5;Ahv+*WqulbUYRx43Y`8B?z#9k z!uxkb1=M{5whKHsprC=#VG4{4ly=4iQxH3mwFPAw$4jMwQ9T1jTl@ms@xpfFqXi=T z@|qo=XMezGKLbV=^!rFSn23Xr2FsD6mYobELUGhw31xwhSiVV)z$3@H2TZI)90xcd zc2k5HT(KjnOE5~6P`q#8COmVTD8#cvvyug$6eze+9;0To*|`!rAs{ur-pE?761-b2 zx>1k(CSuCMv7ShLawGISb)R&j7u){_aET*)4u2-9pFLpo%)tlAcHye9%ri%+glALp zJJ(v!;;kGRb1IsKU{(oXL7-Je^^AFrf)5XM)ar{p^Yx5)UrJ$quCmJo%fzCRk$DQw z{H7uxka!eK5t@JN=vrhh*Vi%LMHGU952`shcbub|WG(Qv+M>Q>gkWLB!AHn4?cP(y zm4B_sjb}d9RO%r_#lgqoT`Owdt~xJ~S8LJH!zpHTEjppO z?004$HFq6C#ER~-Sm{xn@u2N>L5OC8a_o@=ZR<-19E=dTa^9Rf9}9NCp*UhHeBtA8 z$6fFvCXbiT8>f!*<#305go|y3IFKlhkT`M%g5Jlh|JOk`lX|?rPYpPDE&l!3!# Date: Fri, 22 May 2020 11:52:31 +0200 Subject: [PATCH 430/888] Replace wrong icon with the right one --- .../drawable-xhdpi/ic_password_visibility.png | Bin 970 -> 593 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/libs/login/src/main/res/drawable-xhdpi/ic_password_visibility.png b/libs/login/src/main/res/drawable-xhdpi/ic_password_visibility.png index 62f5d6a3433050d098a93cc61bfc3526de0b03a5..1f7b4cc8f24b2f7632cd7568f236c7d765d8e352 100644 GIT binary patch delta 579 zcmV-J0=)go2hjwO8Gi%-008|9F$@3z0vJg|K~#7F?bb_6e03NH@XrJ~LR!*AWX1;F zMzslwc1a3CJMn_+K&`baZsw4+G|`+jF7f|J$m#uxH(zXMf$%6Uz48NaAwiTkq)8 zmZyBEB59(oe4t-Ta^Ci*q=mY)Ag4(MUrE}iFAZwKYkmvDH5(?Cbm>wuX;Uqj`qitl zdDFi^@KXh8MLWS{)r1TauG0~9i(-`3ga36*%uD_Xo@r5*a*(KaAwKgzg^L5wW7V;m znj9G5~oCe+qhc*Fur@<-d25g7f*MFsa5?-_-py(v^=L>*Rc+ozR zrq7ST;Aa5xmL009I%KPcad-5LS!;HkyYk;{T{-uKH8Y;p(a~`qJOBkY@4uS@ R#NYq`002ovPDHLkV1ilQ7bgG! delta 959 zcmV;w13>)I1j+}H8Gi-<00374`G)`i02y>eSaefwW^{L9a%BKPWN%_+AW3auXJt}l zVPtu6$z?nM00V4EL_t(|+T>b|v70aqPP#zZpmc)A2yBpS@YtYqf|3bnCrB~@$poYm zkW4^20oj0xt4Up*B+KBupR4b5TmrIX=|g{Jv3TcW8ET@w?|)Oc4Dy@K%>P%Q4OnIOXpN^pEvHGKSTRQ| zSgtite2DNRTC4*qG(tNzQ<%BzQHB&e0&4IA!~cQTzzS++uR#dkJzR#}IK%E9ye6?>5L9E>=Su@rGNc&vK-y6-I zK^xaGAQ>wS*DqEQhsSrIUnZG5qqVni$tGJtsr_z-Cx7Xs#LYxyY1Gs_AFMf6iexM@ zc$darxVK`n%0JfJDCb>KLCa3e5;Ahv+*WqulbUYRx43Y`8B?z#9k z!uxkb1=M{5whKHsprC=#VG4{4ly=4iQxH3mwFPAw$4jMwQ9T1jTl@ms@xpfFqXi=T z@|qo=XMezGKLbV=^!rFSn23Xr2FsD6mYobELUGhw31xwhSiVV)z$3@H2TZI)90xcd zc2k5HT(KjnOE5~6P`q#8COmVTD8#cvvyug$6eze+9;0To*|`!rAs{ur-pE?761-b2 zx>1k(CSuCMv7ShLawGISb)R&j7u){_aET*)4u2-9pFLpo%)tlAcHye9%ri%+glALp zJJ(v!;;kGRb1IsKU{(oXL7-Je^^AFrf)5XM)ar{p^Yx5)UrJ$quCmJo%fzCRk$DQw z{H7uxka!eK5t@JN=vrhh*Vi%LMHGU952`shcbub|WG(Qv+M>Q>gkWLB!AHn4?cP(y zm4B_sjb}d9RO%r_#lgqoT`Owdt~xJ~S8LJH!zpHTEjppO z?004$HFq6C#ER~-Sm{xn@u2N>L5OC8a_o@=ZR<-19E=dTa^9Rf9}9NCp*UhHeBtA8 z$6fFvCXbiT8>f!*<#305go|y3IFKlhkT`M%g5Jlh|JOk`lX|?rPYpPDE&l!3!# Date: Fri, 22 May 2020 10:38:42 -0300 Subject: [PATCH 431/888] using getViewLifecycleOwner() for observers --- .../org/wordpress/android/login/LoginSiteAddressFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index a1b47247241..e6b653cb69d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -141,12 +141,12 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { mLoginSiteAddressValidator = new LoginSiteAddressValidator(); - mLoginSiteAddressValidator.getIsValid().observe(this, new Observer() { + mLoginSiteAddressValidator.getIsValid().observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(Boolean enabled) { getPrimaryButton().setEnabled(enabled); } }); - mLoginSiteAddressValidator.getErrorMessageResId().observe(this, new Observer() { + mLoginSiteAddressValidator.getErrorMessageResId().observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(Integer resId) { if (resId != null) { showError(resId); From 2f742fdd04e899ede71b38bc20af672fa684a6a4 Mon Sep 17 00:00:00 2001 From: Marko Savic Date: Fri, 22 May 2020 15:39:48 +0200 Subject: [PATCH 432/888] Set password icon programmatically --- .../org/wordpress/android/login/widgets/WPLoginInputRow.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java index c17d99bb528..42f02d84942 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java @@ -79,8 +79,8 @@ private void init(Context context, AttributeSet attrs) { mEditText.setHintTextColor(getResources().getColor(android.R.color.transparent)); } if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleEnabled)) { - mTextInputLayout.setPasswordVisibilityToggleEnabled( - a.getBoolean(R.styleable.wpLoginInputRow_passwordToggleEnabled, false)); + mTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_PASSWORD_TOGGLE); + mTextInputLayout.setEndIconDrawable(R.drawable.selector_password_visibility); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { From 6829ed25faf9b47737f330fe1e4a1251d8e2d46a Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Fri, 22 May 2020 19:34:39 -0600 Subject: [PATCH 433/888] Revert unintentional change during merge Not even sure why this change would've merged in since it's not a change on my end and it wouldn't have come from the other end, but I've reverted it. --- .../drawable-xhdpi/ic_password_visibility.png | Bin 970 -> 593 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/libs/login/src/main/res/drawable-xhdpi/ic_password_visibility.png b/libs/login/src/main/res/drawable-xhdpi/ic_password_visibility.png index 62f5d6a3433050d098a93cc61bfc3526de0b03a5..1f7b4cc8f24b2f7632cd7568f236c7d765d8e352 100644 GIT binary patch delta 579 zcmV-J0=)go2hjwO8Gi%-008|9F$@3z0vJg|K~#7F?bb_6e03NH@XrJ~LR!*AWX1;F zMzslwc1a3CJMn_+K&`baZsw4+G|`+jF7f|J$m#uxH(zXMf$%6Uz48NaAwiTkq)8 zmZyBEB59(oe4t-Ta^Ci*q=mY)Ag4(MUrE}iFAZwKYkmvDH5(?Cbm>wuX;Uqj`qitl zdDFi^@KXh8MLWS{)r1TauG0~9i(-`3ga36*%uD_Xo@r5*a*(KaAwKgzg^L5wW7V;m znj9G5~oCe+qhc*Fur@<-d25g7f*MFsa5?-_-py(v^=L>*Rc+ozR zrq7ST;Aa5xmL009I%KPcad-5LS!;HkyYk;{T{-uKH8Y;p(a~`qJOBkY@4uS@ R#NYq`002ovPDHLkV1ilQ7bgG! delta 959 zcmV;w13>)I1j+}H8Gi-<00374`G)`i02y>eSaefwW^{L9a%BKPWN%_+AW3auXJt}l zVPtu6$z?nM00V4EL_t(|+T>b|v70aqPP#zZpmc)A2yBpS@YtYqf|3bnCrB~@$poYm zkW4^20oj0xt4Up*B+KBupR4b5TmrIX=|g{Jv3TcW8ET@w?|)Oc4Dy@K%>P%Q4OnIOXpN^pEvHGKSTRQ| zSgtite2DNRTC4*qG(tNzQ<%BzQHB&e0&4IA!~cQTzzS++uR#dkJzR#}IK%E9ye6?>5L9E>=Su@rGNc&vK-y6-I zK^xaGAQ>wS*DqEQhsSrIUnZG5qqVni$tGJtsr_z-Cx7Xs#LYxyY1Gs_AFMf6iexM@ zc$darxVK`n%0JfJDCb>KLCa3e5;Ahv+*WqulbUYRx43Y`8B?z#9k z!uxkb1=M{5whKHsprC=#VG4{4ly=4iQxH3mwFPAw$4jMwQ9T1jTl@ms@xpfFqXi=T z@|qo=XMezGKLbV=^!rFSn23Xr2FsD6mYobELUGhw31xwhSiVV)z$3@H2TZI)90xcd zc2k5HT(KjnOE5~6P`q#8COmVTD8#cvvyug$6eze+9;0To*|`!rAs{ur-pE?761-b2 zx>1k(CSuCMv7ShLawGISb)R&j7u){_aET*)4u2-9pFLpo%)tlAcHye9%ri%+glALp zJJ(v!;;kGRb1IsKU{(oXL7-Je^^AFrf)5XM)ar{p^Yx5)UrJ$quCmJo%fzCRk$DQw z{H7uxka!eK5t@JN=vrhh*Vi%LMHGU952`shcbub|WG(Qv+M>Q>gkWLB!AHn4?cP(y zm4B_sjb}d9RO%r_#lgqoT`Owdt~xJ~S8LJH!zpHTEjppO z?004$HFq6C#ER~-Sm{xn@u2N>L5OC8a_o@=ZR<-19E=dTa^9Rf9}9NCp*UhHeBtA8 z$6fFvCXbiT8>f!*<#305go|y3IFKlhkT`M%g5Jlh|JOk`lX|?rPYpPDE&l!3!# Date: Tue, 26 May 2020 12:57:56 +0200 Subject: [PATCH 434/888] Fix password drawable --- .../org/wordpress/android/login/widgets/WPLoginInputRow.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java index c17d99bb528..42f02d84942 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java +++ b/libs/login/src/main/java/org/wordpress/android/login/widgets/WPLoginInputRow.java @@ -79,8 +79,8 @@ private void init(Context context, AttributeSet attrs) { mEditText.setHintTextColor(getResources().getColor(android.R.color.transparent)); } if (a.hasValue(R.styleable.wpLoginInputRow_passwordToggleEnabled)) { - mTextInputLayout.setPasswordVisibilityToggleEnabled( - a.getBoolean(R.styleable.wpLoginInputRow_passwordToggleEnabled, false)); + mTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_PASSWORD_TOGGLE); + mTextInputLayout.setEndIconDrawable(R.drawable.selector_password_visibility); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { From 3a53fae3505fee1b3c3780a4d894cc8a115019e9 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 21 May 2020 15:27:03 -0300 Subject: [PATCH 435/888] Bump login library minSdkVersion to 21 and targetSdkVersion to 29 --- libs/login/build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 9f2f4a3c3ec..c2f9cfd9a04 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -27,12 +27,12 @@ repositories { } android { - compileSdkVersion 28 - buildToolsVersion "28.0.3" + compileSdkVersion 29 + buildToolsVersion "29.0.2" defaultConfig { - minSdkVersion 17 - targetSdkVersion 28 + minSdkVersion 21 + targetSdkVersion 29 versionCode 2 versionName "1.1" From b2fcd8be91d5da47cf93099ef7fca1ab210e36f9 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Wed, 3 Jun 2020 10:42:27 +0200 Subject: [PATCH 436/888] Add screen tracking to login and signup --- .../org/wordpress/android/login/LoginAnalyticsListener.java | 4 +++- .../java/org/wordpress/android/login/LoginEmailFragment.java | 1 + .../wordpress/android/login/LoginMagicLinkSentFragment.java | 2 +- .../org/wordpress/android/login/SignupMagicLinkFragment.java | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java index e79ad1202db..db0213e3fb9 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java @@ -19,7 +19,8 @@ public interface LoginAnalyticsListener { void trackLoginSocial2faNeeded(); void trackLoginSocialSuccess(); void trackMagicLinkFailed(Map properties); - void trackMagicLinkOpenEmailClientViewed(); + void trackSignupMagicLinkOpenEmailClientViewed(); + void trackLoginMagicLinkOpenEmailClientViewed(); void trackMagicLinkRequested(); void trackMagicLinkRequestFormViewed(); void trackPasswordFormViewed(); @@ -51,4 +52,5 @@ public interface LoginAnalyticsListener { void trackConnectedSiteInfoRequested(String url); void trackConnectedSiteInfoFailed(String url, String errorContext, String errorType, String errorDescription); void trackConnectedSiteInfoSucceeded(Map properties); + void trackEmailFilled(); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index c656e2ffd0c..8ab60157b61 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -369,6 +369,7 @@ protected void next(String email) { startProgress(); mRequestedEmail = email; mDispatcher.dispatch(AccountActionBuilder.newIsAvailableEmailAction(email)); + mAnalyticsListener.trackEmailFilled(); } else { showEmailError(R.string.email_invalid); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java index 54ce0dc1aa1..00fff517823 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java @@ -87,7 +87,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { } if (savedInstanceState == null) { - mAnalyticsListener.trackMagicLinkOpenEmailClientViewed(); + mAnalyticsListener.trackLoginMagicLinkOpenEmailClientViewed(); } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java index 910cd28db95..7ff398bce7a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java @@ -118,7 +118,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { } if (savedInstanceState == null) { - mAnalyticsListener.trackMagicLinkOpenEmailClientViewed(); + mAnalyticsListener.trackSignupMagicLinkOpenEmailClientViewed(); } } From 613feff86da4152dde00bcca886e48e43dc6e870 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Wed, 3 Jun 2020 12:23:32 +0200 Subject: [PATCH 437/888] Add source to tracking events --- .../java/org/wordpress/android/login/LoginAnalyticsListener.java | 1 + .../java/org/wordpress/android/login/LoginGoogleFragment.java | 1 + 2 files changed, 2 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java index db0213e3fb9..a57b96560bf 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java @@ -37,6 +37,7 @@ public interface LoginAnalyticsListener { void trackSignupSocialButtonFailure(); void trackSignupSocialToLogin(); void trackSignupTermsOfServiceTapped(); + void trackSocialButtonStart(); void trackSocialAccountsNeedConnecting(); void trackSocialButtonClick(); void trackSocialButtonFailure(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index 99a07dd7532..bcf5b015f90 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -79,6 +79,7 @@ protected void startFlow() { AppLog.d(T.MAIN, "GOOGLE LOGIN: startFlow"); mLoginRequested = true; Intent loginIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); + mAnalyticsListener.trackSocialButtonStart(); startActivityForResult(loginIntent, REQUEST_LOGIN); } else { AppLog.d(T.MAIN, "GOOGLE LOGIN: startFlow called, but is already in progress"); From e13716c33f86856a49e6c3619936290e2ca64488 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Thu, 4 Jun 2020 10:05:27 +0200 Subject: [PATCH 438/888] Remove method that's not tracking screen change --- .../java/org/wordpress/android/login/LoginAnalyticsListener.java | 1 - .../java/org/wordpress/android/login/LoginEmailFragment.java | 1 - 2 files changed, 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java index a57b96560bf..99139de9d85 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java @@ -53,5 +53,4 @@ public interface LoginAnalyticsListener { void trackConnectedSiteInfoRequested(String url); void trackConnectedSiteInfoFailed(String url, String errorContext, String errorType, String errorDescription); void trackConnectedSiteInfoSucceeded(Map properties); - void trackEmailFilled(); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 8ab60157b61..c656e2ffd0c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -369,7 +369,6 @@ protected void next(String email) { startProgress(); mRequestedEmail = email; mDispatcher.dispatch(AccountActionBuilder.newIsAvailableEmailAction(email)); - mAnalyticsListener.trackEmailFilled(); } else { showEmailError(R.string.email_invalid); } From af7e71638f0c5a7cfc0f227a5783e91a3255cfca Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Thu, 4 Jun 2020 16:20:05 +0200 Subject: [PATCH 439/888] First step of failure tracking --- .../org/wordpress/android/login/LoginAnalyticsListener.java | 1 + .../java/org/wordpress/android/login/LoginEmailFragment.java | 1 + .../wordpress/android/login/LoginEmailPasswordFragment.java | 5 +++++ .../org/wordpress/android/login/LoginGoogleFragment.java | 1 + 4 files changed, 8 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java index 99139de9d85..ee335744eaa 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java @@ -53,4 +53,5 @@ public interface LoginAnalyticsListener { void trackConnectedSiteInfoRequested(String url); void trackConnectedSiteInfoFailed(String url, String errorContext, String errorType, String errorDescription); void trackConnectedSiteInfoSucceeded(Map properties); + void trackFailure(String message); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index c656e2ffd0c..792007da18d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -480,6 +480,7 @@ public void onAvailabilityChecked(OnAvailabilityChecked event) { } else { // email address is available on wpcom, so apparently the user can't login with that one. ActivityUtils.hideKeyboardForced(mEmailInput); + mAnalyticsListener.trackFailure("Email not registered WP.com"); showEmailError(R.string.email_not_registered_wpcom); } } else if (mLoginListener != null) { diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index e32c9a12ebe..e659828d46b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -289,6 +289,7 @@ public void onLoginStateUpdated(LoginState loginState) { break; case FAILURE_EMAIL_WRONG_PASSWORD: onLoginFinished(false); + mAnalyticsListener.trackFailure(loginState.getStep().name()); showPasswordError(); break; case FAILURE_2FA: @@ -307,10 +308,12 @@ public void onLoginStateUpdated(LoginState loginState) { break; case FAILURE_FETCHING_ACCOUNT: onLoginFinished(false); + mAnalyticsListener.trackFailure(loginState.getStep().name()); showError(getString(R.string.error_fetch_my_profile)); break; case FAILURE_CANNOT_ADD_DUPLICATE_SITE: onLoginFinished(false); + mAnalyticsListener.trackFailure(loginState.getStep().name()); showError(getString(R.string.cannot_add_duplicate_site)); break; case FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL: @@ -318,11 +321,13 @@ public void onLoginStateUpdated(LoginState loginState) { mLoginListener.loginViaWpcomUsernameInstead(); ToastUtils.showToast(getContext(), R.string.error_user_username_instead_of_email, Duration.LONG); + mAnalyticsListener.trackFailure(loginState.getStep().name()); // consume the state so we don't re-redirect to username login if user backs up LoginWpcomService.clearLoginServiceState(); break; case FAILURE: onLoginFinished(false); + mAnalyticsListener.trackFailure(loginState.getStep().name()); showError(getString(R.string.error_generic)); break; case SUCCESS: diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index bcf5b015f90..d72f72b7fdf 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -226,6 +226,7 @@ public void onSocialChanged(OnSocialChanged event) { event.error.type.toString(), event.error.message); } + mAnalyticsListener.trackFailure(event.error.type.name()); switch (event.error.type) { // WordPress account exists with input email address, but not connected. case USER_EXISTS: From 90a6d1dcca718c8156815f55a9b673f5f4d89c51 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Fri, 5 Jun 2020 11:00:15 +0200 Subject: [PATCH 440/888] Use universal method for failure tracking --- .../java/org/wordpress/android/login/GoogleFragment.java | 1 + .../java/org/wordpress/android/login/Login2FaFragment.java | 4 +++- .../wordpress/android/login/LoginBaseDiscoveryFragment.java | 1 + .../wordpress/android/login/LoginEmailPasswordFragment.java | 5 ++++- .../android/login/LoginMagicLinkRequestFragment.java | 1 + .../wordpress/android/login/LoginSiteAddressFragment.java | 4 +++- .../android/login/LoginUsernamePasswordFragment.java | 2 ++ .../org/wordpress/android/login/SignupMagicLinkFragment.java | 1 + 8 files changed, 16 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/GoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/GoogleFragment.java index dad815405aa..cc4e9ded95f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/GoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/GoogleFragment.java @@ -225,6 +225,7 @@ protected void finishFlow() { } protected void showError(String message) { + mAnalyticsListener.trackFailure(message); finishFlow(); mGoogleListener.onGoogleSignupError(message); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 96b2baab5a1..a35953a5757 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -368,6 +368,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { } private void show2FaError(String message) { + mAnalyticsListener.trackFailure(message); m2FaInput.setError(message); } @@ -389,7 +390,7 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) // TODO: FluxC: could be specific? default: AppLog.e(T.NUX, "Server response: " + errorMessage); - + mAnalyticsListener.trackFailure(errorMessage); ToastUtils.showToast(getActivity(), errorMessage == null ? getString(R.string.error_generic) : errorMessage); break; @@ -397,6 +398,7 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) } private void showErrorDialog(String message) { + mAnalyticsListener.trackFailure(message); AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity()) .setMessage(message) .setPositiveButton(R.string.login_error_button, null) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseDiscoveryFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseDiscoveryFragment.java index 4390ab57d39..40c916f6ee1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseDiscoveryFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseDiscoveryFragment.java @@ -72,6 +72,7 @@ public void onDiscoverySucceeded(OnDiscoveryResponse event) { } private void handleDiscoveryError(DiscoveryError error, final String failedEndpoint) { + mAnalyticsListener.trackFailure(error.name() + " - " + failedEndpoint); if (error == DiscoveryError.WORDPRESS_COM_SITE) { mLoginBaseDiscoveryListener.handleWpComDiscoveryError(failedEndpoint); } else { diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index e659828d46b..a06214ab60a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -244,10 +244,13 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { } private void showPasswordError() { - mPasswordInput.setError(getString(R.string.password_incorrect)); + String message = getString(R.string.password_incorrect); + mAnalyticsListener.trackFailure(message); + mPasswordInput.setError(message); } private void showError(String error) { + mAnalyticsListener.trackFailure(error); mPasswordInput.setError(error); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index fd554f05545..2e89a0bcbd4 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -330,6 +330,7 @@ public void onAuthEmailSent(OnAuthEmailSent event) { HashMap errorProperties = new HashMap<>(); errorProperties.put(ERROR_KEY, event.error.message); mAnalyticsListener.trackMagicLinkFailed(errorProperties); + mAnalyticsListener.trackFailure(event.error.message); AppLog.e(AppLog.T.API, "OnAuthEmailSent has error: " + event.error.type + " - " + event.error.message); if (isAdded()) { diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index a1b47247241..fa23924cfd6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -212,7 +212,9 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { } private void showError(int messageId) { - mSiteAddressInput.setError(getString(messageId)); + String message = getString(messageId); + mAnalyticsListener.trackFailure(message); + mSiteAddressInput.setError(message); } @Override diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index b15eb5b2937..647a7b64045 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -370,6 +370,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { @Override public void handleDiscoveryError(DiscoveryError error, String failedEndpoint) { ActivityUtils.hideKeyboard(getActivity()); + mAnalyticsListener.trackFailure(error.name() + " - " + failedEndpoint); if (error == DiscoveryError.HTTP_AUTH_REQUIRED) { mLoginListener.helpNoJetpackScreen(mInputSiteAddress, mEndpointAddress, getCleanedUsername(), mPasswordInput.getEditText().getText().toString(), @@ -439,6 +440,7 @@ private void showPasswordError(String errorMessage) { private void showError(String errorMessage) { mUsernameInput.setError(errorMessage != null ? " " : null); mPasswordInput.setError(errorMessage); + mAnalyticsListener.trackFailure(errorMessage); if (errorMessage != null) { requestScrollToView(mPasswordInput); diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java index 7ff398bce7a..d00b2b86383 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupMagicLinkFragment.java @@ -220,6 +220,7 @@ private AuthEmailPayloadSource getAuthEmailPayloadSource() { } protected void showErrorDialog(String message) { + mAnalyticsListener.trackFailure(message); DialogInterface.OnClickListener dialogListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { From 8f54072873403159503904021d0fe0e977208b39 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Fri, 5 Jun 2020 12:01:28 +0200 Subject: [PATCH 441/888] Add click tracking to unified login and signup flow --- .../wordpress/android/login/Login2FaFragment.java | 2 ++ .../android/login/LoginAnalyticsListener.java | 13 +++++++++++++ .../android/login/LoginBaseFormFragment.java | 1 + .../wordpress/android/login/LoginEmailFragment.java | 2 ++ .../android/login/LoginEmailPasswordFragment.java | 2 ++ .../login/LoginMagicLinkRequestFragment.java | 2 ++ .../android/login/LoginSiteAddressFragment.java | 2 ++ .../login/LoginUsernamePasswordFragment.java | 1 + .../android/login/SignupEmailFragment.java | 1 + 9 files changed, 26 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index a35953a5757..49fff912d6b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -181,6 +181,7 @@ protected void setupBottomButtons(Button secondaryButton, Button primaryButton) @Override public void onClick(View v) { if (isAdded()) { + mAnalyticsListener.trackSendCodeWithTextClicked(); doAuthAction(R.string.requesting_otp, "", true); } } @@ -278,6 +279,7 @@ public void onResume() { } protected void next() { + mAnalyticsListener.trackSubmit2faCodeClicked(); if (TextUtils.isEmpty(m2FaInput.getEditText().getText())) { show2FaError(getString(R.string.login_empty_2fa)); return; diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java index ee335744eaa..2e0ad33c5a9 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.java @@ -54,4 +54,17 @@ public interface LoginAnalyticsListener { void trackConnectedSiteInfoFailed(String url, String errorContext, String errorType, String errorDescription); void trackConnectedSiteInfoSucceeded(Map properties); void trackFailure(String message); + void trackSendCodeWithTextClicked(); + + void trackSubmit2faCodeClicked(); + + void trackClickOnLoginSiteClicked(); + + void trackSubmitClicked(); + + void trackRequestMagicLinkClick(); + + void trackLoginWithPasswordClick(); + + void trackShowHelpClick(); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index 09d1e009e6f..8aed084045f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -200,6 +200,7 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.help) { + mAnalyticsListener.trackShowHelpClick(); onHelp(); return true; } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 792007da18d..cd1cbf3134b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -200,6 +200,7 @@ public void onClick(View view) { siteLoginButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { + mAnalyticsListener.trackClickOnLoginSiteClicked(); if (mLoginListener != null) { LoginMode loginMode = mLoginListener.getLoginMode(); if (loginMode == LoginMode.JETPACK_STATS) { @@ -360,6 +361,7 @@ public void onSaveInstanceState(Bundle outState) { } protected void next(String email) { + mAnalyticsListener.trackSubmitClicked(); if (!NetworkUtils.checkConnection(getActivity())) { return; } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index a06214ab60a..59767cf2864 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -209,6 +209,8 @@ public void onSaveInstanceState(Bundle outState) { } protected void next() { + mAnalyticsListener.trackSubmitClicked(); + if (!NetworkUtils.checkConnection(getActivity())) { return; } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index 2e89a0bcbd4..8d035cee045 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -126,6 +126,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mRequestMagicLinkButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + mAnalyticsListener.trackRequestMagicLinkClick(); if (mLoginListener != null) { if (NetworkUtils.checkConnection(getActivity())) { showMagicLinkRequestProgressDialog(); @@ -142,6 +143,7 @@ public void onClick(View v) { view.findViewById(R.id.login_enter_password).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + mAnalyticsListener.trackLoginWithPasswordClick(); if (mLoginListener != null) { mLoginListener.usePasswordInstead(mEmail); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index fa23924cfd6..2bfdc4cd86a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -101,6 +101,7 @@ protected void setupBottomButtons(Button secondaryButton, Button primaryButton) secondaryButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { + mAnalyticsListener.trackShowHelpClick(); showSiteAddressHelp(); } }); @@ -173,6 +174,7 @@ protected void discover() { if (!NetworkUtils.checkConnection(getActivity())) { return; } + mAnalyticsListener.trackSubmitClicked(); mLoginBaseDiscoveryListener = this; diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index 647a7b64045..6c35d9eec06 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -277,6 +277,7 @@ public void onSaveInstanceState(Bundle outState) { } protected void next() { + mAnalyticsListener.trackSubmitClicked(); if (!NetworkUtils.checkConnection(getActivity())) { return; } diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java index a492701f015..6f282a83deb 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java @@ -185,6 +185,7 @@ public void onSaveInstanceState(Bundle outState) { } protected void next(String email) { + mAnalyticsListener.trackSubmitClicked(); if (NetworkUtils.checkConnection(getActivity())) { if (isValidEmail(email)) { startProgress(); From 95363b428e20571d3391a256b0568af929dc08c4 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Mon, 8 Jun 2020 16:37:30 +0200 Subject: [PATCH 442/888] End progress when the login fragment is destroyed --- .../org/wordpress/android/login/LoginBaseFormFragment.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index 09d1e009e6f..b29f2421c67 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -207,6 +207,12 @@ public boolean onOptionsItemSelected(MenuItem item) { return false; } + @Override + public void onDestroy() { + endProgress(); + super.onDestroy(); + } + protected void startProgress() { startProgress(true); } From b52a82c9cd962562645eb57c59940d965b417cc6 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Tue, 9 Jun 2020 14:32:19 +0200 Subject: [PATCH 443/888] Fix NPE when primary button is missing --- .../org/wordpress/android/login/LoginBaseFormFragment.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index b29f2421c67..d2c590f2829 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -246,8 +246,9 @@ protected void endProgress() { mProgressDialog.setOnCancelListener(null); mProgressDialog = null; } - - mPrimaryButton.setEnabled(true); + if (mPrimaryButton != null) { + mPrimaryButton.setEnabled(true); + } if (mSecondaryButton != null) { mSecondaryButton.setEnabled(true); From 4943ee76a9f79f45dafb95d65708c6d45fff7732 Mon Sep 17 00:00:00 2001 From: Ondrej Ruttkay Date: Fri, 12 Jun 2020 19:31:47 +0200 Subject: [PATCH 444/888] Update gradle plugin to 4.0 and gradle to 6.1.1 --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 9051314a8ed..762f9515625 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -4,7 +4,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:4.0.0' } } From b80e150e60d9b9676b5f189f966fed28bdcf1b66 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 26 May 2020 00:14:26 -0300 Subject: [PATCH 445/888] Update login theme and styles --- .../login_on_background_medium_selector.xml | 5 + .../color/login_on_surface_high_selector.xml | 5 + .../login_on_surface_medium_selector.xml | 5 + .../login_magic_link_request_screen.xml | 8 +- .../login_magic_link_sent_screen.xml | 8 +- .../signup_bottom_sheet_dialog.xml | 6 +- .../res/layout-land/signup_magic_link.xml | 4 +- .../src/main/res/layout/login_2fa_screen.xml | 2 +- .../main/res/layout/login_alert_http_auth.xml | 4 +- .../layout/login_alert_site_address_help.xml | 2 +- .../layout/login_email_password_screen.xml | 5 +- .../main/res/layout/login_email_screen.xml | 5 +- .../src/main/res/layout/login_form_screen.xml | 6 +- .../src/main/res/layout/login_input_row.xml | 2 +- .../login_magic_link_request_screen.xml | 9 +- .../layout/login_magic_link_sent_screen.xml | 6 +- .../res/layout/login_site_address_screen.xml | 2 +- .../layout/login_username_password_screen.xml | 3 +- .../res/layout/signup_bottom_sheet_dialog.xml | 6 +- .../main/res/layout/signup_email_fragment.xml | 2 +- .../src/main/res/layout/signup_magic_link.xml | 4 +- .../src/main/res/layout/toolbar_login.xml | 5 +- .../src/main/res/values-night/themes.xml | 27 ++++ libs/login/src/main/res/values-v23/themes.xml | 8 + libs/login/src/main/res/values-v27/styles.xml | 10 -- libs/login/src/main/res/values-v27/themes.xml | 10 ++ libs/login/src/main/res/values/colors.xml | 17 +- libs/login/src/main/res/values/shapes.xml | 11 ++ libs/login/src/main/res/values/styles.xml | 145 ++++++++++-------- libs/login/src/main/res/values/themes.xml | 59 +++++++ libs/login/src/main/res/values/types.xml | 70 +++++++++ 31 files changed, 344 insertions(+), 117 deletions(-) create mode 100644 libs/login/src/main/res/color/login_on_background_medium_selector.xml create mode 100644 libs/login/src/main/res/color/login_on_surface_high_selector.xml create mode 100644 libs/login/src/main/res/color/login_on_surface_medium_selector.xml create mode 100644 libs/login/src/main/res/values-night/themes.xml create mode 100644 libs/login/src/main/res/values-v23/themes.xml delete mode 100644 libs/login/src/main/res/values-v27/styles.xml create mode 100644 libs/login/src/main/res/values-v27/themes.xml create mode 100644 libs/login/src/main/res/values/shapes.xml create mode 100644 libs/login/src/main/res/values/themes.xml create mode 100644 libs/login/src/main/res/values/types.xml diff --git a/libs/login/src/main/res/color/login_on_background_medium_selector.xml b/libs/login/src/main/res/color/login_on_background_medium_selector.xml new file mode 100644 index 00000000000..c3c7cbea81c --- /dev/null +++ b/libs/login/src/main/res/color/login_on_background_medium_selector.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/libs/login/src/main/res/color/login_on_surface_high_selector.xml b/libs/login/src/main/res/color/login_on_surface_high_selector.xml new file mode 100644 index 00000000000..fcdf7b8de46 --- /dev/null +++ b/libs/login/src/main/res/color/login_on_surface_high_selector.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/libs/login/src/main/res/color/login_on_surface_medium_selector.xml b/libs/login/src/main/res/color/login_on_surface_medium_selector.xml new file mode 100644 index 00000000000..33876379347 --- /dev/null +++ b/libs/login/src/main/res/color/login_on_surface_medium_selector.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml index 29877bd2aff..6983da02b7f 100644 --- a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml +++ b/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml @@ -33,7 +33,7 @@ @@ -61,7 +61,7 @@ @@ -51,7 +51,7 @@ @@ -57,7 +57,7 @@ + app:theme="@style/Widget.LoginFlow.TextInputLayout"> + app:theme="@style/Widget.LoginFlow.TextInputLayout"> diff --git a/libs/login/src/main/res/layout/login_email_password_screen.xml b/libs/login/src/main/res/layout/login_email_password_screen.xml index 8053752cf6e..8fa16926171 100644 --- a/libs/login/src/main/res/layout/login_email_password_screen.xml +++ b/libs/login/src/main/res/layout/login_email_password_screen.xml @@ -13,7 +13,7 @@ @@ -42,7 +42,7 @@ + android:text="@string/send_link" /> + android:layout_height="wrap_content"> diff --git a/libs/login/src/main/res/values-night/themes.xml b/libs/login/src/main/res/values-night/themes.xml new file mode 100644 index 00000000000..f5296a5ea88 --- /dev/null +++ b/libs/login/src/main/res/values-night/themes.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/libs/login/src/main/res/values-v23/themes.xml b/libs/login/src/main/res/values-v23/themes.xml new file mode 100644 index 00000000000..c0fde8bb516 --- /dev/null +++ b/libs/login/src/main/res/values-v23/themes.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/libs/login/src/main/res/values-v27/styles.xml b/libs/login/src/main/res/values-v27/styles.xml deleted file mode 100644 index 03a359e2ae1..00000000000 --- a/libs/login/src/main/res/values-v27/styles.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/libs/login/src/main/res/values-v27/themes.xml b/libs/login/src/main/res/values-v27/themes.xml new file mode 100644 index 00000000000..fc3d18102eb --- /dev/null +++ b/libs/login/src/main/res/values-v27/themes.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/libs/login/src/main/res/values/colors.xml b/libs/login/src/main/res/values/colors.xml index ec74e875329..605ea18071b 100644 --- a/libs/login/src/main/res/values/colors.xml +++ b/libs/login/src/main/res/values/colors.xml @@ -1,6 +1,21 @@ - + + #3582c4 + #2271b1 + #0a4b78 + + #c9356e + #8c1749 + + #d63638 + + #ffffff + #121212 + #000000 + + + + - - @color/status_bar - @color/login_background_color - @android:color/white + - - @style/LoginTheme.BottomSheetDialogStyle - + + - @style/LoginTheme.ToolBar + - - - - - - + - - - - - - - - - + + + - - diff --git a/libs/login/src/main/res/values/themes.xml b/libs/login/src/main/res/values/themes.xml new file mode 100644 index 00000000000..32f6910f2f2 --- /dev/null +++ b/libs/login/src/main/res/values/themes.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + diff --git a/libs/login/src/main/res/values/types.xml b/libs/login/src/main/res/values/types.xml new file mode 100644 index 00000000000..cff70fb995c --- /dev/null +++ b/libs/login/src/main/res/values/types.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f2f154c971af0d4dc2c82f3cd622abb74a2d4389 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Wed, 13 May 2020 09:56:04 -0300 Subject: [PATCH 446/888] UI update to Login Email screen --- .../android/login/LoginBaseFormFragment.java | 34 +++++- .../android/login/LoginEmailFragment.java | 107 +++++++++++++++--- .../material_on_surface_emphasis_low.xml | 4 + .../drawable/ic_help_outline_white_24dp.xml | 11 ++ .../main/res/layout/login_email_screen.xml | 21 +++- .../src/main/res/layout/login_form_screen.xml | 79 +++++++------ .../res/layout/login_third_party_block.xml | 55 +++++++++ .../src/main/res/layout/toolbar_login.xml | 2 + libs/login/src/main/res/menu/menu_login.xml | 1 + libs/login/src/main/res/values/strings.xml | 6 + 10 files changed, 267 insertions(+), 53 deletions(-) create mode 100644 libs/login/src/main/res/color/material_on_surface_emphasis_low.xml create mode 100644 libs/login/src/main/res/drawable/ic_help_outline_white_24dp.xml create mode 100644 libs/login/src/main/res/layout/login_third_party_block.xml diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index 09d1e009e6f..5e4d0adaf5f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -3,6 +3,8 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.text.TextWatcher; @@ -25,6 +27,7 @@ import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import org.greenrobot.eventbus.Subscribe; @@ -49,6 +52,7 @@ public abstract class LoginBaseFormFragment extends Fragment implements TextWatcher { private static final String KEY_IN_PROGRESS = "KEY_IN_PROGRESS"; private static final String KEY_LOGIN_FINISHED = "KEY_LOGIN_FINISHED"; + static final String ARG_UNIFIED_LOGIN_ENABLED = "ARG_UNIFIED_LOGIN_ENABLED"; private Button mPrimaryButton; private Button mSecondaryButton; @@ -58,6 +62,7 @@ public abstract class LoginBaseFormFragment extends Fragment private boolean mInProgress; private boolean mLoginFinished; + boolean mIsUnifiedLoginEnabled; @Inject protected Dispatcher mDispatcher; @Inject protected SiteStore mSiteStore; @@ -94,6 +99,12 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); + Bundle args = getArguments(); + if (savedInstanceState != null) { + mIsUnifiedLoginEnabled = savedInstanceState.getBoolean(ARG_UNIFIED_LOGIN_ENABLED); + } else if (args != null) { + mIsUnifiedLoginEnabled = args.getBoolean(ARG_UNIFIED_LOGIN_ENABLED, false); + } } protected ViewGroup createMainView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -128,8 +139,8 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); if (actionBar != null) { - actionBar.setDisplayShowTitleEnabled(false); actionBar.setDisplayHomeAsUpEnabled(true); + buildToolbar(toolbar, actionBar); } if (savedInstanceState == null) { @@ -137,6 +148,14 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { } } + protected void buildToolbar(Toolbar toolbar, ActionBar actionBar) { + View toolbarIcon = toolbar.findViewById(R.id.toolbar_icon); + if (toolbarIcon != null) { + toolbarIcon.setVisibility(View.VISIBLE); + } + actionBar.setDisplayShowTitleEnabled(false); + } + @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -190,11 +209,24 @@ public void onSaveInstanceState(Bundle outState) { outState.putBoolean(KEY_IN_PROGRESS, mInProgress); outState.putBoolean(KEY_LOGIN_FINISHED, mLoginFinished); + outState.putBoolean(ARG_UNIFIED_LOGIN_ENABLED, mIsUnifiedLoginEnabled); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.menu_login, menu); + Context context = getContext(); + if (context != null) { + for (int i = 0; i < menu.size(); i++) { + Drawable drawable = menu.getItem(i).getIcon(); + if (drawable != null) { + drawable.mutate(); + drawable.setColorFilter( + ContextCompat.getColor(context, R.color.material_on_surface_emphasis_high_type), + PorterDuff.Mode.SRC_ATOP); + } + } + } } @Override diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index c656e2ffd0c..b6cea26cf72 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -5,11 +5,13 @@ import android.content.Context; import android.content.Intent; import android.content.IntentSender; +import android.content.res.Resources; import android.os.Bundle; import android.text.Editable; import android.text.Html; import android.text.TextWatcher; import android.util.Patterns; +import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -21,7 +23,9 @@ import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.Toolbar; import com.google.android.gms.auth.api.Auth; import com.google.android.gms.auth.api.credentials.Credential; @@ -39,6 +43,7 @@ import org.wordpress.android.fluxc.generated.AccountActionBuilder; import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.AccountStore.OnAvailabilityChecked; +import org.wordpress.android.login.SignupBottomSheetDialogFragment.SignupSheetListener; import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; @@ -52,10 +57,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static android.app.Activity.RESULT_OK; - import dagger.android.support.AndroidSupportInjection; +import static android.app.Activity.RESULT_OK; + public class LoginEmailFragment extends LoginBaseFormFragment implements TextWatcher, OnEditorCommitListener, ConnectionCallbacks, OnConnectionFailedListener { private static final String KEY_GOOGLE_EMAIL = "KEY_GOOGLE_EMAIL"; @@ -98,11 +103,12 @@ public static LoginEmailFragment newInstance(String url) { return fragment; } - public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled) { + public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled, boolean isUnifiedLoginEnabled) { LoginEmailFragment fragment = new LoginEmailFragment(); Bundle args = new Bundle(); args.putBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, isSignupFromLoginEnabled); args.putBoolean(ARG_SITE_LOGIN_ENABLED, isSiteLoginEnabled); + args.putBoolean(ARG_UNIFIED_LOGIN_ENABLED, isUnifiedLoginEnabled); fragment.setArguments(args); return fragment; } @@ -128,7 +134,11 @@ protected void setupLabel(@NonNull TextView label) { break; case FULL: case WPCOM_LOGIN_ONLY: - label.setText(R.string.enter_email_wordpress_com); + if (mIsUnifiedLoginEnabled) { + label.setText(R.string.enter_email_to_continue_wordpress_com); + } else { + label.setText(R.string.enter_email_wordpress_com); + } break; case WOO_LOGIN_MODE: label.setText(getString(R.string.enter_email_for_site, mLoginSiteUrl)); @@ -180,19 +190,7 @@ public void onClick(View view) { googleLoginButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - mAnalyticsListener.trackSocialButtonClick(); - ActivityUtils.hideKeyboardForced(mEmailInput.getEditText()); - - if (NetworkUtils.checkConnection(getActivity())) { - if (isAdded()) { - mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); - mIsSocialLogin = true; - mLoginListener.addGoogleLoginFragment(); - } else { - AppLog.e(T.NUX, "Google login could not be started. LoginEmailFragment was not attached."); - showErrorDialog(getString(R.string.login_error_generic_start)); - } - } + onGoogleSigninClicked(); } }); @@ -239,6 +237,22 @@ public void onClick(View view) { } } + private void onGoogleSigninClicked() { + mAnalyticsListener.trackSocialButtonClick(); + ActivityUtils.hideKeyboardForced(mEmailInput.getEditText()); + + if (NetworkUtils.checkConnection(getActivity())) { + if (isAdded()) { + mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); + mIsSocialLogin = true; + mLoginListener.addGoogleLoginFragment(); + } else { + AppLog.e(T.NUX, "Google login could not be started. LoginEmailFragment was not attached."); + showErrorDialog(getString(R.string.login_error_generic_start)); + } + } + } + @Override protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { // Show Sign-Up button if login mode is Jetpack and signup from login is not enabled @@ -359,6 +373,65 @@ public void onSaveInstanceState(Bundle outState) { } } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View rootView = super.onCreateView(inflater, container, savedInstanceState); + if (mIsUnifiedLoginEnabled && rootView != null) { + // Hide all unused views + rootView.findViewById(R.id.bottom_buttons).setVisibility(View.GONE); + rootView.findViewById(R.id.login_alternatively_label).setVisibility(View.GONE); + rootView.findViewById(R.id.login_google_button).setVisibility(View.GONE); + // Show the new UX + rootView.findViewById(R.id.third_party_buttons).setVisibility(View.VISIBLE); + Button continueButton = rootView.findViewById(R.id.login_continue_button); + continueButton.setVisibility(View.VISIBLE); + continueButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + next(getCleanedEmail()); + } + }); + Button continueTos = rootView.findViewById(R.id.continue_tos); + Button continueWithGoogleTosText = rootView.findViewById(R.id.continue_with_google_tos); + continueTos.setVisibility(View.VISIBLE); + + OnClickListener onClickListener = new OnClickListener() { + public void onClick(View view) { + Context context = getContext(); + if ((context instanceof SignupSheetListener)) { + ((SignupSheetListener) context).onSignupSheetTermsOfServiceClicked(); + } + } + }; + continueTos.setOnClickListener(onClickListener); + continueWithGoogleTosText.setOnClickListener(onClickListener); + Resources resources = rootView + .getContext() + .getResources(); + continueTos.setText(Html.fromHtml( + String.format(resources.getString(R.string.continue_terms_of_service_text), "", ""))); + continueWithGoogleTosText.setText(Html.fromHtml( + String.format(resources.getString(R.string.continue_with_google_terms_of_service_text), "", + ""))); + Button continueWithGoogleButton = rootView.findViewById(R.id.continue_with_google); + continueWithGoogleButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + onGoogleSigninClicked(); + } + }); + } + return rootView; + } + + @Override + protected void buildToolbar(Toolbar toolbar, ActionBar actionBar) { + if (mIsUnifiedLoginEnabled) { + actionBar.setTitle(R.string.get_started); + } else { + super.buildToolbar(toolbar, actionBar); + } + } + protected void next(String email) { if (!NetworkUtils.checkConnection(getActivity())) { return; diff --git a/libs/login/src/main/res/color/material_on_surface_emphasis_low.xml b/libs/login/src/main/res/color/material_on_surface_emphasis_low.xml new file mode 100644 index 00000000000..27396552286 --- /dev/null +++ b/libs/login/src/main/res/color/material_on_surface_emphasis_low.xml @@ -0,0 +1,4 @@ + + + + diff --git a/libs/login/src/main/res/drawable/ic_help_outline_white_24dp.xml b/libs/login/src/main/res/drawable/ic_help_outline_white_24dp.xml new file mode 100644 index 00000000000..5fdc7e34bf1 --- /dev/null +++ b/libs/login/src/main/res/drawable/ic_help_outline_white_24dp.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index b2eb2db0f31..000b93f5b15 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -15,8 +15,7 @@ style="@style/Widget.LoginFlow.TextView.Label" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/margin_extra_large" - android:layout_marginBottom="@dimen/margin_extra_large" + android:layout_marginBottom="@dimen/margin_extra_medium_large" android:gravity="start" android:textAlignment="viewStart" tools:text="@string/enter_email_wordpress_com" /> @@ -29,12 +28,30 @@ android:hint="@string/email_address" android:imeOptions="actionNext" android:importantForAutofill="noExcludeDescendants" + android:layout_marginBottom="@dimen/margin_medium" android:inputType="textEmailAddress" android:textAlignment="viewStart" tools:ignore="UnusedAttribute" /> + + + + - - - + android:visibility="gone" /> + + - + android:paddingStart="@dimen/margin_small_medium" + android:paddingTop="@dimen/margin_medium_large"> - - - + + + + + + diff --git a/libs/login/src/main/res/layout/login_third_party_block.xml b/libs/login/src/main/res/layout/login_third_party_block.xml new file mode 100644 index 00000000000..a4368e01457 --- /dev/null +++ b/libs/login/src/main/res/layout/login_third_party_block.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + diff --git a/libs/login/src/main/res/layout/toolbar_login.xml b/libs/login/src/main/res/layout/toolbar_login.xml index 9589f2b920d..6e847604bf2 100644 --- a/libs/login/src/main/res/layout/toolbar_login.xml +++ b/libs/login/src/main/res/layout/toolbar_login.xml @@ -12,11 +12,13 @@ android:layout_height="wrap_content"> diff --git a/libs/login/src/main/res/menu/menu_login.xml b/libs/login/src/main/res/menu/menu_login.xml index 84886dd8221..8e3a117e35e 100644 --- a/libs/login/src/main/res/menu/menu_login.xml +++ b/libs/login/src/main/res/menu/menu_login.xml @@ -5,6 +5,7 @@ diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 35a838c0f96..5dc5992e934 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -11,8 +11,10 @@ Help Log In Log in to WordPress.com using an email address to manage all your WordPress sites. + Enter your email address to log in or create a WordPress.com account. Log in with WordPress.com to connect to %1$s Log in with your %1$s site credentials + Get Started Next Open mail Alternatively: @@ -56,6 +58,8 @@ Don\'t have an account? %1$sSign up%2$s Can\'t detect your email client app Log in with Google. + Continue with Google + or Close There\'s no WordPress.com account matching this Google account. There was some trouble connecting with the Google account. @@ -71,6 +75,8 @@ We sent you a magic signup link! Check your email on this device, and tap the link in the email to finish signing up. Sending email By signing up, you agree to our %1$sTerms of Service%2$s. + By continuing, you agree to our %1$sTerms of Service%2$s. + If you continue with Google and don\'t already have a WordPress.com account, you are creating an account and you agree to our %1$sTerms of Service%2$s. Sign Up with Email Sign Up with Google Signing up with Google… From 6365170f2cfd5432019d1253f5647aff83b7f807 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 26 May 2020 01:06:00 -0300 Subject: [PATCH 447/888] Extract old Login Email screen to a separate layout file --- .../android/login/LoginBaseFormFragment.java | 24 --- .../android/login/LoginEmailFragment.java | 187 ++++++++++-------- .../material_on_surface_emphasis_low.xml | 2 +- .../main/res/layout/login_email_screen.xml | 138 ++++++------- .../res/layout/login_email_screen_old.xml | 108 ++++++++++ .../src/main/res/layout/login_form_screen.xml | 79 ++++---- .../res/layout/login_third_party_block.xml | 55 ------ libs/login/src/main/res/menu/menu_login.xml | 7 +- libs/login/src/main/res/values/dimens.xml | 1 + 9 files changed, 306 insertions(+), 295 deletions(-) create mode 100644 libs/login/src/main/res/layout/login_email_screen_old.xml delete mode 100644 libs/login/src/main/res/layout/login_third_party_block.xml diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index 5e4d0adaf5f..72483c6e5c7 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -3,8 +3,6 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.text.TextWatcher; @@ -27,7 +25,6 @@ import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; -import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import org.greenrobot.eventbus.Subscribe; @@ -52,7 +49,6 @@ public abstract class LoginBaseFormFragment extends Fragment implements TextWatcher { private static final String KEY_IN_PROGRESS = "KEY_IN_PROGRESS"; private static final String KEY_LOGIN_FINISHED = "KEY_LOGIN_FINISHED"; - static final String ARG_UNIFIED_LOGIN_ENABLED = "ARG_UNIFIED_LOGIN_ENABLED"; private Button mPrimaryButton; private Button mSecondaryButton; @@ -62,7 +58,6 @@ public abstract class LoginBaseFormFragment extends Fragment private boolean mInProgress; private boolean mLoginFinished; - boolean mIsUnifiedLoginEnabled; @Inject protected Dispatcher mDispatcher; @Inject protected SiteStore mSiteStore; @@ -99,12 +94,6 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); - Bundle args = getArguments(); - if (savedInstanceState != null) { - mIsUnifiedLoginEnabled = savedInstanceState.getBoolean(ARG_UNIFIED_LOGIN_ENABLED); - } else if (args != null) { - mIsUnifiedLoginEnabled = args.getBoolean(ARG_UNIFIED_LOGIN_ENABLED, false); - } } protected ViewGroup createMainView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -209,24 +198,11 @@ public void onSaveInstanceState(Bundle outState) { outState.putBoolean(KEY_IN_PROGRESS, mInProgress); outState.putBoolean(KEY_LOGIN_FINISHED, mLoginFinished); - outState.putBoolean(ARG_UNIFIED_LOGIN_ENABLED, mIsUnifiedLoginEnabled); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.menu_login, menu); - Context context = getContext(); - if (context != null) { - for (int i = 0; i < menu.size(); i++) { - Drawable drawable = menu.getItem(i).getIcon(); - if (drawable != null) { - drawable.mutate(); - drawable.setColorFilter( - ContextCompat.getColor(context, R.color.material_on_surface_emphasis_high_type), - PorterDuff.Mode.SRC_ATOP); - } - } - } } @Override diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index b6cea26cf72..f1ba9cc6a94 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -5,13 +5,12 @@ import android.content.Context; import android.content.Intent; import android.content.IntentSender; -import android.content.res.Resources; import android.os.Bundle; import android.text.Editable; import android.text.Html; +import android.text.Spanned; import android.text.TextWatcher; import android.util.Patterns; -import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -57,10 +56,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import dagger.android.support.AndroidSupportInjection; - import static android.app.Activity.RESULT_OK; +import dagger.android.support.AndroidSupportInjection; + public class LoginEmailFragment extends LoginBaseFormFragment implements TextWatcher, OnEditorCommitListener, ConnectionCallbacks, OnConnectionFailedListener { private static final String KEY_GOOGLE_EMAIL = "KEY_GOOGLE_EMAIL"; @@ -77,6 +76,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private static final String ARG_LOGIN_SITE_URL = "ARG_LOGIN_SITE_URL"; private static final String ARG_SIGNUP_FROM_LOGIN_ENABLED = "ARG_SIGNUP_FROM_LOGIN_ENABLED"; private static final String ARG_SITE_LOGIN_ENABLED = "ARG_SITE_LOGIN_ENABLED"; + private static final String ARG_SHOULD_USE_NEW_LAYOUT = "ARG_SHOULD_USE_NEW_LAYOUT"; public static final String TAG = "login_email_fragment_tag"; public static final int MAX_EMAIL_LENGTH = 100; @@ -89,6 +89,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private Integer mCurrentEmailErrorRes = null; private boolean mIsSignupFromLoginEnabled; private boolean mIsSiteLoginEnabled; + private boolean mShouldUseNewLayout; protected WPLoginInputRow mEmailInput; protected boolean mHasDismissedEmailHints; @@ -103,19 +104,20 @@ public static LoginEmailFragment newInstance(String url) { return fragment; } - public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled, boolean isUnifiedLoginEnabled) { + public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled, + boolean shouldUseNewLayout) { LoginEmailFragment fragment = new LoginEmailFragment(); Bundle args = new Bundle(); args.putBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, isSignupFromLoginEnabled); args.putBoolean(ARG_SITE_LOGIN_ENABLED, isSiteLoginEnabled); - args.putBoolean(ARG_UNIFIED_LOGIN_ENABLED, isUnifiedLoginEnabled); + args.putBoolean(ARG_SHOULD_USE_NEW_LAYOUT, shouldUseNewLayout); fragment.setArguments(args); return fragment; } @Override protected @LayoutRes int getContentLayout() { - return R.layout.login_email_screen; + return mShouldUseNewLayout ? R.layout.login_email_screen : R.layout.login_email_screen_old; } @Override @@ -134,7 +136,7 @@ protected void setupLabel(@NonNull TextView label) { break; case FULL: case WPCOM_LOGIN_ONLY: - if (mIsUnifiedLoginEnabled) { + if (mShouldUseNewLayout) { label.setText(R.string.enter_email_to_continue_wordpress_com); } else { label.setText(R.string.enter_email_wordpress_com); @@ -156,7 +158,24 @@ protected void setupLabel(@NonNull TextView label) { protected void setupContent(ViewGroup rootView) { // important for accessibility - talkback getActivity().setTitle(R.string.email_address_login_title); - mEmailInput = rootView.findViewById(R.id.login_email_row); + + setupEmailInput((WPLoginInputRow) rootView.findViewById(R.id.login_email_row)); + + if (mShouldUseNewLayout) { + setupContinueButton((Button) rootView.findViewById(R.id.login_continue_button)); + setupTosButtons( + (Button) rootView.findViewById(R.id.continue_tos), + (Button) rootView.findViewById(R.id.continue_with_google_tos)); + setupSocialButtons((Button) rootView.findViewById(R.id.continue_with_google)); + } else { + setupAlternativeButtons( + (LinearLayout) rootView.findViewById(R.id.login_google_button), + (LinearLayout) rootView.findViewById(R.id.login_site_button)); + } + } + + private void setupEmailInput(WPLoginInputRow emailInput) { + mEmailInput = emailInput; if (BuildConfig.DEBUG) { mEmailInput.getEditText().setText(BuildConfig.DEBUG_WPCOM_LOGIN_EMAIL); } @@ -185,8 +204,43 @@ public void onClick(View view) { } } }); + } + + private void setupContinueButton(Button continueButton) { + continueButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + onContinueClicked(); + } + }); + } - LinearLayout googleLoginButton = rootView.findViewById(R.id.login_google_button); + private void setupTosButtons(Button continueTosButton, Button continueWithGoogleTosButton) { + OnClickListener onClickListener = new OnClickListener() { + public void onClick(View view) { + Context context = getContext(); + if ((context instanceof SignupSheetListener)) { + ((SignupSheetListener) context).onSignupSheetTermsOfServiceClicked(); + } + } + }; + + continueTosButton.setOnClickListener(onClickListener); + continueTosButton.setText(formatUnderlinedText(R.string.continue_terms_of_service_text)); + + continueWithGoogleTosButton.setOnClickListener(onClickListener); + continueWithGoogleTosButton.setText(formatUnderlinedText(R.string.continue_with_google_terms_of_service_text)); + } + + private void setupSocialButtons(Button continueWithGoogleButton) { + continueWithGoogleButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + onGoogleSigninClicked(); + } + }); + } + + private void setupAlternativeButtons(LinearLayout googleLoginButton, LinearLayout siteLoginButton) { googleLoginButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { @@ -194,7 +248,6 @@ public void onClick(View view) { } }); - LinearLayout siteLoginButton = rootView.findViewById(R.id.login_site_button); siteLoginButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { @@ -211,8 +264,8 @@ public void onClick(View view) { } }); - ImageView siteLoginButtonIcon = rootView.findViewById(R.id.login_site_button_icon); - TextView siteLoginButtonText = rootView.findViewById(R.id.login_site_button_text); + ImageView siteLoginButtonIcon = siteLoginButton.findViewById(R.id.login_site_button_icon); + TextView siteLoginButtonText = siteLoginButton.findViewById(R.id.login_site_button_text); switch (mLoginListener.getLoginMode()) { case WOO_LOGIN_MODE: @@ -237,28 +290,21 @@ public void onClick(View view) { } } - private void onGoogleSigninClicked() { - mAnalyticsListener.trackSocialButtonClick(); - ActivityUtils.hideKeyboardForced(mEmailInput.getEditText()); - - if (NetworkUtils.checkConnection(getActivity())) { - if (isAdded()) { - mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); - mIsSocialLogin = true; - mLoginListener.addGoogleLoginFragment(); - } else { - AppLog.e(T.NUX, "Google login could not be started. LoginEmailFragment was not attached."); - showErrorDialog(getString(R.string.login_error_generic_start)); - } + @Override + protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { + if (mShouldUseNewLayout) { + secondaryButton.setVisibility(View.GONE); + primaryButton.setVisibility(View.GONE); + } else { + setupSecondaryButton(secondaryButton); + setupPrimaryButton(primaryButton); } } - @Override - protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { + private void setupSecondaryButton(Button secondaryButton) { // Show Sign-Up button if login mode is Jetpack and signup from login is not enabled if (mLoginListener.getLoginMode() == LoginMode.JETPACK_STATS && !mIsSignupFromLoginEnabled) { - secondaryButton.setText(Html.fromHtml(String.format(getResources().getString( - R.string.login_email_button_signup), "", ""))); + secondaryButton.setText(formatUnderlinedText(R.string.login_email_button_signup)); secondaryButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { mLoginListener.doStartSignup(); @@ -279,14 +325,40 @@ public void onClick(View view) { } else { secondaryButton.setVisibility(View.GONE); } + } + private void setupPrimaryButton(Button primaryButton) { primaryButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { - next(getCleanedEmail()); + onContinueClicked(); } }); } + private Spanned formatUnderlinedText(int stringResId) { + return Html.fromHtml(String.format(getString(stringResId), "", "")); + } + + private void onContinueClicked() { + next(getCleanedEmail()); + } + + private void onGoogleSigninClicked() { + mAnalyticsListener.trackSocialButtonClick(); + ActivityUtils.hideKeyboardForced(mEmailInput.getEditText()); + + if (NetworkUtils.checkConnection(getActivity())) { + if (isAdded()) { + mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); + mIsSocialLogin = true; + mLoginListener.addGoogleLoginFragment(); + } else { + AppLog.e(T.NUX, "Google login could not be started. LoginEmailFragment was not attached."); + showErrorDialog(getString(R.string.login_error_generic_start)); + } + } + } + @Override protected void onHelp() { if (mLoginListener != null) { @@ -315,6 +387,7 @@ public void onCreate(Bundle savedInstanceState) { mLoginSiteUrl = args.getString(ARG_LOGIN_SITE_URL, ""); mIsSignupFromLoginEnabled = args.getBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, false); mIsSiteLoginEnabled = args.getBoolean(ARG_SITE_LOGIN_ENABLED, true); + mShouldUseNewLayout = args.getBoolean(ARG_SHOULD_USE_NEW_LAYOUT, false); } } @@ -373,59 +446,9 @@ public void onSaveInstanceState(Bundle outState) { } } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = super.onCreateView(inflater, container, savedInstanceState); - if (mIsUnifiedLoginEnabled && rootView != null) { - // Hide all unused views - rootView.findViewById(R.id.bottom_buttons).setVisibility(View.GONE); - rootView.findViewById(R.id.login_alternatively_label).setVisibility(View.GONE); - rootView.findViewById(R.id.login_google_button).setVisibility(View.GONE); - // Show the new UX - rootView.findViewById(R.id.third_party_buttons).setVisibility(View.VISIBLE); - Button continueButton = rootView.findViewById(R.id.login_continue_button); - continueButton.setVisibility(View.VISIBLE); - continueButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - next(getCleanedEmail()); - } - }); - Button continueTos = rootView.findViewById(R.id.continue_tos); - Button continueWithGoogleTosText = rootView.findViewById(R.id.continue_with_google_tos); - continueTos.setVisibility(View.VISIBLE); - - OnClickListener onClickListener = new OnClickListener() { - public void onClick(View view) { - Context context = getContext(); - if ((context instanceof SignupSheetListener)) { - ((SignupSheetListener) context).onSignupSheetTermsOfServiceClicked(); - } - } - }; - continueTos.setOnClickListener(onClickListener); - continueWithGoogleTosText.setOnClickListener(onClickListener); - Resources resources = rootView - .getContext() - .getResources(); - continueTos.setText(Html.fromHtml( - String.format(resources.getString(R.string.continue_terms_of_service_text), "", ""))); - continueWithGoogleTosText.setText(Html.fromHtml( - String.format(resources.getString(R.string.continue_with_google_terms_of_service_text), "", - ""))); - Button continueWithGoogleButton = rootView.findViewById(R.id.continue_with_google); - continueWithGoogleButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - onGoogleSigninClicked(); - } - }); - } - return rootView; - } - @Override protected void buildToolbar(Toolbar toolbar, ActionBar actionBar) { - if (mIsUnifiedLoginEnabled) { + if (mShouldUseNewLayout) { actionBar.setTitle(R.string.get_started); } else { super.buildToolbar(toolbar, actionBar); diff --git a/libs/login/src/main/res/color/material_on_surface_emphasis_low.xml b/libs/login/src/main/res/color/material_on_surface_emphasis_low.xml index 27396552286..bf8f29b1df0 100644 --- a/libs/login/src/main/res/color/material_on_surface_emphasis_low.xml +++ b/libs/login/src/main/res/color/material_on_surface_emphasis_low.xml @@ -1,4 +1,4 @@ - + diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index 000b93f5b15..25f8c491aab 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -1,125 +1,97 @@ - + android:orientation="vertical"> - - + android:inputType="textEmailAddress" /> - + - + android:layout_marginBottom="@dimen/margin_small_medium"> - + - + android:layout_gravity="center_horizontal" + android:paddingStart="@dimen/margin_small" + android:paddingEnd="@dimen/margin_small" + android:text="@string/login_or" /> - + - + android:layout_marginEnd="@dimen/margin_extra_large" + android:layout_marginStart="@dimen/margin_extra_large" + android:text="@string/continue_google_button_suffix" + android:visibility="visible" + app:icon="@drawable/ic_google_60dp" + app:iconGravity="textStart" + app:iconPadding="@dimen/margin_small_medium" + app:iconSize="14dp" + app:iconTint="@null" /> - - - - - + diff --git a/libs/login/src/main/res/layout/login_email_screen_old.xml b/libs/login/src/main/res/layout/login_email_screen_old.xml new file mode 100644 index 00000000000..b2eb2db0f31 --- /dev/null +++ b/libs/login/src/main/res/layout/login_email_screen_old.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/login/src/main/res/layout/login_form_screen.xml b/libs/login/src/main/res/layout/login_form_screen.xml index a86fa9399db..7f6ded87500 100644 --- a/libs/login/src/main/res/layout/login_form_screen.xml +++ b/libs/login/src/main/res/layout/login_form_screen.xml @@ -12,7 +12,7 @@ android:id="@+id/scroll_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_above="@+id/bottom_container" + android:layout_above="@+id/bottom_buttons" android:layout_below="@+id/toolbar_container"> - - - - + android:clipToPadding="false" + android:paddingStart="@dimen/margin_small_medium" + android:paddingTop="@dimen/margin_medium_large" + android:paddingEnd="@dimen/margin_medium_large" + android:paddingBottom="@dimen/margin_medium_large"> - + android:paddingRight="@dimen/margin_medium_large" + android:textAlignment="viewStart" + tools:text="Secondary action" /> - - - - - - + + + diff --git a/libs/login/src/main/res/layout/login_third_party_block.xml b/libs/login/src/main/res/layout/login_third_party_block.xml deleted file mode 100644 index a4368e01457..00000000000 --- a/libs/login/src/main/res/layout/login_third_party_block.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/libs/login/src/main/res/menu/menu_login.xml b/libs/login/src/main/res/menu/menu_login.xml index 8e3a117e35e..4c34dcd5fb9 100644 --- a/libs/login/src/main/res/menu/menu_login.xml +++ b/libs/login/src/main/res/menu/menu_login.xml @@ -1,12 +1,11 @@ - - + app:iconTint="?attr/colorControlNormal" + app:showAsAction="always" /> diff --git a/libs/login/src/main/res/values/dimens.xml b/libs/login/src/main/res/values/dimens.xml index daaf6ff0d2b..56f795eb012 100644 --- a/libs/login/src/main/res/values/dimens.xml +++ b/libs/login/src/main/res/values/dimens.xml @@ -1,6 +1,7 @@ + 0.12 72dp 0dp From fb4afef770d46a7e0e0715b225163073f9e1bc26 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 26 May 2020 01:21:02 -0300 Subject: [PATCH 448/888] Update base form layout --- .../android/login/LoginBaseFormFragment.java | 10 +++++ .../login/LoginUsernamePasswordFragment.java | 4 +- .../main/res/layout/login_email_screen.xml | 18 +++++--- .../res/layout/login_email_screen_old.xml | 7 +-- .../src/main/res/layout/login_form_screen.xml | 44 +++++++++---------- 5 files changed, 45 insertions(+), 38 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index 72483c6e5c7..6f9b7367240 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -12,6 +12,7 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; import android.view.ViewStub; import android.widget.Button; import android.widget.EditText; @@ -116,6 +117,15 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mSecondaryButton = (Button) rootView.findViewById(R.id.secondary_button); setupBottomButtons(mSecondaryButton, mPrimaryButton); + // Set the primary button width to match_parent if the secondary button doesn't exist or isn't visible. + // This can be removed after we get rid of the unified flow feature flag. + if ((mSecondaryButton == null || mSecondaryButton.getVisibility() == View.GONE) + && (mPrimaryButton != null && mPrimaryButton.getVisibility() == View.VISIBLE)) { + final LayoutParams layoutParams = mPrimaryButton.getLayoutParams(); + layoutParams.width = LayoutParams.MATCH_PARENT; + mPrimaryButton.setLayoutParams(layoutParams); + } + return rootView; } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index b15eb5b2937..49e0b46ce1b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -12,12 +12,12 @@ import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; -import android.widget.ScrollView; import android.widget.TextView; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.widget.NestedScrollView; import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; @@ -72,7 +72,7 @@ public class LoginUsernamePasswordFragment extends LoginBaseDiscoveryFragment im public static final String TAG = "login_username_password_fragment_tag"; - private ScrollView mScrollView; + private NestedScrollView mScrollView; private WPLoginInputRow mUsernameInput; private WPLoginInputRow mPasswordInput; diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index 25f8c491aab..c9a6e58c73f 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -3,8 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/margin_extra_large" + android:layout_height="match_parent" android:orientation="vertical"> + android:inputType="textEmailAddress" + tools:ignore="UnusedAttribute" /> + + diff --git a/libs/login/src/main/res/layout/login_email_screen_old.xml b/libs/login/src/main/res/layout/login_email_screen_old.xml index b2eb2db0f31..2844ae06d7b 100644 --- a/libs/login/src/main/res/layout/login_email_screen_old.xml +++ b/libs/login/src/main/res/layout/login_email_screen_old.xml @@ -1,11 +1,9 @@ - @@ -15,7 +13,6 @@ style="@style/Widget.LoginFlow.TextView.Label" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/margin_extra_large" android:layout_marginBottom="@dimen/margin_extra_large" android:gravity="start" android:textAlignment="viewStart" @@ -36,7 +33,7 @@ - + android:layout_below="@+id/toolbar_container" + android:fillViewport="true"> - - + android:layout_height="match_parent" + android:layout_marginBottom="@dimen/margin_extra_large" + android:layout_marginTop="@dimen/margin_extra_large" /> + - + android:gravity="center_vertical"> - + android:layout_marginBottom="@dimen/margin_medium_large" + android:layout_marginEnd="@dimen/margin_extra_large" + android:layout_marginStart="@dimen/margin_extra_large" + android:layout_marginTop="@dimen/margin_medium_large" + android:text="@string/login_continue" /> + From 29a6bea13c5ce1dc5e547d67d67802f4fbf14cb2 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Wed, 13 May 2020 09:56:19 -0300 Subject: [PATCH 449/888] UI update to Magic Link Request screen --- .../login/LoginMagicLinkRequestFragment.java | 5 +- .../login_magic_link_request_screen.xml | 86 ---------------- .../login_magic_link_request_screen.xml | 97 +++++++++++-------- libs/login/src/main/res/values/strings.xml | 4 +- 4 files changed, 61 insertions(+), 131 deletions(-) delete mode 100644 libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index fd554f05545..232aab49895 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -151,6 +151,9 @@ public void onClick(View v) { mAvatarProgressBar = view.findViewById(R.id.avatar_progress); ImageView avatarView = view.findViewById(R.id.gravatar); + TextView emailView = view.findViewById(R.id.email); + emailView.setText(mEmail); + // Design changes added to the Woo Magic link sign-in if (mVerifyMagicLinkEmail) { View avatarContainerView = view.findViewById(R.id.avatar_container); @@ -205,7 +208,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); if (actionBar != null) { - actionBar.setDisplayShowTitleEnabled(false); + actionBar.setTitle(R.string.log_in); actionBar.setDisplayHomeAsUpEnabled(true); } diff --git a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml deleted file mode 100644 index 6983da02b7f..00000000000 --- a/libs/login/src/main/res/layout-land/login_magic_link_request_screen.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/login/src/main/res/layout/login_magic_link_request_screen.xml b/libs/login/src/main/res/layout/login_magic_link_request_screen.xml index e3f5251b0e9..95c644e7b08 100644 --- a/libs/login/src/main/res/layout/login_magic_link_request_screen.xml +++ b/libs/login/src/main/res/layout/login_magic_link_request_screen.xml @@ -7,74 +7,85 @@ - + android:layout_height="wrap_content" + android:orientation="vertical"> + + - + - + + + + + - - - + android:paddingStart="@dimen/margin_extra_large" + android:paddingEnd="@dimen/margin_extra_large" + android:text="@string/email_address" /> + - - + android:paddingEnd="@dimen/margin_none" + android:paddingStart="@dimen/margin_none" + android:text="@string/or_type_your_password" /> - + + + diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 5dc5992e934..b6520d036cb 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -4,8 +4,10 @@ Verification code Invalid verification code Send link + Send link by email Send verification email Enter your password instead + Or type your password Username Password Help @@ -28,7 +30,7 @@ Requesting a verification code via SMS. Hmm, we can\'t find a WordPress.com account connected to this email address. Try the link below to log in using your site address. It looks like this password is incorrect. Please double check your information and try again. - We\'ll email you a magic link that\'ll log you in instantly, no password needed. Hunt and peck no more! + We\'ll email you a magic link that\'ll log you in instantly, no password needed. Almost there! We just need to verify your Jetpack connected email address <b>%1$s</b> Your magic link is on its way! Check your email on this device and tap the link in the email you received from WordPress.com. Requesting log-in email From 525efd21c08c8d4006bb5645a6218cb80e9533eb Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 26 May 2020 16:04:39 -0300 Subject: [PATCH 450/888] Extract magic link header to a separate layout file --- .../res/layout/login_include_email_header.xml | 36 +++++++++++++++ .../login_magic_link_request_screen.xml | 46 +++---------------- 2 files changed, 43 insertions(+), 39 deletions(-) create mode 100644 libs/login/src/main/res/layout/login_include_email_header.xml diff --git a/libs/login/src/main/res/layout/login_include_email_header.xml b/libs/login/src/main/res/layout/login_include_email_header.xml new file mode 100644 index 00000000000..4d76f49a7d6 --- /dev/null +++ b/libs/login/src/main/res/layout/login_include_email_header.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + diff --git a/libs/login/src/main/res/layout/login_magic_link_request_screen.xml b/libs/login/src/main/res/layout/login_magic_link_request_screen.xml index 95c644e7b08..8b25988d2a9 100644 --- a/libs/login/src/main/res/layout/login_magic_link_request_screen.xml +++ b/libs/login/src/main/res/layout/login_magic_link_request_screen.xml @@ -14,51 +14,22 @@ + android:orientation="vertical" + android:paddingEnd="@dimen/margin_extra_large" + android:paddingStart="@dimen/margin_extra_large"> - - - - - - - - - - - + android:layout_marginTop="@dimen/margin_extra_large" /> From 6e001c1f897b854c4d5cd3b5ccb3df7ff37a864b Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 26 May 2020 17:05:35 -0300 Subject: [PATCH 451/888] Update Login Magic Link Sent screen --- .../login/LoginMagicLinkSentFragment.java | 42 +++++++++- .../login_magic_link_sent_screen.xml | 77 ------------------ .../layout/login_magic_link_sent_screen.xml | 79 ++++++++++++------- libs/login/src/main/res/values/strings.xml | 4 +- 4 files changed, 94 insertions(+), 108 deletions(-) delete mode 100644 libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java index 54ce0dc1aa1..02a51aa15da 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java @@ -1,6 +1,7 @@ package org.wordpress.android.login; import android.content.Context; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; @@ -8,6 +9,8 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; @@ -15,6 +18,15 @@ import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.Target; + +import org.wordpress.android.util.GravatarUtils; + import javax.inject.Inject; import dagger.android.support.AndroidSupportInjection; @@ -70,6 +82,34 @@ public void onClick(View v) { } }); + final View avatarProgressBar = view.findViewById(R.id.avatar_progress); + ImageView avatarView = view.findViewById(R.id.gravatar); + + TextView emailView = view.findViewById(R.id.email); + emailView.setText(mEmail); + + Glide.with(this) + .load(GravatarUtils.gravatarFromEmail(mEmail, + getContext().getResources().getDimensionPixelSize(R.dimen.avatar_sz_login))) + .apply(RequestOptions.circleCropTransform()) + .apply(RequestOptions.placeholderOf(R.drawable.ic_gridicons_user_circle_100dp)) + .apply(RequestOptions.errorOf(R.drawable.ic_gridicons_user_circle_100dp)) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, Target target, boolean b) { + avatarProgressBar.setVisibility(View.GONE); + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, Target target, + DataSource dataSource, boolean b) { + avatarProgressBar.setVisibility(View.GONE); + return false; + } + }) + .into(avatarView); + return view; } @@ -82,7 +122,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); if (actionBar != null) { - actionBar.setDisplayShowTitleEnabled(false); + actionBar.setTitle(R.string.log_in); actionBar.setDisplayHomeAsUpEnabled(true); } diff --git a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml b/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml deleted file mode 100644 index afe1b4010e1..00000000000 --- a/libs/login/src/main/res/layout-land/login_magic_link_sent_screen.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml b/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml index 9d0e6227f42..504ddb57b72 100644 --- a/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml +++ b/libs/login/src/main/res/layout/login_magic_link_sent_screen.xml @@ -1,44 +1,65 @@ - - - + android:layout_height="0dp" + android:layout_weight="1" + android:overScrollMode="never"> + + + + + + + + + + + + + + - - + android:layout_marginBottom="@dimen/margin_medium_large" + android:layout_marginEnd="@dimen/margin_extra_large" + android:layout_marginStart="@dimen/margin_extra_large" + android:layout_marginTop="@dimen/margin_medium_large" + android:text="@string/check_email" /> diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index b6520d036cb..64de62f5b6b 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -19,6 +19,7 @@ Get Started Next Open mail + Check email Alternatively: Log in by entering your site address. Log in with site credentials @@ -32,8 +33,9 @@ It looks like this password is incorrect. Please double check your information and try again. We\'ll email you a magic link that\'ll log you in instantly, no password needed. Almost there! We just need to verify your Jetpack connected email address <b>%1$s</b> - Your magic link is on its way! Check your email on this device and tap the link in the email you received from WordPress.com. + Check your email on this device and tap the link in the email you received from WordPress.com. Requesting log-in email + Not seeing the email? Check your Spam or Junk Mail folder. Currently unavailable. Please enter your password Enter your WordPress.com password. To proceed with this Google account, please provide the matching WordPress.com password. This will be asked only once. From 368fb8fa7eeccf4a4f17c1bb7043c7707cb746e2 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 26 May 2020 19:01:48 -0300 Subject: [PATCH 452/888] Update Login Email Password screen --- .../login/LoginEmailPasswordFragment.java | 62 ++++++++++++++-- .../layout/login_email_password_screen.xml | 73 +++++-------------- libs/login/src/main/res/values/strings.xml | 1 + 3 files changed, 77 insertions(+), 59 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index e32c9a12ebe..bbeb50d55ab 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -1,6 +1,7 @@ package org.wordpress.android.login; import android.content.Context; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; @@ -10,11 +11,22 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; +import android.widget.ImageView; +import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.widget.Toolbar; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.Target; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -26,6 +38,7 @@ import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; import org.wordpress.android.util.AutoForeground; +import org.wordpress.android.util.GravatarUtils; import org.wordpress.android.util.NetworkUtils; import org.wordpress.android.util.ToastUtils; import org.wordpress.android.util.ToastUtils.Duration; @@ -145,16 +158,11 @@ protected void setupLabel(@NonNull TextView label) { protected void setupContent(ViewGroup rootView) { // important for accessibility - talkback getActivity().setTitle(R.string.selfhosted_site_login_title); - ((TextView) rootView.findViewById(R.id.login_email)).setText(mEmailAddress); mPasswordInput = rootView.findViewById(R.id.login_password_row); mPasswordInput.setOnEditorCommitListener(this); - } - @Override - protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { - secondaryButton.setText(R.string.forgot_password); - secondaryButton.setOnClickListener(new OnClickListener() { + rootView.findViewById(R.id.login_reset_password).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mLoginListener != null) { @@ -162,6 +170,48 @@ public void onClick(View v) { } } }); + + final ProgressBar avatarProgressBar = rootView.findViewById(R.id.avatar_progress); + final ImageView avatarView = rootView.findViewById(R.id.gravatar); + final TextView emailView = rootView.findViewById(R.id.email); + + emailView.setText(mEmailAddress); + + Glide.with(this) + .load(GravatarUtils.gravatarFromEmail(mEmailAddress, + getContext().getResources().getDimensionPixelSize(R.dimen.avatar_sz_login))) + .apply(RequestOptions.circleCropTransform()) + .apply(RequestOptions.placeholderOf(R.drawable.ic_gridicons_user_circle_100dp)) + .apply(RequestOptions.errorOf(R.drawable.ic_gridicons_user_circle_100dp)) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, Target target, + boolean b) { + avatarProgressBar.setVisibility(View.GONE); + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, Target target, + DataSource dataSource, boolean b) { + avatarProgressBar.setVisibility(View.GONE); + return false; + } + }) + .into(avatarView); + } + + @Override + protected void buildToolbar(Toolbar toolbar, ActionBar actionBar) { + actionBar.setTitle(R.string.log_in); + } + + @Override + protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { + if (secondaryButton != null) { + secondaryButton.setVisibility(View.GONE); + } + primaryButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { next(); diff --git a/libs/login/src/main/res/layout/login_email_password_screen.xml b/libs/login/src/main/res/layout/login_email_password_screen.xml index 8fa16926171..9ed913cf776 100644 --- a/libs/login/src/main/res/layout/login_email_password_screen.xml +++ b/libs/login/src/main/res/layout/login_email_password_screen.xml @@ -4,12 +4,15 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginBottom="@dimen/margin_extra_large" android:orientation="vertical" - android:paddingStart="@dimen/margin_extra_large" - android:paddingLeft="@dimen/margin_extra_large" android:paddingEnd="@dimen/margin_extra_large" - android:paddingRight="@dimen/margin_extra_large"> + android:paddingStart="@dimen/margin_extra_large"> + + - - - - - - - - - - - - + android:visibility="gone" + tools:text="@string/enter_wpcom_password" + tools:visibility="visible" /> + app:passwordToggleEnabled="true" /> + + diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 64de62f5b6b..c6469daf32c 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -102,6 +102,7 @@ Please log in using your WordPress.com username instead of your email address. Logging in Lost your password? + Reset your password An error occurred The site at this address is not a WordPress site. For us to connect to it, the site must use WordPress. Check that the site URL entered is valid From da87e3017a00c017db4fddfbe3a1ddaffb633c25 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 26 May 2020 20:13:54 -0300 Subject: [PATCH 453/888] Update Login 2FA screen --- .../android/login/Login2FaFragment.java | 25 ++++++++++++------- .../src/main/res/layout/login_2fa_screen.xml | 20 +++++++++------ libs/login/src/main/res/values/strings.xml | 4 +-- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 96b2baab5a1..b74ebf37f84 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -18,7 +18,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; +import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.Toolbar; import com.google.android.material.dialog.MaterialAlertDialogBuilder; @@ -89,7 +91,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple ArrayList mOldSitesIDs; - private Button mSecondaryButton; + private Button mOtpButton; private String mEmailAddress; private String mIdToken; private String mNonce; @@ -172,12 +174,10 @@ protected void setupContent(ViewGroup rootView) { // restrict the allowed input chars to just numbers m2FaInput.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789")); - } - @Override - protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { - secondaryButton.setText(R.string.login_text_otp); - secondaryButton.setOnClickListener(new OnClickListener() { + mOtpButton = rootView.findViewById(R.id.login_otp_button); + mOtpButton.setText(mSentSmsCode ? R.string.login_text_otp_another : R.string.login_text_otp); + mOtpButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (isAdded()) { @@ -185,9 +185,11 @@ public void onClick(View v) { } } }); - secondaryButton.setText(getString(mSentSmsCode ? R.string.login_text_otp_another : R.string.login_text_otp)); - mSecondaryButton = secondaryButton; + } + @Override + protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { + secondaryButton.setVisibility(View.GONE); primaryButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { next(); @@ -195,6 +197,11 @@ public void onClick(View v) { }); } + @Override + protected void buildToolbar(Toolbar toolbar, ActionBar actionBar) { + actionBar.setTitle(R.string.log_in); + } + @Override protected EditText getEditTextToFocusOnStart() { return m2FaInput.getEditText(); @@ -514,7 +521,7 @@ protected void onLoginFinished() { private void setTextForSms() { mLabel.setText(getString(R.string.enter_verification_code_sms, mPhoneNumber)); - mSecondaryButton.setText(getString(R.string.login_text_otp_another)); + mOtpButton.setText(getString(R.string.login_text_otp_another)); mSentSmsCode = true; } } diff --git a/libs/login/src/main/res/layout/login_2fa_screen.xml b/libs/login/src/main/res/layout/login_2fa_screen.xml index c0c95e0855e..b6aa8734ed4 100644 --- a/libs/login/src/main/res/layout/login_2fa_screen.xml +++ b/libs/login/src/main/res/layout/login_2fa_screen.xml @@ -1,20 +1,17 @@ + android:paddingStart="@dimen/margin_extra_large"> @@ -23,5 +20,14 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/verification_code" - android:inputType="numberDecimal"/> + android:inputType="numberDecimal" /> + + diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index c6469daf32c..2bf36e3a8b4 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -26,8 +26,8 @@ Log in with your username. Almost there! Please enter the verification code from your Authenticator app. We sent a text message to the phone number ending in %s. Please enter the verification code in the SMS. - Text me a code instead. - Text me another code instead. + Text me a code instead + Text me another code instead Requesting a verification code via SMS. Hmm, we can\'t find a WordPress.com account connected to this email address. Try the link below to log in using your site address. It looks like this password is incorrect. Please double check your information and try again. From 96abd60a23f630255342c599c61ff3bc413c8167 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 26 May 2020 20:48:10 -0300 Subject: [PATCH 454/888] Update Login Site Address screen --- .../login/LoginEmailPasswordFragment.java | 5 +---- .../login/LoginSiteAddressFragment.java | 18 +++++++++++----- .../res/layout/login_site_address_screen.xml | 21 ++++++++++--------- libs/login/src/main/res/values/strings.xml | 1 + 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index bbeb50d55ab..b269c3afac1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -208,10 +208,7 @@ protected void buildToolbar(Toolbar toolbar, ActionBar actionBar) { @Override protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { - if (secondaryButton != null) { - secondaryButton.setVisibility(View.GONE); - } - + secondaryButton.setVisibility(View.GONE); primaryButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { next(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index a1b47247241..41a8ae40fa1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -16,6 +16,8 @@ import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.widget.Toolbar; import androidx.lifecycle.Observer; import org.greenrobot.eventbus.Subscribe; @@ -93,17 +95,18 @@ protected void setupContent(ViewGroup rootView) { } mSiteAddressInput.addTextChangedListener(this); mSiteAddressInput.setOnEditorCommitListener(this); - } - @Override - protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { - secondaryButton.setText(R.string.login_site_address_help); - secondaryButton.setOnClickListener(new OnClickListener() { + rootView.findViewById(R.id.login_site_address_help_button).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showSiteAddressHelp(); } }); + } + + @Override + protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { + secondaryButton.setVisibility(View.GONE); primaryButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { discover(); @@ -111,6 +114,11 @@ public void onClick(View v) { }); } + @Override + protected void buildToolbar(Toolbar toolbar, ActionBar actionBar) { + actionBar.setTitle(R.string.log_in); + } + @Override protected EditText getEditTextToFocusOnStart() { return mSiteAddressInput.getEditText(); diff --git a/libs/login/src/main/res/layout/login_site_address_screen.xml b/libs/login/src/main/res/layout/login_site_address_screen.xml index 35a55d85d59..fc5c3dd0ac2 100644 --- a/libs/login/src/main/res/layout/login_site_address_screen.xml +++ b/libs/login/src/main/res/layout/login_site_address_screen.xml @@ -3,31 +3,32 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/margin_extra_large" android:orientation="vertical" - android:paddingStart="@dimen/margin_extra_large" - android:paddingLeft="@dimen/margin_extra_large" android:paddingEnd="@dimen/margin_extra_large" - android:paddingRight="@dimen/margin_extra_large"> + android:paddingStart="@dimen/margin_extra_large"> + android:inputType="textUri" /> + + diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 2bf36e3a8b4..ae0695752dd 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -51,6 +51,7 @@ What\'s my site address? Your site address appears in the bar at the top of the screen when you visit your site in Chrome. Need more help? + Find your site address Checking site address Error while adding site. Error code: %s Log in to WordPress.com to access the post. From 07984dca785f846bd46f3c38f55e6d873cb2fdde Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Wed, 27 May 2020 16:20:46 -0300 Subject: [PATCH 455/888] Update Login Username Password screen --- .../login/LoginUsernamePasswordFragment.java | 53 ++++----- .../layout/login_username_password_screen.xml | 106 +++--------------- libs/login/src/main/res/values/strings.xml | 1 + libs/login/src/main/res/values/styles.xml | 8 -- 4 files changed, 34 insertions(+), 134 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index 49e0b46ce1b..1ce08080161 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -11,17 +11,15 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; -import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.widget.Toolbar; import androidx.core.widget.NestedScrollView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.request.RequestOptions; - import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder; @@ -43,6 +41,7 @@ import org.wordpress.android.util.AppLog.T; import org.wordpress.android.util.EditTextUtils; import org.wordpress.android.util.NetworkUtils; +import org.wordpress.android.util.StringUtils; import org.wordpress.android.util.ToastUtils; import org.wordpress.android.util.UrlUtils; @@ -123,9 +122,11 @@ public static LoginUsernamePasswordFragment newInstance(String inputSiteAddress, @Override protected void setupLabel(@NonNull TextView label) { - if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { - label.setText(getString(R.string.enter_credentials_for_site, mInputSiteAddress)); - } + final boolean isWoo = mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE; + final int labelResId = isWoo ? R.string.enter_credentials_for_site : R.string.enter_account_info_for_site; + final String formattedSiteAddress = + UrlUtils.removeScheme(UrlUtils.removeXmlrpcSuffix(StringUtils.notNullStr(mInputSiteAddress))); + label.setText(getString(labelResId, formattedSiteAddress)); } @Override @@ -134,28 +135,6 @@ protected void setupContent(ViewGroup rootView) { getActivity().setTitle(R.string.selfhosted_site_login_title); mScrollView = rootView.findViewById(R.id.scroll_view); - rootView.findViewById(R.id.login_site_title_static).setVisibility(mIsWpcom ? View.GONE : View.VISIBLE); - rootView.findViewById(R.id.login_blavatar_static).setVisibility(mIsWpcom ? View.GONE : View.VISIBLE); - rootView.findViewById(R.id.login_blavatar).setVisibility(mIsWpcom ? View.VISIBLE : View.GONE); - rootView.findViewById(R.id.label).setVisibility( - (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) ? View.VISIBLE : View.GONE); - - if (mSiteIconUrl != null) { - Glide.with(this) - .load(mSiteIconUrl) - .apply(RequestOptions.placeholderOf(R.drawable.ic_placeholder_blavatar_grey_lighten_20_40dp)) - .apply(RequestOptions.errorOf(R.drawable.ic_placeholder_blavatar_grey_lighten_20_40dp)) - .into(((ImageView) rootView.findViewById(R.id.login_blavatar))); - } - - TextView siteNameView = (rootView.findViewById(R.id.login_site_title)); - siteNameView.setText(mSiteName); - siteNameView.setVisibility(mSiteName != null ? View.VISIBLE : View.GONE); - - TextView siteAddressView = (rootView.findViewById(R.id.login_site_address)); - siteAddressView.setText(UrlUtils.removeScheme(UrlUtils.removeXmlrpcSuffix(mInputSiteAddress))); - siteAddressView.setVisibility(mInputSiteAddress != null ? View.VISIBLE : View.GONE); - String inputSiteAddressWithoutProtocol = UrlUtils.removeScheme(mInputSiteAddress); mInputSiteAddressWithoutSuffix = (mEndpointAddress == null || mEndpointAddress.isEmpty()) ? inputSiteAddressWithoutProtocol : UrlUtils.removeXmlrpcSuffix(mEndpointAddress); @@ -182,12 +161,8 @@ public void onEditorCommit() { mPasswordInput.addTextChangedListener(this); mPasswordInput.setOnEditorCommitListener(this); - } - @Override - protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { - secondaryButton.setText(R.string.forgot_password); - secondaryButton.setOnClickListener(new OnClickListener() { + rootView.findViewById(R.id.login_reset_password).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mLoginListener != null) { @@ -199,6 +174,11 @@ public void onClick(View v) { } } }); + } + + @Override + protected void setupBottomButtons(Button secondaryButton, Button primaryButton) { + secondaryButton.setVisibility(View.GONE); primaryButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { next(); @@ -206,6 +186,11 @@ public void onClick(View v) { }); } + @Override + protected void buildToolbar(Toolbar toolbar, ActionBar actionBar) { + actionBar.setTitle(R.string.log_in); + } + @Override protected EditText getEditTextToFocusOnStart() { return mUsernameInput.getEditText(); diff --git a/libs/login/src/main/res/layout/login_username_password_screen.xml b/libs/login/src/main/res/layout/login_username_password_screen.xml index 5aa316c7092..890485da7d7 100644 --- a/libs/login/src/main/res/layout/login_username_password_screen.xml +++ b/libs/login/src/main/res/layout/login_username_password_screen.xml @@ -4,120 +4,42 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/margin_extra_large" android:orientation="vertical" - android:paddingStart="@dimen/margin_extra_large" - android:paddingLeft="@dimen/margin_extra_large" android:paddingEnd="@dimen/margin_extra_large" - android:paddingRight="@dimen/margin_extra_large"> + android:paddingStart="@dimen/margin_extra_large"> - - - - - - - - - - - - - - - - - - - + tools:text="Enter your account information for pamelanguyen.com." /> + android:inputType="textPersonName" /> + app:passwordToggleEnabled="true" /> + + + diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index ae0695752dd..78afaa273f6 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -16,6 +16,7 @@ Enter your email address to log in or create a WordPress.com account. Log in with WordPress.com to connect to %1$s Log in with your %1$s site credentials + Enter your account information for %1$s. Get Started Next Open mail diff --git a/libs/login/src/main/res/values/styles.xml b/libs/login/src/main/res/values/styles.xml index 92368f68bf9..8d166bc5331 100644 --- a/libs/login/src/main/res/values/styles.xml +++ b/libs/login/src/main/res/values/styles.xml @@ -117,12 +117,4 @@ 0dp - - - From 6f6a4a572b099d3ee4783fa7326d45e5f5ab4e0d Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Fri, 10 Jul 2020 13:51:27 +0200 Subject: [PATCH 480/888] Disable continue button when email is empty --- .../wordpress/android/login/LoginEmailFragment.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index d367ebda20b..b563e2e236a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -219,6 +219,15 @@ public void onClick(View view) { }); } + private void updateContinueButtonEnabledStatus() { + View view = getView(); + if (view != null) { + Button continueButton = (Button) view.findViewById(R.id.login_continue_button); + String currentEmail = mEmailInput.getEditText().getText().toString(); + continueButton.setEnabled(!currentEmail.trim().isEmpty()); + } + } + private void setupTosButtons(Button continueTosButton, Button continueWithGoogleTosButton) { OnClickListener onClickListener = new OnClickListener() { public void onClick(View view) { @@ -447,6 +456,7 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { public void onResume() { super.onResume(); mAnalyticsListener.emailFormScreenResumed(); + updateContinueButtonEnabledStatus(); } @Override @@ -537,6 +547,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { mEmailInput.setError(null); mIsSocialLogin = false; clearEmailError(); + updateContinueButtonEnabledStatus(); } private void showEmailError(int messageId) { From 0f5a4dd22ffa9e9e5daa42532cbcf0d5566c781f Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Fri, 10 Jul 2020 14:01:50 +0200 Subject: [PATCH 481/888] Disable primary button when password is not filled in --- .../android/login/LoginEmailPasswordFragment.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 9988f713be6..95ff0edeac1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -109,6 +109,7 @@ public void onCreate(Bundle savedInstanceState) { @Override public void onResume() { super.onResume(); + updatePrimaryButtonEnabledStatus(); // connect to the Service. We'll receive updates via EventBus. mServiceEventConnection = new AutoForeground.ServiceEventConnection(getContext(), @@ -127,6 +128,15 @@ public void onPause() { mServiceEventConnection.disconnect(getContext(), this); } + private void updatePrimaryButtonEnabledStatus() { + View view = getView(); + if (view != null) { + Button primaryButton = (Button) view.findViewById(R.id.primary_button); + String currentPassword = mPasswordInput.getEditText().getText().toString(); + primaryButton.setEnabled(!currentPassword.trim().isEmpty()); + } + } + @Override protected boolean listenForLogin() { return false; @@ -266,6 +276,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { mPasswordInput.setError(null); LoginWpcomService.clearLoginServiceState(); + updatePrimaryButtonEnabledStatus(); } private void showPasswordError() { From 9d8abee8e6cda8af28dec1030555c9066b6aa4d5 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Fri, 10 Jul 2020 14:46:19 +0200 Subject: [PATCH 482/888] Disable primary button when username or password are missing --- .../android/login/LoginEmailPasswordFragment.java | 3 +-- .../login/LoginUsernamePasswordFragment.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 95ff0edeac1..ede7c31c65f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -131,9 +131,8 @@ public void onPause() { private void updatePrimaryButtonEnabledStatus() { View view = getView(); if (view != null) { - Button primaryButton = (Button) view.findViewById(R.id.primary_button); String currentPassword = mPasswordInput.getEditText().getText().toString(); - primaryButton.setEnabled(!currentPassword.trim().isEmpty()); + getPrimaryButton().setEnabled(!currentPassword.trim().isEmpty()); } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index 0f28c52166a..1dc483319c8 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -261,6 +261,20 @@ public void onSaveInstanceState(Bundle outState) { outState.putBoolean(KEY_GET_SITE_OPTIONS_INITIATED, mGetSiteOptionsInitiated); } + @Override public void onResume() { + super.onResume(); + updatePrimaryButtonEnabledStatus(); + } + + private void updatePrimaryButtonEnabledStatus() { + View view = getView(); + if (view != null) { + String currentUsername = mUsernameInput.getEditText().getText().toString(); + String currentPassword = mPasswordInput.getEditText().getText().toString(); + getPrimaryButton().setEnabled(!currentPassword.trim().isEmpty() && !currentUsername.trim().isEmpty()); + } + } + protected void next() { mAnalyticsListener.trackSubmitClicked(); if (!NetworkUtils.checkConnection(getActivity())) { @@ -335,6 +349,7 @@ public void beforeTextChanged(CharSequence s, int start, int count, int after) { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { showError(null); + updatePrimaryButtonEnabledStatus(); } @Override From e39e0d751c61f9f7e2f05dd09860b25d9357a19d Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 10 Jul 2020 21:44:16 -0300 Subject: [PATCH 483/888] Update placeholder color to ensure compatibility on older API levels --- .../res/drawable/ic_user_circle_no_padding_grey_24dp.xml | 2 +- libs/login/src/main/res/values-night/colors.xml | 6 ++++++ libs/login/src/main/res/values/colors.xml | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 libs/login/src/main/res/values-night/colors.xml diff --git a/libs/login/src/main/res/drawable/ic_user_circle_no_padding_grey_24dp.xml b/libs/login/src/main/res/drawable/ic_user_circle_no_padding_grey_24dp.xml index 8f7dd2de232..fe272c2b53b 100644 --- a/libs/login/src/main/res/drawable/ic_user_circle_no_padding_grey_24dp.xml +++ b/libs/login/src/main/res/drawable/ic_user_circle_no_padding_grey_24dp.xml @@ -4,6 +4,6 @@ android:viewportHeight="24" android:viewportWidth="24"> diff --git a/libs/login/src/main/res/values-night/colors.xml b/libs/login/src/main/res/values-night/colors.xml new file mode 100644 index 00000000000..3a8511ee4e5 --- /dev/null +++ b/libs/login/src/main/res/values-night/colors.xml @@ -0,0 +1,6 @@ + + + + #61FFFFFF + diff --git a/libs/login/src/main/res/values/colors.xml b/libs/login/src/main/res/values/colors.xml index 605ea18071b..2412c4aca54 100644 --- a/libs/login/src/main/res/values/colors.xml +++ b/libs/login/src/main/res/values/colors.xml @@ -14,6 +14,9 @@ #121212 #000000 + + #61121212 From 81a85fad92e4f747262189c1c796a28974a9508c Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Wed, 26 Aug 2020 19:00:59 -0300 Subject: [PATCH 512/888] Update Email screen to disable hint picker dialog if autofill is enabled --- .../android/login/LoginEmailFragment.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 8ee05da5b07..36d6f4d09ac 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentSender; +import android.os.Build; import android.os.Bundle; import android.text.Editable; import android.text.Html; @@ -14,6 +15,7 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.view.autofill.AutofillManager; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; @@ -193,8 +195,7 @@ private void setupEmailInput(WPLoginInputRow emailInput) { public void onFocusChange(View view, boolean hasFocus) { if (hasFocus && !mIsDisplayingEmailHints && !mHasDismissedEmailHints) { mAnalyticsListener.trackSelectEmailField(); - mIsDisplayingEmailHints = true; - getEmailHints(); + showHintPickerDialogIfNeeded(); } } }); @@ -204,8 +205,7 @@ public void onClick(View view) { mAnalyticsListener.trackSelectEmailField(); if (!mIsDisplayingEmailHints && !mHasDismissedEmailHints) { mAnalyticsListener.trackSelectEmailField(); - mIsDisplayingEmailHints = true; - getEmailHints(); + showHintPickerDialogIfNeeded(); } } }); @@ -656,7 +656,22 @@ public void onConnectionSuspended(int i) { AppLog.d(T.NUX, LOG_TAG + ": Google API client connection suspended"); } - public void getEmailHints() { + private void showHintPickerDialogIfNeeded() { + // If autofill is available and enabled, we favor the active autofill service over the hint picker dialog. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + final AutofillManager autofillManager = requireContext().getSystemService(AutofillManager.class); + if (autofillManager != null && autofillManager.isEnabled()) { + AppLog.d(T.NUX, LOG_TAG + ": Autofill framework is enabled. Disabling hint picker dialog."); + return; + } + } + + AppLog.d(T.NUX, LOG_TAG + ": Autofill framework is unavailable or disabled. Showing hint picker dialog."); + + showHintPickerDialog(); + } + + private void showHintPickerDialog() { GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance(); if (getContext() == null || googleApiAvailability.isGooglePlayServicesAvailable(getContext()) != ConnectionResult.SUCCESS) { @@ -674,6 +689,7 @@ public void getEmailHints() { try { startIntentSenderForResult(intent.getIntentSender(), EMAIL_CREDENTIALS_REQUEST_CODE, null, 0, 0, 0, null); + mIsDisplayingEmailHints = true; } catch (IntentSender.SendIntentException exception) { AppLog.d(T.NUX, LOG_TAG + "Could not start email hint picker" + exception); } catch (ActivityNotFoundException exception) { From 7e7ccd3279cb90935a04f652714740ef1cc6abaa Mon Sep 17 00:00:00 2001 From: Klymentiy haykov Date: Wed, 2 Sep 2020 20:07:33 -0700 Subject: [PATCH 513/888] Removed another unused import. --- .../wordpress/android/login/LoginMagicLinkRequestFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index 073aff628c3..2107b326d86 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -21,7 +21,6 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; From a3bbcb59fff1f66d28c177d8a5a5a42d21e787b1 Mon Sep 17 00:00:00 2001 From: Klymentiy haykov Date: Thu, 3 Sep 2020 13:10:55 -0700 Subject: [PATCH 514/888] Made the backstack popping logic be applied to forced request instead of only passwordless. --- .../android/login/LoginMagicLinkRequestFragment.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index 2107b326d86..ccf31cd7586 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -21,6 +21,7 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -352,6 +353,14 @@ public void onAuthEmailSent(OnAuthEmailSent event) { mAnalyticsListener.trackMagicLinkRequested(); if (mLoginListener != null) { + // when magic link request if forced we want to remove this fragment from backstack so user will not be + // able to navigate back to it from "Magic Link Sent" Screen + if (mForceRequestAtStart) { + FragmentManager fragmentManager = getFragmentManager(); + if (fragmentManager != null) { + fragmentManager.popBackStackImmediate(); + } + } mLoginListener.showMagicLinkSentScreen(mEmail, mAllowPassword); } } From 65ad1b84883444563f11a308d7d4ec4dd6307f02 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Wed, 9 Sep 2020 16:10:52 -0300 Subject: [PATCH 515/888] Update signup magic link labels --- libs/login/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 687f9833978..d4384ff8613 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -81,10 +81,10 @@ There was some trouble sending the email. You can retry now or close and try again later. Close Retry - We’ve emailed you a magic 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. + 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. Sending email We’ll use this email address to create your new WordPress.com account. - We’ll email you a magic link to create your new WordPress.com account. + We’ll email you a signup link to create your new WordPress.com account. By signing up, you agree to our %1$sTerms of Service%2$s. By continuing, you agree to our %1$sTerms of Service%2$s. If you continue with Google and don\'t already have a WordPress.com account, you are creating an account and you agree to our %1$sTerms of Service%2$s. From 930e157dad8e775e5e4cbe055ef1ba192c2c9665 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Wed, 9 Sep 2020 16:19:16 -0300 Subject: [PATCH 516/888] Update login magic link labels --- libs/login/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index d4384ff8613..13f91ba8cdb 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -33,7 +33,7 @@ Requesting a verification code via SMS. Hmm, we can\'t find a WordPress.com account connected to this email address. Try the link below to log in using your site address. It looks like this password is incorrect. Please double check your information and try again. - We\'ll email you a magic link that\'ll log you in instantly, no password needed. + We\'ll email you a link that\'ll log you in instantly, no password needed. Almost there! We just need to verify your Jetpack connected email address <b>%1$s</b> Check your email on this device and tap the link in the email you received from WordPress.com. Requesting log-in email From dd21dc019b5eb8f8f01d8ec3e261ff68d9b0121a Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Wed, 9 Sep 2020 18:33:38 -0300 Subject: [PATCH 517/888] Add click tracking to magic link option on the Password screen --- .../org/wordpress/android/login/LoginEmailPasswordFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 1585f17c86f..9bb55e76d74 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -194,6 +194,7 @@ public void onClick(View v) { magicLinkButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mLoginListener != null) { + mAnalyticsListener.trackRequestMagicLinkClick(); mLoginListener.useMagicLinkInstead(mEmailAddress, mVerifyMagicLinkEmail); } } From a476e2f9511ed3d880f7d418fcaa973a793509c4 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Wed, 9 Sep 2020 18:37:50 -0300 Subject: [PATCH 518/888] Move tracking method to correct place --- .../wordpress/android/login/LoginMagicLinkRequestFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index ccf31cd7586..d8d23bdd281 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -136,6 +136,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mRequestMagicLinkButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + mAnalyticsListener.trackRequestMagicLinkClick(); dispatchMagicLinkRequest(); } }); @@ -267,7 +268,6 @@ public void onStop() { } private void dispatchMagicLinkRequest() { - mAnalyticsListener.trackRequestMagicLinkClick(); if (mLoginListener != null) { if (NetworkUtils.checkConnection(getActivity())) { showMagicLinkRequestProgressDialog(); From 25cf46b8b34ba1a73b05d01a8bef7f348a008365 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 10 Sep 2020 20:50:13 -0300 Subject: [PATCH 519/888] Extract method with logic to determine if site has Jetpack --- .../login/LoginSiteAddressFragment.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index ef360e9706d..a861402f5f7 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -28,6 +28,7 @@ import org.wordpress.android.fluxc.network.MemorizingTrustManager; import org.wordpress.android.fluxc.network.discovery.SelfHostedEndpointFinder.DiscoveryError; import org.wordpress.android.fluxc.store.AccountStore; +import org.wordpress.android.fluxc.store.SiteStore.ConnectSiteInfoPayload; import org.wordpress.android.fluxc.store.SiteStore.OnConnectSiteInfoChecked; import org.wordpress.android.fluxc.store.SiteStore.OnWPComSiteFetched; import org.wordpress.android.login.util.SiteUtils; @@ -411,15 +412,8 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { properties.put("is_wordpress", Boolean.toString(event.info.isWordPress)); properties.put("is_wp_com", Boolean.toString(event.info.isWPCom)); - // Determining if jetpack is actually installed takes additional logic. This final - // calculated event property will make querying this event more straight-forward: - boolean hasJetpack = false; - if (event.info.isWPCom && event.info.hasJetpack) { - // This is likely an atomic site. - hasJetpack = true; - } else if (event.info.isJetpackConnected) { - hasJetpack = true; - } + boolean hasJetpack = calculateHasJetpack(event.info); + properties.put("login_calculated_has_jetpack", Boolean.toString(hasJetpack)); mAnalyticsListener.trackConnectedSiteInfoSucceeded(properties); @@ -437,4 +431,17 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { } } } + + private boolean calculateHasJetpack(ConnectSiteInfoPayload siteInfo) { + // Determining if jetpack is actually installed takes additional logic. This final + // calculated event property will make querying this event more straight-forward: + boolean hasJetpack = false; + if (siteInfo.isWPCom && siteInfo.hasJetpack) { + // This is likely an atomic site. + hasJetpack = true; + } else if (siteInfo.isJetpackConnected) { + hasJetpack = true; + } + return hasJetpack; + } } From de8239513cfeed67c22d5cf2e8f593ba7ea6ecc6 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 10 Sep 2020 20:57:56 -0300 Subject: [PATCH 520/888] Extract method with logic to handle connect site info for Woo --- .../login/LoginSiteAddressFragment.java | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index a861402f5f7..b106e3f0013 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -401,34 +401,38 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { 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("url_after_redirects", event.info.urlAfterRedirects); - properties.put("exists", Boolean.toString(event.info.exists)); - properties.put("has_jetpack", Boolean.toString(event.info.hasJetpack)); - properties.put("is_jetpack_active", Boolean.toString(event.info.isJetpackActive)); - properties.put("is_jetpack_connected", Boolean.toString(event.info.isJetpackConnected)); - properties.put("is_wordpress", Boolean.toString(event.info.isWordPress)); - properties.put("is_wp_com", Boolean.toString(event.info.isWPCom)); - - boolean hasJetpack = calculateHasJetpack(event.info); - - properties.put("login_calculated_has_jetpack", Boolean.toString(hasJetpack)); - 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 { - mLoginListener.gotConnectedSiteInfo( - event.info.url, - event.info.urlAfterRedirects, - hasJetpack); - } + handleConnectSiteInfoForWoo(event.info); + } + } + + private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo) { + // TODO: If we plan to keep this logic we should convert these labels to constants + HashMap properties = new HashMap<>(); + properties.put("url", siteInfo.url); + properties.put("url_after_redirects", siteInfo.urlAfterRedirects); + properties.put("exists", Boolean.toString(siteInfo.exists)); + properties.put("has_jetpack", Boolean.toString(siteInfo.hasJetpack)); + properties.put("is_jetpack_active", Boolean.toString(siteInfo.isJetpackActive)); + properties.put("is_jetpack_connected", Boolean.toString(siteInfo.isJetpackConnected)); + properties.put("is_wordpress", Boolean.toString(siteInfo.isWordPress)); + properties.put("is_wp_com", Boolean.toString(siteInfo.isWPCom)); + + boolean hasJetpack = calculateHasJetpack(siteInfo); + + properties.put("login_calculated_has_jetpack", Boolean.toString(hasJetpack)); + mAnalyticsListener.trackConnectedSiteInfoSucceeded(properties); + + if (!siteInfo.exists) { + // Site does not exist + showError(R.string.invalid_site_url_message); + } else if (!siteInfo.isWordPress) { + // Not a WordPress site + showError(R.string.enter_wordpress_site); + } else { + mLoginListener.gotConnectedSiteInfo( + siteInfo.url, + siteInfo.urlAfterRedirects, + hasJetpack); } } From 430ed9a12b9251b0d046a24e8ba118464221fd0f Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 10 Sep 2020 21:04:47 -0300 Subject: [PATCH 521/888] Use connect/site-info endpoint for WordPress --- .../login/LoginSiteAddressFragment.java | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index b106e3f0013..8284ec3e7b5 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -191,12 +191,8 @@ protected void discover() { String cleanedXmlrpcSuffix = UrlUtils.removeXmlrpcSuffix(mRequestedSiteAddress); - if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { - mAnalyticsListener.trackConnectedSiteInfoRequested(cleanedXmlrpcSuffix); - mDispatcher.dispatch(SiteActionBuilder.newFetchConnectSiteInfoAction(cleanedXmlrpcSuffix)); - } else { - mDispatcher.dispatch(SiteActionBuilder.newFetchWpcomSiteByUrlAction(cleanedXmlrpcSuffix)); - } + mAnalyticsListener.trackConnectedSiteInfoRequested(cleanedXmlrpcSuffix); + mDispatcher.dispatch(SiteActionBuilder.newFetchConnectSiteInfoAction(cleanedXmlrpcSuffix)); startProgress(); } @@ -401,7 +397,11 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { showError(R.string.invalid_site_url_message); } else { - handleConnectSiteInfoForWoo(event.info); + if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { + handleConnectSiteInfoForWoo(event.info); + } else { + handleConnectSiteInfoForWordPress(event.info); + } } } @@ -436,6 +436,37 @@ private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo) { } } + private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo) { + boolean hasJetpack = calculateHasJetpack(siteInfo); + + if (!siteInfo.exists) { + // Site does not exist + showError(R.string.invalid_site_url_message); + } else if (!siteInfo.isWPCom && !hasJetpack) { + // Not a WordPress.com or Jetpack site + if (mLoginListener.getLoginMode() == LoginMode.WPCOM_LOGIN_ONLY) { + showError(R.string.enter_wpcom_or_jetpack_site); + endProgress(); + } else { + // Start the discovery process + initiateDiscovery(); + } + } else { + if (hasJetpack && mLoginListener.getLoginMode() != LoginMode.WPCOM_LOGIN_ONLY) { + // If Jetpack site, treat it as self-hosted and start the discovery process + // An exception is WPCOM_LOGIN_ONLY mode - in that case we're only interested in adding sites + // through WordPress.com login, and should proceed along that login path + initiateDiscovery(); + return; + } + + endProgress(); + + // it's a wp.com site so, treat it as such. + mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(siteInfo.url), null, null); + } + } + private boolean calculateHasJetpack(ConnectSiteInfoPayload siteInfo) { // Determining if jetpack is actually installed takes additional logic. This final // calculated event property will make querying this event more straight-forward: From cfd9079bfc817bac8a7207be40f350f7773bc900 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 10 Sep 2020 21:07:10 -0300 Subject: [PATCH 522/888] Remove event handler for unused endpoint response --- .../login/LoginSiteAddressFragment.java | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index 8284ec3e7b5..c6191423e40 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -30,7 +30,6 @@ import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.SiteStore.ConnectSiteInfoPayload; 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; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; @@ -327,46 +326,6 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { // OnChanged events - @SuppressWarnings("unused") - @Subscribe(threadMode = ThreadMode.MAIN) - public void onWPComSiteFetched(OnWPComSiteFetched event) { - if (mRequestedSiteAddress == null) { - // bail if user canceled - return; - } - - if (!isAdded()) { - return; - } - - if (event.isError()) { - // Not a WordPress.com or Jetpack site - if (mLoginListener.getLoginMode() == LoginMode.WPCOM_LOGIN_ONLY) { - showError(R.string.enter_wpcom_or_jetpack_site); - endProgress(); - } else { - // Start the discovery process - initiateDiscovery(); - } - } else { - if (event.site.isJetpackInstalled() && mLoginListener.getLoginMode() != LoginMode.WPCOM_LOGIN_ONLY) { - // If Jetpack site, treat it as self-hosted and start the discovery process - // An exception is WPCOM_LOGIN_ONLY mode - in that case we're only interested in adding sites - // through WordPress.com login, and should proceed along that login path - initiateDiscovery(); - return; - } - - endProgress(); - - // it's a wp.com site so, treat it as such. - mLoginListener.gotWpcomSiteInfo( - UrlUtils.removeScheme(event.site.getUrl()), - event.site.getName(), - event.site.getIconUrl()); - } - } - @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { From a3267cdabff921c3a8ab63d15bc27c1c04d48b52 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 10 Sep 2020 21:15:49 -0300 Subject: [PATCH 523/888] Remove obsolete parameters siteName and siteIconUrl from Username screen --- .../org/wordpress/android/login/LoginListener.java | 2 +- .../android/login/LoginSiteAddressFragment.java | 4 ++-- .../android/login/LoginUsernamePasswordFragment.java | 11 +---------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index a59b51b64c4..ac64383e4e3 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -51,7 +51,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok // Login Site Address input callbacks void alreadyLoggedInWpcom(ArrayList oldSitesIds); - void gotWpcomSiteInfo(String siteAddress, String siteName, String siteIconUrl); + void gotWpcomSiteInfo(String siteAddress); void gotConnectedSiteInfo(@NonNull String siteAddress, @Nullable String redirectUrl, boolean hasJetpack); void gotXmlRpcEndpoint(String inputSiteAddress, String endpointAddress); void handleSslCertificateError(MemorizingTrustManager memorizingTrustManager, SelfSignedSSLCallback callback); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index c6191423e40..19b74fd32c0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -287,7 +287,7 @@ public void handleWpComDiscoveryError(String failedEndpoint) { ArrayList oldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, true); mLoginListener.alreadyLoggedInWpcom(oldSitesIDs); } else { - mLoginListener.gotWpcomSiteInfo(failedEndpoint, null, null); + mLoginListener.gotWpcomSiteInfo(failedEndpoint); } } @@ -422,7 +422,7 @@ private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo) endProgress(); // it's a wp.com site so, treat it as such. - mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(siteInfo.url), null, null); + mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(siteInfo.url)); } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index f6bc0830fb8..555636dd800 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -61,8 +61,6 @@ public class LoginUsernamePasswordFragment extends LoginBaseDiscoveryFragment im private static final String ARG_INPUT_SITE_ADDRESS = "ARG_INPUT_SITE_ADDRESS"; private static final String ARG_ENDPOINT_ADDRESS = "ARG_ENDPOINT_ADDRESS"; - private static final String ARG_SITE_NAME = "ARG_SITE_NAME"; - private static final String ARG_SITE_ICON_URL = "ARG_SITE_ICON_URL"; private static final String ARG_INPUT_USERNAME = "ARG_INPUT_USERNAME"; private static final String ARG_INPUT_PASSWORD = "ARG_INPUT_PASSWORD"; private static final String ARG_IS_WPCOM = "ARG_IS_WPCOM"; @@ -87,22 +85,17 @@ public class LoginUsernamePasswordFragment extends LoginBaseDiscoveryFragment im private String mInputSiteAddress; private String mInputSiteAddressWithoutSuffix; private String mEndpointAddress; - private String mSiteName; - private String mSiteIconUrl; private String mInputUsername; private String mInputPassword; private boolean mIsWpcom; public static LoginUsernamePasswordFragment newInstance(String inputSiteAddress, String endpointAddress, - String siteName, String siteIconUrl, String inputUsername, String inputPassword, boolean isWpcom) { LoginUsernamePasswordFragment fragment = new LoginUsernamePasswordFragment(); Bundle args = new Bundle(); args.putString(ARG_INPUT_SITE_ADDRESS, inputSiteAddress); args.putString(ARG_ENDPOINT_ADDRESS, endpointAddress); - args.putString(ARG_SITE_NAME, siteName); - args.putString(ARG_SITE_ICON_URL, siteIconUrl); args.putString(ARG_INPUT_USERNAME, inputUsername); args.putString(ARG_INPUT_PASSWORD, inputPassword); args.putBoolean(ARG_IS_WPCOM, isWpcom); @@ -217,8 +210,6 @@ public void onCreate(Bundle savedInstanceState) { mInputSiteAddress = getArguments().getString(ARG_INPUT_SITE_ADDRESS); mEndpointAddress = getArguments().getString(ARG_ENDPOINT_ADDRESS, null); - mSiteName = getArguments().getString(ARG_SITE_NAME); - mSiteIconUrl = getArguments().getString(ARG_SITE_ICON_URL); mInputUsername = getArguments().getString(ARG_INPUT_USERNAME); mInputPassword = getArguments().getString(ARG_INPUT_PASSWORD); mIsWpcom = getArguments().getBoolean(ARG_IS_WPCOM); @@ -410,7 +401,7 @@ private int getDiscoveryErrorMessage(DiscoveryError error) { @Override public void handleWpComDiscoveryError(String failedEndpoint) { AppLog.e(T.API, "Inputted a wpcom address in site address screen. Redirecting to Email screen"); - mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(failedEndpoint), null, null); + mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(failedEndpoint)); } @Override From 73bd2c83421dc6784deec7e95dba8f46386aaacf Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 11 Sep 2020 12:38:56 -0300 Subject: [PATCH 524/888] Move convenience methods for controlling progress to login base class --- .../android/login/LoginBaseFormFragment.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index 260dcd042dc..574ca638e05 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -232,6 +232,12 @@ public void onDestroy() { super.onDestroy(); } + protected void startProgressIfNeeded() { + if (!isInProgress()) { + startProgress(); + } + } + protected void startProgress() { startProgress(true); } @@ -248,14 +254,18 @@ protected void startProgress(boolean cancellable) { new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialogInterface) { - if (isInProgress()) { - endProgress(); - } + endProgressIfNeeded(); } }); mInProgress = true; } + protected void endProgressIfNeeded() { + if (isInProgress()) { + endProgress(); + } + } + @CallSuper protected void endProgress() { mInProgress = false; From 8cee8eb719e078d3f93a2300f59e4443fc20bee9 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 11 Sep 2020 13:06:42 -0300 Subject: [PATCH 525/888] Update site address screen to only end progress after discovery process --- .../login/LoginSiteAddressFragment.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index 19b74fd32c0..a806dce84dc 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -338,16 +338,9 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { 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, + mRequestedSiteAddress, event.getClass().getSimpleName(), event.error.type.name(), event.error.message); @@ -355,6 +348,8 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { AppLog.e(T.API, "onFetchedConnectSiteInfo has error: " + event.error.message); showError(R.string.invalid_site_url_message); + + endProgressIfNeeded(); } else { if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { handleConnectSiteInfoForWoo(event.info); @@ -365,6 +360,8 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { } private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo) { + endProgressIfNeeded(); + // TODO: If we plan to keep this logic we should convert these labels to constants HashMap properties = new HashMap<>(); properties.put("url", siteInfo.url); @@ -401,11 +398,12 @@ private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo) if (!siteInfo.exists) { // Site does not exist showError(R.string.invalid_site_url_message); + endProgressIfNeeded(); } else if (!siteInfo.isWPCom && !hasJetpack) { // Not a WordPress.com or Jetpack site if (mLoginListener.getLoginMode() == LoginMode.WPCOM_LOGIN_ONLY) { showError(R.string.enter_wpcom_or_jetpack_site); - endProgress(); + endProgressIfNeeded(); } else { // Start the discovery process initiateDiscovery(); @@ -419,7 +417,7 @@ private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo) return; } - endProgress(); + endProgressIfNeeded(); // it's a wp.com site so, treat it as such. mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(siteInfo.url)); From 291e9ecefe0c0670cdf258574cc769b032f22866 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 11 Sep 2020 14:09:52 -0300 Subject: [PATCH 526/888] Remove check for existing sites as it doesn't work with self-signed SSL --- .../wordpress/android/login/LoginSiteAddressFragment.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index a806dce84dc..5444e0e76c6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -395,11 +395,7 @@ private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo) { private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo) { boolean hasJetpack = calculateHasJetpack(siteInfo); - if (!siteInfo.exists) { - // Site does not exist - showError(R.string.invalid_site_url_message); - endProgressIfNeeded(); - } else if (!siteInfo.isWPCom && !hasJetpack) { + if (!siteInfo.isWPCom && !hasJetpack) { // Not a WordPress.com or Jetpack site if (mLoginListener.getLoginMode() == LoginMode.WPCOM_LOGIN_ONLY) { showError(R.string.enter_wpcom_or_jetpack_site); From 6eaf25cf9c26a4bc398386af15f85e66392cd079 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Sat, 12 Sep 2020 20:38:40 -0400 Subject: [PATCH 527/888] Upgrade Gradle to 6 --- libs/login/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 5eb03fdb41d..53223e1108d 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -10,7 +10,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:4.0.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -29,7 +29,6 @@ repositories { android { compileSdkVersion 29 - buildToolsVersion "29.0.2" defaultConfig { minSdkVersion 21 From 8793801fe15aa2d7708bbc4b4e15365ea67882b9 Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Sun, 13 Sep 2020 18:51:53 -0400 Subject: [PATCH 528/888] Only log track failures if message is not null --- .../java/org/wordpress/android/login/Login2FaFragment.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 1a0eded4c82..88911a031ce 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -379,8 +379,10 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { updateContinueButtonEnabledStatus(); } - private void show2FaError(String message) { - mAnalyticsListener.trackFailure(message); + private void show2FaError(@Nullable String message) { + if (message != null) { + mAnalyticsListener.trackFailure(message); + } m2FaInput.setError(message); } From 570ebfeb9e7a26298e481fc3e92913e3ff65179c Mon Sep 17 00:00:00 2001 From: Nick Bradbury Date: Mon, 14 Sep 2020 08:16:24 -0400 Subject: [PATCH 529/888] Updated gradle dependecy --- libs/login/build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index e035681462a..1f329662032 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -4,7 +4,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.0' + classpath 'com.android.tools.build:gradle:4.0.1' } } @@ -32,16 +32,16 @@ android { } dependencies { - implementation ('org.wordpress:utils:1.20.3') { + implementation ('org.wordpress:utils:1.26') { exclude group: "com.android.volley" } - implementation 'androidx.appcompat:appcompat:1.0.2' - implementation 'androidx.vectordrawable:vectordrawable-animated:1.0.0' - implementation 'androidx.media:media:1.0.1' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0' + implementation 'androidx.media:media:1.1.0' implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' - implementation 'com.google.android.material:material:1.1.0' + implementation 'com.google.android.material:material:1.2.1' api 'com.google.android.gms:play-services-auth:15.0.1' From 3fdf93c9edeb093797ad81f47ecb335de5e387fe Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Mon, 14 Sep 2020 08:49:13 -0400 Subject: [PATCH 530/888] Hide TOS buttons if not in signup mode during login --- .../android/login/LoginEmailFragment.java | 48 +++++++++++++----- .../main/res/layout/login_email_screen.xml | 50 +++++++++++++++---- 2 files changed, 75 insertions(+), 23 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 4f555f64942..206f56b6b45 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -80,6 +80,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private static final String ARG_SITE_LOGIN_ENABLED = "ARG_SITE_LOGIN_ENABLED"; private static final String ARG_SHOULD_USE_NEW_LAYOUT = "ARG_SHOULD_USE_NEW_LAYOUT"; private static final String ARG_OPTIONAL_SITE_CREDS_LAYOUT = "ARG_OPTIONAL_SITE_CREDS_LAYOUT"; + private static final String ARG_HIDE_TOS = "ARG_HIDE_TOS"; public static final String TAG = "login_email_fragment_tag"; public static final String TAG_ALT_LAYOUT = "login_email_fragment_alternate_layout_tag"; @@ -95,6 +96,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private boolean mIsSiteLoginEnabled; private boolean mShouldUseNewLayout; private boolean mOptionalSiteCredsLayout; + private boolean mHideTos; protected WPLoginInputRow mEmailInput; protected boolean mHasDismissedEmailHints; @@ -118,13 +120,23 @@ public static LoginEmailFragment newInstance(String url, boolean optionalSiteCre return fragment; } - public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled, + public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, + boolean isSiteLoginEnabled, boolean shouldUseNewLayout) { + return newInstance( + isSignupFromLoginEnabled, isSiteLoginEnabled, shouldUseNewLayout, false); + } + + public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, + boolean isSiteLoginEnabled, + boolean shouldUseNewLayout, + boolean hideTos) { LoginEmailFragment fragment = new LoginEmailFragment(); Bundle args = new Bundle(); args.putBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, isSignupFromLoginEnabled); args.putBoolean(ARG_SITE_LOGIN_ENABLED, isSiteLoginEnabled); args.putBoolean(ARG_SHOULD_USE_NEW_LAYOUT, shouldUseNewLayout); + args.putBoolean(ARG_HIDE_TOS, hideTos); fragment.setArguments(args); return fragment; } @@ -256,20 +268,31 @@ private void updateContinueButtonEnabledStatus() { } private void setupTosButtons(Button continueTosButton, Button continueWithGoogleTosButton) { - OnClickListener onClickListener = new OnClickListener() { - public void onClick(View view) { - Context context = getContext(); - if ((context instanceof SignupSheetListener)) { - ((SignupSheetListener) context).onSignupSheetTermsOfServiceClicked(); + if (mHideTos) { + // Hide the TOS buttons + continueTosButton.setVisibility(View.GONE); + continueWithGoogleTosButton.setVisibility(View.GONE); + } else { + // Show the TOS buttons + continueTosButton.setVisibility(View.VISIBLE); + continueWithGoogleTosButton.setVisibility(View.VISIBLE); + + OnClickListener onClickListener = new OnClickListener() { + public void onClick(View view) { + Context context = getContext(); + if ((context instanceof SignupSheetListener)) { + ((SignupSheetListener) context).onSignupSheetTermsOfServiceClicked(); + } } - } - }; + }; - continueTosButton.setOnClickListener(onClickListener); - continueTosButton.setText(formatTosText(R.string.continue_terms_of_service_text)); + continueTosButton.setOnClickListener(onClickListener); + continueTosButton.setText(formatTosText(R.string.continue_terms_of_service_text)); - continueWithGoogleTosButton.setOnClickListener(onClickListener); - continueWithGoogleTosButton.setText(formatTosText(R.string.continue_with_google_terms_of_service_text)); + continueWithGoogleTosButton.setOnClickListener(onClickListener); + continueWithGoogleTosButton + .setText(formatTosText(R.string.continue_with_google_terms_of_service_text)); + } } private void setupSocialButtons(Button continueWithGoogleButton) { @@ -452,6 +475,7 @@ public void onCreate(Bundle savedInstanceState) { mIsSiteLoginEnabled = args.getBoolean(ARG_SITE_LOGIN_ENABLED, true); mShouldUseNewLayout = args.getBoolean(ARG_SHOULD_USE_NEW_LAYOUT, false); mOptionalSiteCredsLayout = args.getBoolean(ARG_OPTIONAL_SITE_CREDS_LAYOUT, false); + mHideTos = args.getBoolean(ARG_HIDE_TOS, false); } } diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index c9a6e58c73f..9e9bfc44469 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -1,19 +1,21 @@ - + android:layout_height="match_parent"> + android:text="@string/continue_terms_of_service_text" + app:layout_constraintTop_toBottomOf="@+id/login_email_row" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + tools:visibility="gone"/> + android:text="@string/login_continue" + app:layout_goneMarginTop="@dimen/margin_extra_large" + app:layout_constraintTop_toBottomOf="@+id/continue_tos" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> + android:layout_weight="1" + app:layout_constraintTop_toBottomOf="@+id/login_continue_button" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> + android:layout_marginBottom="@dimen/margin_small_medium" + app:layout_constraintBottom_toTopOf="@+id/continue_with_google" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"> + app:iconTint="@null" + app:layout_constraintBottom_toTopOf="@+id/continue_with_google_tos" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> + android:text="@string/continue_with_google_terms_of_service_text" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" /> - + From d10380ea06524d8b546ff6fad4517c1efbc5d14d Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 11 Sep 2020 14:15:48 -0300 Subject: [PATCH 531/888] Add missing switch case on discovery error handling --- .../org/wordpress/android/login/LoginSiteAddressFragment.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index 5444e0e76c6..ca7e1560950 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -263,6 +263,9 @@ public void certificateTrusted() { case MISSING_XMLRPC_METHOD: showError(R.string.xmlrpc_missing_method_error); break; + case WORDPRESS_COM_SITE: + // This is handled by handleWpComDiscoveryError + break; case XMLRPC_BLOCKED: showError(R.string.xmlrpc_post_blocked_error); break; From 5e8f771ecea16118de15b9796cb678391bd48c73 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 11 Sep 2020 15:55:08 -0300 Subject: [PATCH 532/888] Extract method with logic to create connect site info event properties --- .../login/LoginSiteAddressFragment.java | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index ca7e1560950..3c05bf6a266 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -41,6 +41,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; import javax.inject.Inject; @@ -50,6 +51,16 @@ public class LoginSiteAddressFragment extends LoginBaseDiscoveryFragment impleme OnEditorCommitListener, LoginBaseDiscoveryFragment.LoginBaseDiscoveryListener { private static final String KEY_REQUESTED_SITE_ADDRESS = "KEY_REQUESTED_SITE_ADDRESS"; + private static final String KEY_SITE_INFO_URL = "url"; + private static final String KEY_SITE_INFO_URL_AFTER_REDIRECTS = "url_after_redirects"; + private static final String KEY_SITE_INFO_EXISTS = "exists"; + private static final String KEY_SITE_INFO_HAS_JETPACK = "has_jetpack"; + private static final String KEY_SITE_INFO_IS_JETPACK_ACTIVE = "is_jetpack_active"; + private static final String KEY_SITE_INFO_IS_JETPACK_CONNECTED = "is_jetpack_connected"; + private static final String KEY_SITE_INFO_IS_WORDPRESS = "is_wordpress"; + private static final String KEY_SITE_INFO_IS_WPCOM = "is_wp_com"; + private static final String KEY_SITE_INFO_CALCULATED_HAS_JETPACK = "login_calculated_has_jetpack"; + public static final String TAG = "login_site_address_fragment_tag"; private WPLoginInputRow mSiteAddressInput; @@ -354,33 +365,21 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { endProgressIfNeeded(); } else { + boolean hasJetpack = calculateHasJetpack(event.info); + + mAnalyticsListener.trackConnectedSiteInfoSucceeded(createConnectSiteInfoProperties(event.info, hasJetpack)); + if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { - handleConnectSiteInfoForWoo(event.info); + handleConnectSiteInfoForWoo(event.info, hasJetpack); } else { - handleConnectSiteInfoForWordPress(event.info); + handleConnectSiteInfoForWordPress(event.info, hasJetpack); } } } - private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo) { + private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo, boolean hasJetpack) { endProgressIfNeeded(); - // TODO: If we plan to keep this logic we should convert these labels to constants - HashMap properties = new HashMap<>(); - properties.put("url", siteInfo.url); - properties.put("url_after_redirects", siteInfo.urlAfterRedirects); - properties.put("exists", Boolean.toString(siteInfo.exists)); - properties.put("has_jetpack", Boolean.toString(siteInfo.hasJetpack)); - properties.put("is_jetpack_active", Boolean.toString(siteInfo.isJetpackActive)); - properties.put("is_jetpack_connected", Boolean.toString(siteInfo.isJetpackConnected)); - properties.put("is_wordpress", Boolean.toString(siteInfo.isWordPress)); - properties.put("is_wp_com", Boolean.toString(siteInfo.isWPCom)); - - boolean hasJetpack = calculateHasJetpack(siteInfo); - - properties.put("login_calculated_has_jetpack", Boolean.toString(hasJetpack)); - mAnalyticsListener.trackConnectedSiteInfoSucceeded(properties); - if (!siteInfo.exists) { // Site does not exist showError(R.string.invalid_site_url_message); @@ -395,9 +394,7 @@ private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo) { } } - private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo) { - boolean hasJetpack = calculateHasJetpack(siteInfo); - + private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo, boolean hasJetpack) { if (!siteInfo.isWPCom && !hasJetpack) { // Not a WordPress.com or Jetpack site if (mLoginListener.getLoginMode() == LoginMode.WPCOM_LOGIN_ONLY) { @@ -435,4 +432,18 @@ private boolean calculateHasJetpack(ConnectSiteInfoPayload siteInfo) { } return hasJetpack; } + + private Map createConnectSiteInfoProperties(ConnectSiteInfoPayload siteInfo, boolean hasJetpack) { + HashMap properties = new HashMap<>(); + properties.put(KEY_SITE_INFO_URL, siteInfo.url); + properties.put(KEY_SITE_INFO_URL_AFTER_REDIRECTS, siteInfo.urlAfterRedirects); + properties.put(KEY_SITE_INFO_EXISTS, Boolean.toString(siteInfo.exists)); + properties.put(KEY_SITE_INFO_HAS_JETPACK, Boolean.toString(siteInfo.hasJetpack)); + properties.put(KEY_SITE_INFO_IS_JETPACK_ACTIVE, Boolean.toString(siteInfo.isJetpackActive)); + properties.put(KEY_SITE_INFO_IS_JETPACK_CONNECTED, Boolean.toString(siteInfo.isJetpackConnected)); + properties.put(KEY_SITE_INFO_IS_WORDPRESS, Boolean.toString(siteInfo.isWordPress)); + properties.put(KEY_SITE_INFO_IS_WPCOM, Boolean.toString(siteInfo.isWPCom)); + properties.put(KEY_SITE_INFO_CALCULATED_HAS_JETPACK, Boolean.toString(hasJetpack)); + return properties; + } } From fdc7b75cfa070821a50db68280f24bfe53234446 Mon Sep 17 00:00:00 2001 From: Ondrej Ruttkay Date: Wed, 16 Sep 2020 15:24:55 +0200 Subject: [PATCH 533/888] Fix login flow memory leaks --- .../android/login/LoginBaseFormFragment.java | 11 +++++++++++ .../android/login/LoginEmailFragment.java | 6 ++++++ .../login/LoginMagicLinkRequestFragment.java | 6 ++++++ .../android/login/LoginSiteAddressFragment.java | 3 ++- .../login/LoginUsernamePasswordFragment.java | 14 ++++++++++++++ .../android/login/SignupEmailFragment.java | 7 +++++++ 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index 260dcd042dc..3ab325b4ae6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -232,6 +232,17 @@ public void onDestroy() { super.onDestroy(); } + @Override public void onDestroyView() { + mPrimaryButton = null; + mSecondaryButton = null; + + if (mProgressDialog != null) { + mProgressDialog.setOnCancelListener(null); + mProgressDialog = null; + } + super.onDestroyView(); + } + protected void startProgress() { startProgress(true); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 206f56b6b45..d2bcad76545 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -267,6 +267,12 @@ private void updateContinueButtonEnabledStatus() { } } + @Override public void onDestroyView() { + mEmailInput = null; + + super.onDestroyView(); + } + private void setupTosButtons(Button continueTosButton, Button continueWithGoogleTosButton) { if (mHideTos) { // Hide the TOS buttons diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index 240712924fb..ba8d56969e8 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -208,6 +208,12 @@ public void onDetach() { mLoginListener = null; } + @Override public void onDestroyView() { + mRequestMagicLinkButton = null; + + super.onDestroyView(); + } + @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index ef360e9706d..fdd85ac1882 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -174,8 +174,9 @@ public void onSaveInstanceState(Bundle outState) { } @Override public void onDestroyView() { - super.onDestroyView(); mLoginSiteAddressValidator.dispose(); + + super.onDestroyView(); } protected void discover() { diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index f6bc0830fb8..421ebb5d697 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -205,6 +205,20 @@ protected void onHelp() { } } + @Override public void onDestroyView() { + if (mPasswordInput != null) { + mPasswordInput.setOnEditorCommitListener(null); + mPasswordInput = null; + } + if (mUsernameInput != null) { + mUsernameInput.setOnEditorCommitListener(null); + mUsernameInput = null; + } + mScrollView = null; + + super.onDestroyView(); + } + @Override public void onAttach(Context context) { AndroidSupportInjection.inject(this); diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java index 62201fa6185..76219768915 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupEmailFragment.java @@ -218,6 +218,13 @@ public void onDetach() { mLoginListener = null; } + @Override + public void onDestroyView() { + mEmailInput = null; + + super.onDestroyView(); + } + private String getCleanedEmail() { return EditTextUtils.getText(mEmailInput.getEditText()).trim(); } From 9c369b153b8023a330e9ceb517c393ff120997aa Mon Sep 17 00:00:00 2001 From: malinajirka Date: Thu, 17 Sep 2020 09:02:42 +0200 Subject: [PATCH 534/888] Updates robolectric to v4.4 in order to fix tenor tests --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 5eb03fdb41d..7d508fb10c1 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -86,7 +86,7 @@ dependencies { testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.28.2' testImplementation 'androidx.arch.core:core-testing:2.1.0' - testImplementation 'org.robolectric:robolectric:4.3.1' + testImplementation 'org.robolectric:robolectric:4.4' testImplementation 'org.assertj:assertj-core:3.11.1' } From 344e527f35f4ead95e63b71b07ddf908a6898587 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 15 Sep 2020 14:35:18 -0300 Subject: [PATCH 535/888] Update logic to handle connect site info for Jetpack and Atomic sites --- .../login/LoginSiteAddressFragment.java | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index 3c05bf6a266..fa0c16ff9e6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -395,28 +395,34 @@ private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo, boolea } private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo, boolean hasJetpack) { - if (!siteInfo.isWPCom && !hasJetpack) { - // Not a WordPress.com or Jetpack site + if (siteInfo.isWPCom || hasJetpack) { + // It's a WordPress.com or a valid Jetpack site + if (mLoginListener.getLoginMode() == LoginMode.SELFHOSTED_ONLY) { + // We're only interested in self-hosted sites + if (hasJetpack) { + // If Jetpack site, treat it as self-hosted and start the discovery process + // Note: This also includes Atomic sites + initiateDiscovery(); + } else { + // Not a self-hosted site + showError(R.string.invalid_site_url_message); // TODO Update error message + endProgressIfNeeded(); + } + } else { + // It's a WordPress.com or a valid Jetpack site, so treat it as such + endProgressIfNeeded(); + mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(siteInfo.url)); + } + } else { + // Not a WordPress.com or a valid Jetpack site if (mLoginListener.getLoginMode() == LoginMode.WPCOM_LOGIN_ONLY) { + // We're only interested in WordPress.com accounts showError(R.string.enter_wpcom_or_jetpack_site); endProgressIfNeeded(); } else { // Start the discovery process initiateDiscovery(); } - } else { - if (hasJetpack && mLoginListener.getLoginMode() != LoginMode.WPCOM_LOGIN_ONLY) { - // If Jetpack site, treat it as self-hosted and start the discovery process - // An exception is WPCOM_LOGIN_ONLY mode - in that case we're only interested in adding sites - // through WordPress.com login, and should proceed along that login path - initiateDiscovery(); - return; - } - - endProgressIfNeeded(); - - // it's a wp.com site so, treat it as such. - mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(siteInfo.url)); } } From 0088a726dccdf2f58726f17b2b49c49972d36666 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 15 Sep 2020 19:12:56 -0300 Subject: [PATCH 536/888] Update Email screen label when logging in to a specific site address --- .../android/login/LoginEmailFragment.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index f40e8b77604..73e02d1c37f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -10,6 +10,7 @@ import android.text.Editable; import android.text.Html; import android.text.Spanned; +import android.text.TextUtils; import android.text.TextWatcher; import android.util.Patterns; import android.view.View; @@ -112,11 +113,17 @@ public static LoginEmailFragment newInstance(String url) { public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled, boolean shouldUseNewLayout) { + return newInstance(isSignupFromLoginEnabled, isSiteLoginEnabled, shouldUseNewLayout, null); + } + + public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled, + boolean shouldUseNewLayout, String url) { LoginEmailFragment fragment = new LoginEmailFragment(); Bundle args = new Bundle(); args.putBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, isSignupFromLoginEnabled); args.putBoolean(ARG_SITE_LOGIN_ENABLED, isSiteLoginEnabled); args.putBoolean(ARG_SHOULD_USE_NEW_LAYOUT, shouldUseNewLayout); + args.putString(ARG_LOGIN_SITE_URL, url); fragment.setArguments(args); return fragment; } @@ -142,10 +149,12 @@ protected void setupLabel(@NonNull TextView label) { break; case FULL: case WPCOM_LOGIN_ONLY: - if (mShouldUseNewLayout) { - label.setText(R.string.enter_email_to_continue_wordpress_com); - } else { + if (!mShouldUseNewLayout) { label.setText(R.string.enter_email_wordpress_com); + } else if (!TextUtils.isEmpty(mLoginSiteUrl)) { + label.setText(getString(R.string.enter_email_for_site, mLoginSiteUrl)); + } else { + label.setText(R.string.enter_email_to_continue_wordpress_com); } break; case WOO_LOGIN_MODE: From ab9c0b6706c0f36d4dd8a13ae2b710bbdf3b6f2a Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 17 Sep 2020 12:39:01 -0300 Subject: [PATCH 537/888] Disable signup with Google when coming from Site Address flow --- .../java/org/wordpress/android/login/LoginEmailFragment.java | 2 +- .../main/java/org/wordpress/android/login/LoginListener.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 73e02d1c37f..d1d54b6f412 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -382,7 +382,7 @@ private void onGoogleSigninClicked() { if (isAdded()) { mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); mIsSocialLogin = true; - mLoginListener.addGoogleLoginFragment(); + mLoginListener.addGoogleLoginFragment(mIsSignupFromLoginEnabled); } else { AppLog.e(T.NUX, "Google login could not be started. LoginEmailFragment was not attached."); showErrorDialog(getString(R.string.login_error_generic_start)); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 3b4efc54434..0f04d4a9f33 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -29,7 +29,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void loginViaSiteCredentials(String inputSiteAddress); void helpEmailScreen(String email); void helpSocialEmailScreen(String email); - void addGoogleLoginFragment(); + void addGoogleLoginFragment(boolean isSignupFromLoginEnabled); void showHelpFindingConnectedEmail(); // Login Request Magic Link callbacks From 2b117c82a3bb83d7876f2040113c2ac32e423600 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 17 Sep 2020 14:48:55 -0300 Subject: [PATCH 538/888] Add internal reference comment related to Jetpack/Atomic detection logic --- .../org/wordpress/android/login/LoginSiteAddressFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index fa0c16ff9e6..a0451cdc85e 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -428,7 +428,8 @@ private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo, private boolean calculateHasJetpack(ConnectSiteInfoPayload siteInfo) { // Determining if jetpack is actually installed takes additional logic. This final - // calculated event property will make querying this event more straight-forward: + // calculated event property will make querying this event more straight-forward. + // Internal reference: p99K0U-1vO-p2#comment-3574 boolean hasJetpack = false; if (siteInfo.isWPCom && siteInfo.hasJetpack) { // This is likely an atomic site. From a3b2682aae90c5da95887c02c147f4768cc48355 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 17 Sep 2020 20:44:44 -0300 Subject: [PATCH 539/888] Preserve behavior when adding WP.com sites from add self-hosted option --- .../android/login/LoginEmailFragment.java | 1 + .../android/login/LoginSiteAddressFragment.java | 16 ++++++---------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index d1d54b6f412..c18032d51c8 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -149,6 +149,7 @@ protected void setupLabel(@NonNull TextView label) { break; case FULL: case WPCOM_LOGIN_ONLY: + case SELFHOSTED_ONLY: if (!mShouldUseNewLayout) { label.setText(R.string.enter_email_wordpress_com); } else if (!TextUtils.isEmpty(mLoginSiteUrl)) { diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index a0451cdc85e..deb2fd6ead2 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -396,25 +396,21 @@ private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo, boolea private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo, boolean hasJetpack) { if (siteInfo.isWPCom || hasJetpack) { - // It's a WordPress.com or a valid Jetpack site + // It's a WordPress.com or a connected Jetpack site if (mLoginListener.getLoginMode() == LoginMode.SELFHOSTED_ONLY) { // We're only interested in self-hosted sites if (hasJetpack) { // If Jetpack site, treat it as self-hosted and start the discovery process // Note: This also includes Atomic sites initiateDiscovery(); - } else { - // Not a self-hosted site - showError(R.string.invalid_site_url_message); // TODO Update error message - endProgressIfNeeded(); + return; } - } else { - // It's a WordPress.com or a valid Jetpack site, so treat it as such - endProgressIfNeeded(); - mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(siteInfo.url)); } + // It's a WordPress.com or a connected Jetpack site, so treat it as such + endProgressIfNeeded(); + mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(siteInfo.url)); } else { - // Not a WordPress.com or a valid Jetpack site + // Not a WordPress.com or a connected Jetpack site if (mLoginListener.getLoginMode() == LoginMode.WPCOM_LOGIN_ONLY) { // We're only interested in WordPress.com accounts showError(R.string.enter_wpcom_or_jetpack_site); From e8fb6419c15002f419dc450f3208512758f443e8 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Thu, 17 Sep 2020 20:49:11 -0300 Subject: [PATCH 540/888] Update string to remove reference to a missing button --- libs/login/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 13f91ba8cdb..d3c99eaad6d 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -31,7 +31,7 @@ Text me a code instead Text me another code instead Requesting a verification code via SMS. - Hmm, we can\'t find a WordPress.com account connected to this email address. Try the link below to log in using your site address. + Hmm, we can\'t find a WordPress.com account connected to this email address. It looks like this password is incorrect. Please double check your information and try again. We\'ll email you a link that\'ll log you in instantly, no password needed. Almost there! We just need to verify your Jetpack connected email address <b>%1$s</b> From 4b0f2dcba5e6eb59b0a2f1ee30b6b02152e40846 Mon Sep 17 00:00:00 2001 From: Ondrej Ruttkay Date: Mon, 21 Sep 2020 12:54:04 +0200 Subject: [PATCH 541/888] Null the site address view when the view is destroyed --- .../org/wordpress/android/login/LoginSiteAddressFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index fdd85ac1882..c39c0fe347d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -175,6 +175,7 @@ public void onSaveInstanceState(Bundle outState) { @Override public void onDestroyView() { mLoginSiteAddressValidator.dispose(); + mSiteAddressInput = null; super.onDestroyView(); } From c0da887fb615fee2f236a2bbcb2c711ddfaaabbd Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Thu, 24 Sep 2020 10:09:29 -0400 Subject: [PATCH 542/888] Allow login to complete if WPcom login without the woo-specific site address check This is important for a case where the email is being blocked for some reason and the user has been forced to login with their WPcom username instead. Since this flow wouldn't include a login site address then we shouldn't be attempting to validate it. --- .../wordpress/android/login/LoginUsernamePasswordFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index 421ebb5d697..ecfb8a9607f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -634,7 +634,7 @@ public void onSiteChanged(OnSiteChanged event) { return; } - if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { + if (!mIsWpcom && mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { SiteModel lastAddedXMLRPCSite = SiteUtils.getXMLRPCSiteByUrl(mSiteStore, mInputSiteAddress); if (lastAddedXMLRPCSite != null) { // the wp.getOptions endpoint is already called From dcf4663ca614c1792e9eed92e57c7711ce19efe3 Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Thu, 24 Sep 2020 15:51:16 -0400 Subject: [PATCH 543/888] Make screen scrollable for smaller displays and lower resolutions --- .../main/res/layout/login_email_screen.xml | 227 +++++++++--------- 1 file changed, 118 insertions(+), 109 deletions(-) diff --git a/libs/login/src/main/res/layout/login_email_screen.xml b/libs/login/src/main/res/layout/login_email_screen.xml index 9e9bfc44469..76f8f2769eb 100644 --- a/libs/login/src/main/res/layout/login_email_screen.xml +++ b/libs/login/src/main/res/layout/login_email_screen.xml @@ -1,129 +1,138 @@ - - + android:layout_height="wrap_content"> - - - + - + - + - + - + android:layout_height="0dp" + android:layout_weight="1" + app:layout_constraintTop_toBottomOf="@+id/login_continue_button" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> - + android:layout_marginBottom="@dimen/margin_small_medium" + app:layout_constraintTop_toBottomOf="@+id/spacer" + app:layout_constraintBottom_toTopOf="@+id/continue_with_google" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintVertical_bias="1.0"> - + - + - + + + + + + + - + From b6415e858245e6693b71e6a0443d8c3b843bb414 Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Thu, 24 Sep 2020 17:04:16 -0400 Subject: [PATCH 544/888] Nest layout in a ScrollView so buttons no longer overlap on smaller screens --- ...login_email_optional_site_creds_screen.xml | 137 ++++++++++-------- 1 file changed, 73 insertions(+), 64 deletions(-) diff --git a/libs/login/src/main/res/layout/login_email_optional_site_creds_screen.xml b/libs/login/src/main/res/layout/login_email_optional_site_creds_screen.xml index 47102121674..75601813709 100644 --- a/libs/login/src/main/res/layout/login_email_optional_site_creds_screen.xml +++ b/libs/login/src/main/res/layout/login_email_optional_site_creds_screen.xml @@ -1,78 +1,87 @@ - - + android:layout_height="wrap_content"> - + - + - + - - + + + + + + From 0baf705cb3134a867e65e15306d4cad81198bb2e Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Thu, 24 Sep 2020 19:07:04 -0400 Subject: [PATCH 545/888] Add new methods for updating the step when resuming site address and email password views --- .../org/wordpress/android/login/LoginAnalyticsListener.kt | 2 ++ .../wordpress/android/login/LoginEmailPasswordFragment.java | 1 + .../wordpress/android/login/LoginSiteAddressFragment.java | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt index c111b8bd9e5..9a62f44b52f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt @@ -68,6 +68,8 @@ interface LoginAnalyticsListener { fun trackEmailSignupConfirmationViewed() fun trackSocialSignupConfirmationViewed() fun trackCreateAccountClick() + fun emailPasswordFormScreenResumed() + fun siteAddressFormScreenResumed() enum class CreatedAccountSource { EMAIL, diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 17b469cd0c9..dd3154bf1e0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -109,6 +109,7 @@ public void onCreate(Bundle savedInstanceState) { @Override public void onResume() { super.onResume(); + mAnalyticsListener.emailPasswordFormScreenResumed(); updatePrimaryButtonEnabledStatus(); // connect to the Service. We'll receive updates via EventBus. diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index fdd85ac1882..ea908522004 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -166,6 +166,12 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { }); } + @Override public void onResume() { + super.onResume(); + + mAnalyticsListener.siteAddressFormScreenResumed(); + } + @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); From 0c650db3779c0269e10d900d0862b0cb6bdb07fc Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Thu, 24 Sep 2020 19:12:47 -0400 Subject: [PATCH 546/888] Add new methods for updating the step when resuming magic link and site creds views --- .../org/wordpress/android/login/LoginAnalyticsListener.kt | 3 +++ .../android/login/LoginMagicLinkRequestFragment.java | 5 +++++ .../wordpress/android/login/LoginMagicLinkSentFragment.java | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt index 9a62f44b52f..5d73713f8f3 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt @@ -70,6 +70,9 @@ interface LoginAnalyticsListener { fun trackCreateAccountClick() fun emailPasswordFormScreenResumed() fun siteAddressFormScreenResumed() + fun magicLinkRequestScreenResumed() + fun magicLinkSentScreenResumed() + fun usernamePasswordScreenResumed() enum class CreatedAccountSource { EMAIL, diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java index ba8d56969e8..9df2c9c454b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkRequestFragment.java @@ -202,6 +202,11 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { getActivity().setTitle(R.string.magic_link_login_title); } + @Override public void onResume() { + super.onResume(); + mAnalyticsListener.magicLinkRequestScreenResumed(); + } + @Override public void onDetach() { super.onDetach(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java index 472f2554e99..002a93f14d1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMagicLinkSentFragment.java @@ -125,6 +125,11 @@ public void onAttach(Context context) { } } + @Override public void onResume() { + super.onResume(); + mAnalyticsListener.magicLinkSentScreenResumed(); + } + @Override public void onDetach() { super.onDetach(); From 2792bb3765a4e4ddf4b72ebbcacf982c4ab0375c Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Thu, 24 Sep 2020 19:35:59 -0400 Subject: [PATCH 547/888] Add new methods for updating the step when resuming site creds screen --- .../wordpress/android/login/LoginUsernamePasswordFragment.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index ecfb8a9607f..470c5b099ef 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -279,6 +279,7 @@ public void onSaveInstanceState(Bundle outState) { @Override public void onResume() { super.onResume(); + mAnalyticsListener.usernamePasswordScreenResumed(); updatePrimaryButtonEnabledStatus(); } @@ -695,3 +696,4 @@ public void onProfileFetched(OnProfileFetched event) { finishLogin(); } } + From ca47736f19092918f5525d5a6ca99c084ace94b4 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Mon, 28 Sep 2020 16:59:21 -0300 Subject: [PATCH 548/888] Bump default LoginFlow's FluxC version --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 833cb777c5e..695d27980a5 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -64,7 +64,7 @@ dependencies { exclude group: "org.wordpress", module: "utils" } } else { - implementation("com.github.wordpress-mobile.WordPress-FluxC-Android:fluxc:1.5.1-beta-4") { + implementation("com.github.wordpress-mobile.WordPress-FluxC-Android:fluxc:1.6.22") { exclude group: "com.android.support" exclude group: "org.wordpress", module: "utils" } From 037ce0e4c1efdd62d7438e65dd2eb332438b4705 Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Wed, 30 Sep 2020 17:07:53 -0400 Subject: [PATCH 549/888] Call login listener method for unregistered email if in WPcom login flow This hook will allow us to show the new "No WordPress.com account found" error screen. --- .../wordpress/android/login/LoginEmailFragment.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index d2bcad76545..fd762cbc83c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -683,7 +683,18 @@ public void onAvailabilityChecked(OnAvailabilityChecked event) { case EMAIL: if (event.isAvailable) { ActivityUtils.hideKeyboardForced(mEmailInput); - if (mIsSignupFromLoginEnabled) { + + // Will be true if in the Woo app and currently in the WPcom login + // flow. We need to check this to know if we should display the + // 'No WPcom account found' error screen. + boolean isWooWPcomLoginFlow = false; + if (mLoginListener != null + && mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE + && !mOptionalSiteCredsLayout) { + isWooWPcomLoginFlow = true; + } + + if (mIsSignupFromLoginEnabled || isWooWPcomLoginFlow) { if (mLoginListener != null) { mLoginListener.gotUnregisteredEmail(event.value); } From 32ceaa15b41f1a723428730492bf9e9744c1fb8e Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 2 Oct 2020 19:15:17 -0300 Subject: [PATCH 550/888] Update behavior when handling Jetpack sites so it uses site credentials --- .../android/login/LoginSiteAddressFragment.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index deb2fd6ead2..767ae90b256 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -372,7 +372,7 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { handleConnectSiteInfoForWoo(event.info, hasJetpack); } else { - handleConnectSiteInfoForWordPress(event.info, hasJetpack); + handleConnectSiteInfoForWordPress(event.info); } } } @@ -394,23 +394,21 @@ private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo, boolea } } - private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo, boolean hasJetpack) { - if (siteInfo.isWPCom || hasJetpack) { - // It's a WordPress.com or a connected Jetpack site + private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo) { + if (siteInfo.isWPCom) { + // It's a Simple or Atomic site if (mLoginListener.getLoginMode() == LoginMode.SELFHOSTED_ONLY) { // We're only interested in self-hosted sites - if (hasJetpack) { - // If Jetpack site, treat it as self-hosted and start the discovery process - // Note: This also includes Atomic sites + if (siteInfo.hasJetpack) { + // This is an Atomic site, so treat it as self-hosted and start the discovery process initiateDiscovery(); return; } } - // It's a WordPress.com or a connected Jetpack site, so treat it as such endProgressIfNeeded(); mLoginListener.gotWpcomSiteInfo(UrlUtils.removeScheme(siteInfo.url)); } else { - // Not a WordPress.com or a connected Jetpack site + // It's a Jetpack or self-hosted site if (mLoginListener.getLoginMode() == LoginMode.WPCOM_LOGIN_ONLY) { // We're only interested in WordPress.com accounts showError(R.string.enter_wpcom_or_jetpack_site); From 6891d23f88b1a94940f03303f00f3671bcd58783 Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Fri, 9 Oct 2020 16:50:41 -0400 Subject: [PATCH 551/888] Update to conform to changes from the Login Library None of these changes should change the functionality of login in the app, just minor tweaks needed to happy to build successfully. --- .../android/login/LoginEmailFragment.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 482fe8ccd23..a5fba9a9c44 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -129,24 +129,34 @@ public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled, boolean shouldUseNewLayout) { return newInstance( - isSignupFromLoginEnabled, isSiteLoginEnabled, shouldUseNewLayout, false); + isSignupFromLoginEnabled, isSiteLoginEnabled, shouldUseNewLayout, null); } public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled, boolean shouldUseNewLayout, boolean hideTos) { - return newInstance(isSignupFromLoginEnabled, isSiteLoginEnabled, shouldUseNewLayout, null); + LoginEmailFragment fragment = new LoginEmailFragment(); + Bundle args = new Bundle(); + args.putBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, isSignupFromLoginEnabled); + args.putBoolean(ARG_SITE_LOGIN_ENABLED, isSiteLoginEnabled); + args.putBoolean(ARG_SHOULD_USE_NEW_LAYOUT, shouldUseNewLayout); + args.putBoolean(ARG_HIDE_TOS, hideTos); + args.putString(ARG_LOGIN_SITE_URL, null); + fragment.setArguments(args); + return fragment; } - public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, boolean isSiteLoginEnabled, - boolean shouldUseNewLayout, String url) { + public static LoginEmailFragment newInstance(boolean isSignupFromLoginEnabled, + boolean isSiteLoginEnabled, + boolean shouldUseNewLayout, + String url) { LoginEmailFragment fragment = new LoginEmailFragment(); Bundle args = new Bundle(); args.putBoolean(ARG_SIGNUP_FROM_LOGIN_ENABLED, isSignupFromLoginEnabled); args.putBoolean(ARG_SITE_LOGIN_ENABLED, isSiteLoginEnabled); args.putBoolean(ARG_SHOULD_USE_NEW_LAYOUT, shouldUseNewLayout); - args.putBoolean(ARG_HIDE_TOS, hideTos); + args.putBoolean(ARG_HIDE_TOS, false); args.putString(ARG_LOGIN_SITE_URL, url); fragment.setArguments(args); return fragment; From 2e9bca4fc504727aa90bf912f261a775764883e0 Mon Sep 17 00:00:00 2001 From: Amanda Riu Date: Mon, 12 Oct 2020 13:33:19 -0400 Subject: [PATCH 552/888] Remove confusion over tag usage by renaming and fix social login bug These changes will fix an issue where the `LoginEmailFragment` cannot be found upon successful social login so the app appears to hang when really it just has no way to move forward because the TAG used recall the fragment from the stack wasn't the same one used in it's creation. This confusion happens because there are two different layouts now for the `LoginEmailFragment`, one that has an option to login with site creds, and one that does not. --- .../java/org/wordpress/android/login/LoginEmailFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index fd762cbc83c..94ec56e2c25 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -83,7 +83,7 @@ public class LoginEmailFragment extends LoginBaseFormFragment imp private static final String ARG_HIDE_TOS = "ARG_HIDE_TOS"; public static final String TAG = "login_email_fragment_tag"; - public static final String TAG_ALT_LAYOUT = "login_email_fragment_alternate_layout_tag"; + public static final String TAG_SITE_CREDS_LAYOUT = "login_email_fragment_site_creds_layout_tag"; public static final int MAX_EMAIL_LENGTH = 100; private ArrayList mOldSitesIDs = new ArrayList<>(); From aba351913d3d70b08c0f77540747912d15a73849 Mon Sep 17 00:00:00 2001 From: Klymentiy haykov Date: Mon, 12 Oct 2020 19:11:31 -0700 Subject: [PATCH 553/888] Added transparent status bar. --- libs/login/src/main/res/layout/toolbar_login.xml | 1 + libs/login/src/main/res/values-v21/dimens.xml | 7 +++++++ libs/login/src/main/res/values-v21/themes.xml | 6 ++++++ libs/login/src/main/res/values-v23/dimens.xml | 7 +++++++ libs/login/src/main/res/values-v23/themes.xml | 4 ++++ 5 files changed, 25 insertions(+) create mode 100644 libs/login/src/main/res/values-v21/dimens.xml create mode 100644 libs/login/src/main/res/values-v21/themes.xml create mode 100644 libs/login/src/main/res/values-v23/dimens.xml diff --git a/libs/login/src/main/res/layout/toolbar_login.xml b/libs/login/src/main/res/layout/toolbar_login.xml index 6e847604bf2..608fc8c5985 100644 --- a/libs/login/src/main/res/layout/toolbar_login.xml +++ b/libs/login/src/main/res/layout/toolbar_login.xml @@ -3,6 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/appbar_main" android:layout_width="match_parent" + android:paddingTop="@dimen/status_bar_height_offset" android:layout_height="wrap_content"> + + + + 0dp + + diff --git a/libs/login/src/main/res/values-v21/themes.xml b/libs/login/src/main/res/values-v21/themes.xml new file mode 100644 index 00000000000..308bb6ba0c1 --- /dev/null +++ b/libs/login/src/main/res/values-v21/themes.xml @@ -0,0 +1,6 @@ + + + + + + From c7f57423f01fe828b6f3032491a3b235290bb73d Mon Sep 17 00:00:00 2001 From: Klymentiy haykov Date: Mon, 12 Oct 2020 21:59:04 -0700 Subject: [PATCH 554/888] Fixed more lint errors. --- libs/login/src/main/res/values-v21/dimens.xml | 7 ------- libs/login/src/main/res/values-v21/themes.xml | 6 ------ libs/login/src/main/res/values/dimens.xml | 2 ++ libs/login/src/main/res/values/themes.xml | 2 ++ 4 files changed, 4 insertions(+), 13 deletions(-) delete mode 100644 libs/login/src/main/res/values-v21/dimens.xml delete mode 100644 libs/login/src/main/res/values-v21/themes.xml diff --git a/libs/login/src/main/res/values-v21/dimens.xml b/libs/login/src/main/res/values-v21/dimens.xml deleted file mode 100644 index fc23b561a2c..00000000000 --- a/libs/login/src/main/res/values-v21/dimens.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - 0dp - - diff --git a/libs/login/src/main/res/values-v21/themes.xml b/libs/login/src/main/res/values-v21/themes.xml deleted file mode 100644 index 308bb6ba0c1..00000000000 --- a/libs/login/src/main/res/values-v21/themes.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - + + - @@ -77,7 +80,7 @@ @color/login_on_surface_medium_selector - @@ -88,16 +91,16 @@ ?android:colorBackground - - - diff --git a/libs/login/src/main/res/values/themes.xml b/libs/login/src/main/res/values/themes.xml index 40849e2761c..637f2a53358 100644 --- a/libs/login/src/main/res/values/themes.xml +++ b/libs/login/src/main/res/values/themes.xml @@ -1,5 +1,7 @@ - + + - - - - From 40d5200805b264e927ed12988adbbdc15c6d4136 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Mon, 22 Mar 2021 18:46:41 -0300 Subject: [PATCH 605/888] Remove unused dimensions --- libs/login/src/main/res/values/dimens.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libs/login/src/main/res/values/dimens.xml b/libs/login/src/main/res/values/dimens.xml index f034df83af5..c3ef9473aff 100644 --- a/libs/login/src/main/res/values/dimens.xml +++ b/libs/login/src/main/res/values/dimens.xml @@ -3,9 +3,6 @@ 0.12 - 72dp - 0dp - 0dp 24dp 1dp @@ -29,14 +26,8 @@ 32dp 40dp - - 4dp - - 20dp 92dp 4dp - 24dp - 9dp From 912b4749554e94fa817a1d0048ba3fe2354adbdf Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Mon, 22 Mar 2021 18:46:47 -0300 Subject: [PATCH 606/888] Remove unused colors --- libs/login/src/main/res/values/colors.xml | 118 +--------------------- 1 file changed, 2 insertions(+), 116 deletions(-) diff --git a/libs/login/src/main/res/values/colors.xml b/libs/login/src/main/res/values/colors.xml index c220ec20cec..188e973a9d2 100644 --- a/libs/login/src/main/res/values/colors.xml +++ b/libs/login/src/main/res/values/colors.xml @@ -19,123 +19,9 @@ #61121212 - - @color/blue_wordpress - @color/status_bar - @color/orange_jazzy - @color/white - @color/blue_light - @color/grey_lighten_20 - - - #00000000 - @color/grey_lighten_30 - @color/grey_lighten_20 - #FFFFFF - #F1F1F1 - - #000000 - @color/grey_lighten_30 - - - - - - #0087be - #78dcfa - #00aadc - #005082 - - #87a6bc - #f3f6f8 - #2e4453 - @color/grey_darken_10 - - #537994 - - - #e9eff3 - #c8d7e1 - #a8bece - #668eaa - #4f748e - #3d596d - - - #f0821e - #d54e21 - - - #f0b849 - #d94f4f - #4ab866 - - - #66000000 - #80000000 - #cc78dcfa - #802e4453 - #b32e4453 - #80888888 - #80a8bece - #80c8d7e1 - #80e9eff3 - #66ffffff - #99ffffff - #a6ffffff - - - - - - #fffafafa - #fff5f5f5 - #ffeeeeee - #ffe0e0e0 - #ffbdbdbd - #ff9e9e9e - #ff757575 - #ff616161 - #ff424242 - #ff212121 - - - - #006b98 - #ff517188 - @color/blue_medium - @color/grey_light - - @color/blue_wordpress - @color/white - @color/blue_medium - @color/white - @color/blue_wordpress - @color/gray - @color/blue_wordpress - @color/grey_dark - @color/grey_text_min - @color/grey_text_min - @color/blue_medium - @color/blue_medium - @color/grey_dark - @color/grey_text_min - @color/grey_text_min - @color/grey_dark - @color/grey_text_min - @color/grey_dark - - @color/grey_lighten_10 - @color/grey - @color/blue_wordpress + #c8d7e1 + #0087be From 72dd57258a720bd82ddbf5041672170e5ca4b661 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Wed, 31 Mar 2021 13:04:35 +0200 Subject: [PATCH 607/888] Set colorSecondary and colorSecondaryVariant to blue in login library --- libs/login/src/main/res/values-night/themes.xml | 4 ++-- libs/login/src/main/res/values/themes.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/res/values-night/themes.xml b/libs/login/src/main/res/values-night/themes.xml index f5296a5ea88..79815f0bee4 100644 --- a/libs/login/src/main/res/values-night/themes.xml +++ b/libs/login/src/main/res/values-night/themes.xml @@ -4,8 +4,8 @@ - - - diff --git a/libs/login/src/main/res/values/themes.xml b/libs/login/src/main/res/values/themes.xml index df28fc77909..b1e85c40f18 100644 --- a/libs/login/src/main/res/values/themes.xml +++ b/libs/login/src/main/res/values/themes.xml @@ -64,8 +64,11 @@ - From 26c40e8b35183fcc6332fa6b4f13257d52dc39d5 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Thu, 10 Nov 2022 17:00:54 +0200 Subject: [PATCH 716/888] Analysis: Remove unnecessary duplicate v27 theme login flow config Since this 0c0ba6c1f6bd9c5175e1b2101feca211812398c1 change resolved the obsolete sdk int lint warning for res values v23, this 'android:statusBarColor' and 'android:windowLightStatusBar' became the default. As such, those can be now removed from teh v27 configuration. --- libs/login/src/main/res/values-v27/themes.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/login/src/main/res/values-v27/themes.xml b/libs/login/src/main/res/values-v27/themes.xml index fc3d18102eb..b2d33fc6343 100644 --- a/libs/login/src/main/res/values-v27/themes.xml +++ b/libs/login/src/main/res/values-v27/themes.xml @@ -1,9 +1,6 @@ - From ed67b85d37c3d38f43ec1f5a5bb31bef681dfac3 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 14 Nov 2022 15:27:00 +0200 Subject: [PATCH 717/888] Revert "Analysis: Remove unnecessary duplicate v27 theme login flow config" This reverts commit 26c40e8b35183fcc6332fa6b4f13257d52dc39d5. --- libs/login/src/main/res/values-v27/themes.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/login/src/main/res/values-v27/themes.xml b/libs/login/src/main/res/values-v27/themes.xml index b2d33fc6343..fc3d18102eb 100644 --- a/libs/login/src/main/res/values-v27/themes.xml +++ b/libs/login/src/main/res/values-v27/themes.xml @@ -1,6 +1,9 @@ + From 63d3f9f701524abc251065ff5e04c95233d65fe9 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Wed, 16 Nov 2022 15:16:09 +0200 Subject: [PATCH 718/888] Build: Replace gradle ext with project ext for sdk versions declaration For more info on that check PR comment and relevant discussion below: https://github.com/wordpress-mobile/WordPress-FluxC-Android/ pull/2563#discussion_r1020079074 --- libs/login/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 3f55ec278ac..bdaf9443167 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -21,11 +21,11 @@ repositories { } android { - compileSdkVersion gradle.ext.compileSdkVersion + compileSdkVersion rootProject.compileSdkVersion defaultConfig { - minSdkVersion gradle.ext.minSdkVersion - targetSdkVersion gradle.ext.targetSdkVersion + minSdkVersion rootProject.minSdkVersion + targetSdkVersion rootProject.targetSdkVersion vectorDrawables.useSupportLibrary = true } From c48385ccc1d1a64614b857928d734f709dd0690b Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Thu, 2 Feb 2023 15:54:48 +0100 Subject: [PATCH 719/888] Disable XMLRPC discovery for Woo login --- .../android/login/LoginSiteAddressFragment.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index e3d3eb5c79c..eaa2d7e1cf4 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -429,23 +429,13 @@ private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo) { endProgressIfNeeded(); // Not a WordPress site mLoginListener.handleSiteAddressError(siteInfo); - } else if (mConnectSiteInfoCalculatedHasJetpack) { + } else { endProgressIfNeeded(); mLoginListener.gotConnectedSiteInfo( mConnectSiteInfoUrl, mConnectSiteInfoUrlRedirect, mConnectSiteInfoCalculatedHasJetpack ); - } else { - /** - * Jetpack internally uses xml-rpc protocol. Due to a bug on the API, when jetpack is - * setup and connected to a .com account `isJetpackConnected` returns false when xml-rpc - * is disabled. - * This is causing issues to the client apps as they can't differentiate between - * "xml-rpc disabled" and "jetpack not connected" states. Therefore, the login flow - * library needs to invoke "xml-rpc discovery" to check if xml-rpc is accessible. - */ - initiateDiscovery(); } } From f1656df2eb81fa815db9b8d647bc95d4eab320aa Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Wed, 15 Feb 2023 17:10:07 +0100 Subject: [PATCH 720/888] Strip know paths before sending the site-info API request We identified some cases when the response fails to identify Jetpack sites when the request is sent with some suffixes. --- .../login/LoginSiteAddressFragment.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index eaa2d7e1cf4..93a3b602e7e 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -3,6 +3,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; @@ -26,6 +27,7 @@ import org.wordpress.android.fluxc.generated.SiteActionBuilder; import org.wordpress.android.fluxc.network.HTTPAuthManager; import org.wordpress.android.fluxc.network.MemorizingTrustManager; +import org.wordpress.android.fluxc.network.discovery.DiscoveryUtils; import org.wordpress.android.fluxc.network.discovery.SelfHostedEndpointFinder.DiscoveryError; import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.SiteStore.ConnectSiteInfoPayload; @@ -216,10 +218,10 @@ protected void discover() { mRequestedSiteAddress = mLoginSiteAddressValidator.getCleanedSiteAddress(); - String cleanedXmlrpcSuffix = UrlUtils.removeXmlrpcSuffix(mRequestedSiteAddress); + String cleanedUrl = stripKnownPaths(mRequestedSiteAddress); - mAnalyticsListener.trackConnectedSiteInfoRequested(cleanedXmlrpcSuffix); - mDispatcher.dispatch(SiteActionBuilder.newFetchConnectSiteInfoAction(cleanedXmlrpcSuffix)); + mAnalyticsListener.trackConnectedSiteInfoRequested(cleanedUrl); + mDispatcher.dispatch(SiteActionBuilder.newFetchConnectSiteInfoAction(cleanedUrl)); startProgress(); } @@ -502,4 +504,22 @@ private Map createConnectSiteInfoProperties(ConnectSiteInfoPaylo properties.put(KEY_SITE_INFO_CALCULATED_HAS_JETPACK, Boolean.toString(hasJetpack)); return properties; } + + private String stripKnownPaths(String url) { + String cleanedXmlrpcSuffix = UrlUtils.removeXmlrpcSuffix(url); + + // Make sure to use a valid URL so that DiscoveryUtils#stripKnownPaths is able to strip paths + String scheme = Uri.parse(cleanedXmlrpcSuffix).getScheme(); + String urlWithScheme; + if (scheme == null) { + urlWithScheme = UrlUtils.addUrlSchemeIfNeeded(cleanedXmlrpcSuffix, false); + } else { + urlWithScheme = cleanedXmlrpcSuffix; + } + + String cleanedUrl = DiscoveryUtils.stripKnownPaths(urlWithScheme); + + // Revert the scheme changes + return scheme == null ? UrlUtils.removeScheme(cleanedUrl) : cleanedUrl; + } } From d750e22808e65dd79f25d1c388417c8776340e60 Mon Sep 17 00:00:00 2001 From: Renan Lukas <14964993+RenanLukas@users.noreply.github.com> Date: Thu, 30 Mar 2023 00:26:49 -0300 Subject: [PATCH 721/888] Stop filtering JP connected sites when LoginMode is JETPACK_LOGIN_ONLY --- .../wordpress/android/login/LoginBaseFormFragment.java | 8 +++++++- .../org/wordpress/android/login/LoginEmailFragment.java | 1 + .../android/login/LoginEmailPasswordFragment.java | 1 + .../main/java/org/wordpress/android/login/LoginMode.java | 1 + .../org/wordpress/android/login/LoginWpcomService.java | 8 +++++++- .../java/org/wordpress/android/login/util/SiteUtils.java | 7 +++++-- 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index 3a2c9a6278f..c66e1d10a0a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -336,12 +336,18 @@ public void onAccountChanged(OnAccountChanged event) { mDispatcher.dispatch(AccountActionBuilder.newFetchSettingsAction()); } else if (event.causeOfChange == AccountAction.FETCH_SETTINGS) { // The user's account settings have also been fetched and stored - now we can fetch the user's sites - FetchSitesPayload payload = SiteUtils.getFetchSitesPayload(isWooAppLogin()); + FetchSitesPayload payload = + SiteUtils.getFetchSitesPayload(isJetpackAppLogin(), isWooAppLogin()); mDispatcher.dispatch(SiteActionBuilder.newFetchSitesAction(payload)); mDispatcher.dispatch(AccountActionBuilder.newFetchSubscriptionsAction()); } } + protected boolean isJetpackAppLogin() { + return (mLoginListener instanceof LoginListener) + && ((LoginListener) mLoginListener).getLoginMode() == LoginMode.JETPACK_LOGIN_ONLY; + } + protected boolean isWooAppLogin() { return (mLoginListener instanceof LoginListener) && ((LoginListener) mLoginListener).getLoginMode() == LoginMode.WOO_LOGIN_MODE; diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index 42c002a1616..e305051b327 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -156,6 +156,7 @@ protected void setupLabel(@NonNull TextView label) { break; case FULL: case WPCOM_LOGIN_ONLY: + case JETPACK_LOGIN_ONLY: case SELFHOSTED_ONLY: if (!TextUtils.isEmpty(mLoginSiteUrl)) { label.setText(Html.fromHtml( diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index c65813cb359..3645d8f7a65 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -285,6 +285,7 @@ protected void next() { mIdToken, mService, mIsSocialLogin, + mLoginListener.getLoginMode() == LoginMode.JETPACK_LOGIN_ONLY, mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE ); mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java index c71973571ef..4b76f027d0a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java @@ -6,6 +6,7 @@ public enum LoginMode { FULL, SELFHOSTED_ONLY, WPCOM_LOGIN_ONLY, + JETPACK_LOGIN_ONLY, JETPACK_STATS, WPCOM_LOGIN_DEEPLINK, WPCOM_REAUTHENTICATE, diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 401b28de89b..ae2f55c75c1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -44,6 +44,7 @@ public class LoginWpcomService extends AutoForeground { private static final String ARG_PASSWORD = "ARG_PASSWORD"; private static final String ARG_SOCIAL_ID_TOKEN = "ARG_SOCIAL_ID_TOKEN"; private static final String ARG_SOCIAL_LOGIN = "ARG_SOCIAL_LOGIN"; + private static final String ARG_JETPACK_APP_LOGIN = "ARG_JETPACK_APP_LOGIN"; private static final String ARG_WOO_APP_LOGIN = "ARG_WOO_APP_LOGIN"; private static final String ARG_SOCIAL_SERVICE = "ARG_SOCIAL_SERVICE"; @@ -158,6 +159,7 @@ static class OnCredentialsOK { private String mIdToken; private String mService; private boolean mIsSocialLogin; + private boolean mIsJetpackAppLogin; private boolean mIsWooAppLogin; public static void loginWithEmailAndPassword( @@ -166,6 +168,7 @@ public static void loginWithEmailAndPassword( String password, String idToken, String service, boolean isSocialLogin, + boolean isJetpackAppLogin, boolean isWooAppLogin) { Intent intent = new Intent(context, LoginWpcomService.class); intent.putExtra(ARG_EMAIL, email); @@ -173,6 +176,7 @@ public static void loginWithEmailAndPassword( intent.putExtra(ARG_SOCIAL_ID_TOKEN, idToken); intent.putExtra(ARG_SOCIAL_SERVICE, service); intent.putExtra(ARG_SOCIAL_LOGIN, isSocialLogin); + intent.putExtra(ARG_JETPACK_APP_LOGIN, isJetpackAppLogin); intent.putExtra(ARG_WOO_APP_LOGIN, isWooAppLogin); context.startService(intent); } @@ -262,6 +266,7 @@ public int onStartCommand(@Nullable Intent intent, int flags, int startId) { mIdToken = intent.getStringExtra(ARG_SOCIAL_ID_TOKEN); mService = intent.getStringExtra(ARG_SOCIAL_SERVICE); mIsSocialLogin = intent.getBooleanExtra(ARG_SOCIAL_LOGIN, false); + mIsJetpackAppLogin = intent.getBooleanExtra(ARG_JETPACK_APP_LOGIN, false); mIsWooAppLogin = intent.getBooleanExtra(ARG_WOO_APP_LOGIN, false); AuthenticatePayload payload = new AuthenticatePayload(email, password); @@ -382,7 +387,8 @@ public void onAccountChanged(OnAccountChanged event) { } else if (event.causeOfChange == AccountAction.FETCH_SETTINGS) { setState(LoginStep.FETCHING_SITES); // The user's account settings have also been fetched and stored - now we can fetch the user's sites - FetchSitesPayload payload = SiteUtils.getFetchSitesPayload(mIsWooAppLogin); + FetchSitesPayload payload = + SiteUtils.getFetchSitesPayload(mIsJetpackAppLogin, mIsWooAppLogin); mDispatcher.dispatch(SiteActionBuilder.newFetchSitesAction(payload)); } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/util/SiteUtils.java b/libs/login/src/main/java/org/wordpress/android/login/util/SiteUtils.java index 88afeefac0f..5eff40a34ba 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/util/SiteUtils.java +++ b/libs/login/src/main/java/org/wordpress/android/login/util/SiteUtils.java @@ -48,8 +48,11 @@ private static SiteModel getSiteByMatchingUrl(List siteModelList, Str } @NonNull - public static FetchSitesPayload getFetchSitesPayload(boolean isWooAppLogin) { + public static FetchSitesPayload getFetchSitesPayload(boolean isJetpackAppLogin, + boolean isWooAppLogin) { ArrayList siteFilters = new ArrayList<>(); - return new FetchSitesPayload(siteFilters, !isWooAppLogin); + return new FetchSitesPayload( + siteFilters, !isJetpackAppLogin && !isWooAppLogin + ); } } From 41fd65d2d65eb59da7bb215634fa162dc3a2bd2e Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 3 Jul 2023 17:19:55 +0200 Subject: [PATCH 722/888] Analysis: Resolve to lower case deprecated warning Warning Message: "'toLowerCase(Locale): String' is deprecated. Use lowercase() instead." --- .../java/org/wordpress/android/login/LoginAnalyticsListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt index 8f8e3698e1d..a5dc2d5eb9d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt @@ -78,7 +78,7 @@ interface LoginAnalyticsListener { GOOGLE; fun asPropertyMap() = hashMapOf( - "source" to name.toLowerCase(Locale.ROOT) + "source" to name.lowercase(Locale.ROOT) ) } } From b6c4c92eac05e82e793b217d90de1d4c877cc872 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 3 Jul 2023 17:21:29 +0200 Subject: [PATCH 723/888] Analysis: Suppress deprecated warning Warning Message: "'onActivityCreated(Bundle?): Unit' is deprecated. Deprecated in Java" This warning is suppressed, that is, instead of it being resolved, since a resolution would require a proper investigation and testing. As such, it might be best to ignore this as out of scope, for now, and so as to not introduce any breaking changes to this library related module. --- .../org/wordpress/android/login/SignupConfirmationFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt index 400007fa0ce..b0b5492b49c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt @@ -117,7 +117,7 @@ class SignupConfirmationFragment : Fragment() { } } - @Suppress("OVERRIDE_DEPRECATION") + @Suppress("DEPRECATION", "OVERRIDE_DEPRECATION") override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) // important for accessibility - talkback From 7cc9813daea48ab7332fc778de5a22ad874d55bc Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 3 Jul 2023 17:33:00 +0200 Subject: [PATCH 724/888] Build: Automatically migrate to non-transitive r classes The changes in this commit was automatically applied on triggering the "Refactor" -> "Migration to Non-Transitive R Classes..." migration process via AS. --- .../java/org/wordpress/android/login/LoginEmailFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index e305051b327..a9902a6b966 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -319,7 +319,7 @@ protected void setupBottomButton(Button button) { private Spanned formatTosText(int stringResId) { final int primaryColorResId = ContextExtensionsKt.getColorResIdFromAttribute(getContext(), - R.attr.colorSecondary); + com.google.android.material.R.attr.colorSecondary); final String primaryColorHtml = HtmlUtils.colorResToHtmlColor(getContext(), primaryColorResId); return Html.fromHtml(getString(stringResId, "", "")); } From 778c61c57cacc7d48411724bbf580d4e2999a04a Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Tue, 11 Jul 2023 14:11:26 +0300 Subject: [PATCH 725/888] Build: Move package from android manifest to build files This is an AGP version '8.0' breaking change that requires 'namespace' in module-level build scripts, see build failure below: ------------------------------------------------------------------------ FAILURE: Build failed with an exception. * What went wrong: A problem occurred configuring project ':WordPressLoginFlow'. > Failed to notify project evaluation listener. > Could not create an instance of type com.android.build.api.variant.impl.LibraryVariantBuilderImpl. > Namespace not specified. Please specify a namespace in the module's build.gradle file like so: android { namespace 'com.example.namespace' } If the package attribute is specified in the source AndroidManifest.xml, it can be migrated automatically to the namespace value in the build.gradle file using the AGP Upgrade Assistant; please refer to https://developer.android.com/ studio/build/agp-upgrade-assistant for more information. > Could not get unknown property 'release' for SoftwareComponent container of type org.gradle.api.internal.component. DefaultSoftwareComponentContainer. ------------------------------------------------------------------------ Explanation: "You must set the namespace in the module-level 'build.gradle.kts' file, rather than the manifest file." For more info see: https://developer.android.com/build/releases/ gradle-plugin#namespace-dsl --- libs/login/build.gradle | 2 ++ libs/login/src/main/AndroidManifest.xml | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 libs/login/src/main/AndroidManifest.xml diff --git a/libs/login/build.gradle b/libs/login/build.gradle index bdaf9443167..238cf42f267 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -21,6 +21,8 @@ repositories { } android { + namespace "org.wordpress.android.login" + compileSdkVersion rootProject.compileSdkVersion defaultConfig { diff --git a/libs/login/src/main/AndroidManifest.xml b/libs/login/src/main/AndroidManifest.xml deleted file mode 100644 index 66ba33cd212..00000000000 --- a/libs/login/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - From ab9065103132098cf284e52323ec46e0abe04944 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Tue, 11 Jul 2023 14:12:38 +0300 Subject: [PATCH 726/888] Build: Enable build config build feature for wordpress login flow This is an AGP version '8.0' breaking change that changes the build option default values, see build failure below: ------------------------------------------------------------------------ FAILURE: Build failed with an exception. * What went wrong: A problem occurred configuring project ':WordPressLoginFlow'. > Failed to notify project evaluation listener. > com.android.builder.errors.EvalIssueException: Build Type 'debug' contains custom BuildConfig fields, but the feature is disabled. > Could not get unknown property 'release' for SoftwareComponent container of type org.gradle.api.internal.component .DefaultSoftwareComponentContainer. ------------------------------------------------------------------------ Explanation: "Starting with AGP 8.0, the default values for these flags have changed to improve build performance. AGP 8.0 doesn't generate 'BuildConfig' by default. You need to specify this option using the DSL in the projects where you need it." For more info see: https://developer.android.com/build/releases/ gradle-plugin#default-changes --- libs/login/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 238cf42f267..2a642d2d053 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -31,6 +31,9 @@ android { vectorDrawables.useSupportLibrary = true } + buildFeatures { + buildConfig true + } } dependencies { From c756345feb20bd87cacd15897f534d000e9f9679 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Sat, 22 Jul 2023 00:46:41 -0400 Subject: [PATCH 727/888] Update publish-to-s3 Gradle plugin to 0.8.0 --- libs/login/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 2a642d2d053..00c90506165 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -108,7 +108,6 @@ project.afterEvaluate { groupId "org.wordpress" artifactId "login" - artifact tasks.named("androidSourcesJar") // version is set by 'publish-to-s3' plugin } } From b724eae50439f9ecabd42b4ab397f542923d5227 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Thu, 10 Aug 2023 17:56:07 -0300 Subject: [PATCH 728/888] Remove JetpackCP filter when adding SH sites from Jetpack app --- .../org/wordpress/android/login/LoginBaseFormFragment.java | 6 ++++-- .../org/wordpress/android/login/LoginEmailFragment.java | 1 + .../main/java/org/wordpress/android/login/LoginMode.java | 1 + .../wordpress/android/login/LoginSiteAddressFragment.java | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index c66e1d10a0a..1d066d25e4a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -344,8 +344,10 @@ public void onAccountChanged(OnAccountChanged event) { } protected boolean isJetpackAppLogin() { - return (mLoginListener instanceof LoginListener) - && ((LoginListener) mLoginListener).getLoginMode() == LoginMode.JETPACK_LOGIN_ONLY; + if (!(mLoginListener instanceof LoginListener)) return false; + + LoginMode mode = ((LoginListener) mLoginListener).getLoginMode(); + return mode == LoginMode.JETPACK_LOGIN_ONLY || mode == LoginMode.JETPACK_SELFHOSTED; } protected boolean isWooAppLogin() { diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java index a9902a6b966..b65dbc299fe 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailFragment.java @@ -157,6 +157,7 @@ protected void setupLabel(@NonNull TextView label) { case FULL: case WPCOM_LOGIN_ONLY: case JETPACK_LOGIN_ONLY: + case JETPACK_SELFHOSTED: case SELFHOSTED_ONLY: if (!TextUtils.isEmpty(mLoginSiteUrl)) { label.setText(Html.fromHtml( diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java b/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java index 4b76f027d0a..b715b9a6baf 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginMode.java @@ -5,6 +5,7 @@ public enum LoginMode { FULL, SELFHOSTED_ONLY, + JETPACK_SELFHOSTED, WPCOM_LOGIN_ONLY, JETPACK_LOGIN_ONLY, JETPACK_STATS, diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index 93a3b602e7e..8d99ea6b837 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -444,7 +444,8 @@ private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo) { private void handleConnectSiteInfoForWordPress(ConnectSiteInfoPayload siteInfo) { if (siteInfo.isWPCom) { // It's a Simple or Atomic site - if (mLoginListener.getLoginMode() == LoginMode.SELFHOSTED_ONLY) { + LoginMode mode = mLoginListener.getLoginMode(); + if (mode == LoginMode.SELFHOSTED_ONLY || mode == LoginMode.JETPACK_SELFHOSTED) { // We're only interested in self-hosted sites if (siteInfo.hasJetpack) { // This is an Atomic site, so treat it as self-hosted and start the discovery process From 59bb474d074bc3d99c461753f2e9a2a5aff3e32e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 19 Oct 2023 19:03:15 -0300 Subject: [PATCH 729/888] Handle NEEDS_SECURITY_KEY error scenario --- .../wordpress/android/login/LoginWpcomService.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index ae2f55c75c1..05864eedcfb 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -59,6 +59,8 @@ public enum LoginStep { FAILURE_EMAIL_WRONG_PASSWORD, FAILURE_2FA, FAILURE_SOCIAL_2FA, + FAILURE_SECURITY_KEY, + FAILURE_SOCIAL_SECURITY_KEY, FAILURE_FETCHING_ACCOUNT, FAILURE_CANNOT_ADD_DUPLICATE_SITE, FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL, @@ -302,6 +304,16 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) setState(LoginStep.FAILURE_2FA); } + case NEEDS_SECURITY_KEY: + // login credentials were correct anyway so, offer to save to SmartLock + signalCredentialsOK(); + + if (mIsSocialLogin) { + setState(LoginStep.FAILURE_SOCIAL_SECURITY_KEY); + } else { + setState(LoginStep.FAILURE_SECURITY_KEY); + } + break; case EMAIL_LOGIN_NOT_ALLOWED: setState(LoginStep.FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL); From 3c51489519ba6cc3049bcf82b439ab59b521c64e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 19 Oct 2023 19:17:29 -0300 Subject: [PATCH 730/888] Add security key events to LoginListener --- .../main/java/org/wordpress/android/login/LoginListener.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 21226e90c7f..ade1b97801b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -50,6 +50,8 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void needs2fa(String email, String password); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); + void needsSecurityKey(String userId, String nonceInfo); + void needsSocialSecurityKey(String userId, String nonceInfo); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From 70e072648d44ea78c2e2865ed7c7de3a46c19091 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 19 Oct 2023 19:28:38 -0300 Subject: [PATCH 731/888] Fix missing break in error switch case --- .../java/org/wordpress/android/login/LoginWpcomService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 05864eedcfb..9226f025ad7 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -303,7 +303,7 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) } else { setState(LoginStep.FAILURE_2FA); } - + break; case NEEDS_SECURITY_KEY: // login credentials were correct anyway so, offer to save to SmartLock signalCredentialsOK(); @@ -313,7 +313,6 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) } else { setState(LoginStep.FAILURE_SECURITY_KEY); } - break; case EMAIL_LOGIN_NOT_ALLOWED: setState(LoginStep.FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL); From bc7206f727fcf93a37a7984e1cc374fce5de08dd Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 19 Oct 2023 20:56:42 -0300 Subject: [PATCH 732/888] Add security key button --- libs/login/src/main/res/layout/login_2fa_screen.xml | 9 +++++++++ libs/login/src/main/res/values/strings.xml | 1 + 2 files changed, 10 insertions(+) diff --git a/libs/login/src/main/res/layout/login_2fa_screen.xml b/libs/login/src/main/res/layout/login_2fa_screen.xml index b6aa8734ed4..129451b9e76 100644 --- a/libs/login/src/main/res/layout/login_2fa_screen.xml +++ b/libs/login/src/main/res/layout/login_2fa_screen.xml @@ -22,6 +22,15 @@ android:hint="@string/verification_code" android:inputType="numberDecimal" /> + + Almost there! Please enter the verification code from your Authenticator app. We sent a text message to the phone number ending in %s. Please enter the verification code in the SMS. Text me a code instead + Continue with security key Text me another code instead Requesting a verification code via SMS. Hmm, we can\'t find a WordPress.com account connected to this email address. From 214950f477cf0819950e5db32a20e29df5951392 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 19 Oct 2023 21:04:15 -0300 Subject: [PATCH 733/888] Bind security key button in Login2FaFragment --- .../java/org/wordpress/android/login/Login2FaFragment.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 154b00dfbb7..53a1abd2fb4 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -92,6 +92,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple ArrayList mOldSitesIDs; private Button mOtpButton; + private Button mSecurityKeyButton; private String mEmailAddress; private String mIdToken; private String mNonce; @@ -186,6 +187,11 @@ public void onClick(View v) { } } }); + + mSecurityKeyButton = rootView.findViewById(R.id.login_security_key_button); + mSecurityKeyButton.setOnClickListener(view -> { + + }); } @Override From afa50597b04471c85f525b26ec0ffafa62eb4aa0 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 19 Oct 2023 21:08:03 -0300 Subject: [PATCH 734/888] Handle Security Key button click --- .../org/wordpress/android/login/Login2FaFragment.java | 11 ++++++++++- .../wordpress/android/login/LoginAnalyticsListener.kt | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 53a1abd2fb4..f41b793f7a5 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -190,7 +190,8 @@ public void onClick(View v) { mSecurityKeyButton = rootView.findViewById(R.id.login_security_key_button); mSecurityKeyButton.setOnClickListener(view -> { - + mAnalyticsListener.trackContinueWithSecurityKeyClicked(); + doAuthWithSecurityKeyAction(); }); } @@ -330,6 +331,14 @@ private void doAuthAction(@StringRes int messageId, String twoStepCode, boolean } } + private void doAuthWithSecurityKeyAction() { + if (!NetworkUtils.checkConnection(getActivity())) { + return; + } + + + } + private String getAuthCodeFromClipboard() { ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(CLIPBOARD_SERVICE); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt index a5dc2d5eb9d..ded0e4367e7 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt @@ -55,6 +55,7 @@ interface LoginAnalyticsListener { fun trackConnectedSiteInfoSucceeded(properties: Map) fun trackFailure(message: String?) fun trackSendCodeWithTextClicked() + fun trackContinueWithSecurityKeyClicked() fun trackSubmit2faCodeClicked() fun trackSubmitClicked() fun trackRequestMagicLinkClick() From 8b87deb89cff8002eb44f677574e92e326667fc6 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Fri, 20 Oct 2023 05:55:13 -0300 Subject: [PATCH 735/888] Do initial handling of security key payload to FluxC --- .../java/org/wordpress/android/login/Login2FaFragment.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index f41b793f7a5..fac819d5e91 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -28,6 +28,7 @@ import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.fluxc.generated.AccountActionBuilder; import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder; +import org.wordpress.android.fluxc.store.AccountStore.AuthSecurityKeyPayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticatePayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; @@ -336,7 +337,10 @@ private void doAuthWithSecurityKeyAction() { return; } - + AuthSecurityKeyPayload payload = new AuthSecurityKeyPayload(0, 0, "", + "", new byte[0], new byte[0], new byte[0], new byte[0], + new byte[0]); + mDispatcher.dispatch(AuthenticationActionBuilder.newAuthenticateSecurityKeyAction(payload)); } private String getAuthCodeFromClipboard() { From 364ca4ee2c0fbe3acfde809e9dc7c9b9c6afa4b6 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Sat, 21 Oct 2023 23:34:32 -0300 Subject: [PATCH 736/888] Update Security Key Payload with actual data --- .../java/org/wordpress/android/login/Login2FaFragment.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index fac819d5e91..d468f59ef11 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -28,11 +28,11 @@ import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.fluxc.generated.AccountActionBuilder; import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder; -import org.wordpress.android.fluxc.store.AccountStore.AuthSecurityKeyPayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticatePayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; import org.wordpress.android.fluxc.store.AccountStore.OnSocialChanged; +import org.wordpress.android.fluxc.store.AccountStore.PushSecurityKeyPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialAuthPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialSmsPayload; @@ -337,9 +337,7 @@ private void doAuthWithSecurityKeyAction() { return; } - AuthSecurityKeyPayload payload = new AuthSecurityKeyPayload(0, 0, "", - "", new byte[0], new byte[0], new byte[0], new byte[0], - new byte[0]); + PushSecurityKeyPayload payload = new PushSecurityKeyPayload(mUserId, mNonce); mDispatcher.dispatch(AuthenticationActionBuilder.newAuthenticateSecurityKeyAction(payload)); } From 3119e6fd93ce4347fa921e123a8daf933a06e6c0 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 11:02:52 -0300 Subject: [PATCH 737/888] Fix incorrect configuration of Security key button --- libs/login/src/main/res/layout/login_2fa_screen.xml | 2 +- libs/login/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/res/layout/login_2fa_screen.xml b/libs/login/src/main/res/layout/login_2fa_screen.xml index 129451b9e76..cae797c6023 100644 --- a/libs/login/src/main/res/layout/login_2fa_screen.xml +++ b/libs/login/src/main/res/layout/login_2fa_screen.xml @@ -29,7 +29,7 @@ android:layout_height="wrap_content" android:paddingEnd="@dimen/margin_none" android:paddingStart="@dimen/margin_none" - tools:text="@string/login_text_security_key" /> + android:text="@string/login_text_security_key" /> Almost there! Please enter the verification code from your Authenticator app. We sent a text message to the phone number ending in %s. Please enter the verification code in the SMS. Text me a code instead - Continue with security key + Use a security key Text me another code instead Requesting a verification code via SMS. Hmm, we can\'t find a WordPress.com account connected to this email address. From 20b07df2845f83ac4deeceeeff58ac1bc93e5aff Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 13:11:03 -0300 Subject: [PATCH 738/888] Update Login2FaFragment callback interface and payloads --- .../wordpress/android/login/Login2FaFragment.java | 15 +++++++++++++-- .../wordpress/android/login/LoginListener.java | 4 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index d468f59ef11..94f8e736544 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -32,6 +32,7 @@ import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; import org.wordpress.android.fluxc.store.AccountStore.OnSocialChanged; +import org.wordpress.android.fluxc.store.AccountStore.OnWebauthnChallengeReceived; import org.wordpress.android.fluxc.store.AccountStore.PushSecurityKeyPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialAuthPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialPayload; @@ -336,8 +337,8 @@ private void doAuthWithSecurityKeyAction() { if (!NetworkUtils.checkConnection(getActivity())) { return; } - - PushSecurityKeyPayload payload = new PushSecurityKeyPayload(mUserId, mNonce); + //TODO: Check if security key is available, if not, trigger PushSecurityKeyPayload + PushSecurityKeyPayload payload = new PushSecurityKeyPayload(mEmailAddress, mPassword); mDispatcher.dispatch(AuthenticationActionBuilder.newAuthenticateSecurityKeyAction(payload)); } @@ -554,4 +555,14 @@ private void setTextForSms() { mOtpButton.setText(getString(R.string.login_text_otp_another)); mSentSmsCode = true; } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { + if (event.isError()) { + //TODO: Handle error + return; + } + mLoginListener.signSecurityKey(event.challengeInfo); + } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index ade1b97801b..61cc3c8cbbc 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -6,6 +6,7 @@ import androidx.annotation.Nullable; import org.wordpress.android.fluxc.network.MemorizingTrustManager; +import org.wordpress.android.fluxc.network.rest.wpcom.auth.passkey.WebauthnChallengeInfo; import org.wordpress.android.fluxc.store.SiteStore; import org.wordpress.android.fluxc.store.SiteStore.ConnectSiteInfoPayload; @@ -50,8 +51,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void needs2fa(String email, String password); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); - void needsSecurityKey(String userId, String nonceInfo); - void needsSocialSecurityKey(String userId, String nonceInfo); + void signSecurityKey(WebauthnChallengeInfo challengeInfo); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From 2f3f1374947ea4aafd08f7b0b5c518352412e79e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 13:19:47 -0300 Subject: [PATCH 739/888] Fix lint issues --- .../java/org/wordpress/android/login/Login2FaFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 94f8e736544..ea8142840b8 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -337,7 +337,7 @@ private void doAuthWithSecurityKeyAction() { if (!NetworkUtils.checkConnection(getActivity())) { return; } - //TODO: Check if security key is available, if not, trigger PushSecurityKeyPayload + // TODO: Check if security key is available, if not, trigger PushSecurityKeyPayload PushSecurityKeyPayload payload = new PushSecurityKeyPayload(mEmailAddress, mPassword); mDispatcher.dispatch(AuthenticationActionBuilder.newAuthenticateSecurityKeyAction(payload)); } @@ -560,7 +560,7 @@ private void setTextForSms() { @Subscribe(threadMode = ThreadMode.MAIN) public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { if (event.isError()) { - //TODO: Handle error + // TODO: Handle error return; } mLoginListener.signSecurityKey(event.challengeInfo); From a588a9876bbdb0452ecb215a7215eb67c1d1d371 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 19:38:36 -0300 Subject: [PATCH 740/888] Handle the OnSecurityKeyAuthStarted event --- .../android/login/LoginEmailPasswordFragment.java | 14 ++++++++++++++ .../org/wordpress/android/login/LoginListener.java | 1 + 2 files changed, 15 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 3645d8f7a65..d02fd06888c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -22,6 +22,7 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import org.wordpress.android.fluxc.store.AccountStore.OnSecurityKeyAuthStarted; import org.wordpress.android.login.LoginWpcomService.LoginState; import org.wordpress.android.login.LoginWpcomService.OnCredentialsOK; import org.wordpress.android.login.util.AvatarHelper; @@ -39,6 +40,7 @@ import java.util.ArrayList; import dagger.android.support.AndroidSupportInjection; +import kotlin.Suppress; public class LoginEmailPasswordFragment extends LoginBaseFormFragment implements TextWatcher, OnEditorCommitListener { @@ -342,6 +344,13 @@ public void onCredentialsOK(OnCredentialsOK event) { saveCredentialsInSmartLock(mLoginListener, mEmailAddress, mRequestedPassword); } + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSecurityKeyAuthStarted(OnSecurityKeyAuthStarted event) { + mLoginListener.needsSecurityKey(event.userId, event.webauthnNonce); + } + + @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) public void onLoginStateUpdated(LoginState loginState) { @@ -378,6 +387,11 @@ public void onLoginStateUpdated(LoginState loginState) { // consume the state so we don't relauch the 2FA dialog if user backs up LoginWpcomService.clearLoginServiceState(); break; + case FAILURE_SECURITY_KEY: + // TODO: remove this, not necessary + onLoginFinished(false); + // consume the state so we don't relauch the 2FA dialog if user backs up + LoginWpcomService.clearLoginServiceState(); case FAILURE_FETCHING_ACCOUNT: onLoginFinished(false); showError(getString(R.string.error_fetch_my_profile)); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 61cc3c8cbbc..86b33325c96 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -51,6 +51,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void needs2fa(String email, String password); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); + void needsSecurityKey(String userId, String webauthnNonce); void signSecurityKey(WebauthnChallengeInfo challengeInfo); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From b0e864008861033b57c40ebb08c9424893624ec1 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 19:41:51 -0300 Subject: [PATCH 741/888] Create Security Key newInstance function for Login2FaFragment --- .../wordpress/android/login/Login2FaFragment.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index ea8142840b8..cf9f8cbfc84 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -74,6 +74,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private static final String ARG_2FA_USER_ID = "ARG_2FA_USER_ID"; private static final String ARG_EMAIL_ADDRESS = "ARG_EMAIL_ADDRESS"; private static final String ARG_PASSWORD = "ARG_PASSWORD"; + private static final String ARG_WEBAUTHN_NONCE = "WEBAUTHN_NONCE"; private static final int LENGTH_NONCE_AUTHENTICATOR = 6; private static final int LENGTH_NONCE_BACKUP = 8; private static final int LENGTH_NONCE_SMS = 7; @@ -99,6 +100,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private String mIdToken; private String mNonce; private String mNonceAuthenticator; + private String mWebauthnNonce; private String mNonceBackup; private String mNonceSms; private String mPassword; @@ -120,6 +122,18 @@ public static Login2FaFragment newInstance(String emailAddress, String password) return fragment; } + public static Login2FaFragment newInstanceSecurityKey(String emailAddress, String password, + String userId, String webauthnNonce) { + Login2FaFragment fragment = new Login2FaFragment(); + Bundle args = new Bundle(); + args.putString(ARG_EMAIL_ADDRESS, emailAddress); + args.putString(ARG_PASSWORD, password); + args.putString(ARG_2FA_USER_ID, userId); + args.putString(ARG_WEBAUTHN_NONCE, webauthnNonce); + fragment.setArguments(args); + return fragment; + } + public static Login2FaFragment newInstanceSocial(String emailAddress, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms) { @@ -243,6 +257,7 @@ public void onCreate(Bundle savedInstanceState) { mIsSocialLogin = getArguments().getBoolean(ARG_2FA_IS_SOCIAL); mIsSocialLoginConnect = getArguments().getBoolean(ARG_2FA_IS_SOCIAL_CONNECT); mService = getArguments().getString(ARG_2FA_SOCIAL_SERVICE); + mWebauthnNonce = getArguments().getString(ARG_WEBAUTHN_NONCE); if (savedInstanceState != null) { // Overwrite argument nonce values with saved state values on device rotation. From 8d05f76b270bad8fd2959cb87a8c46f288de51e2 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 19:43:02 -0300 Subject: [PATCH 742/888] Use correct data when dispatching PushSecurityKeyPayload --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index cf9f8cbfc84..173e411537e 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -353,7 +353,7 @@ private void doAuthWithSecurityKeyAction() { return; } // TODO: Check if security key is available, if not, trigger PushSecurityKeyPayload - PushSecurityKeyPayload payload = new PushSecurityKeyPayload(mEmailAddress, mPassword); + PushSecurityKeyPayload payload = new PushSecurityKeyPayload(mUserId, mWebauthnNonce); mDispatcher.dispatch(AuthenticationActionBuilder.newAuthenticateSecurityKeyAction(payload)); } From 717aadcb3579db57d672697868a30de6d2cf42f4 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 19:43:52 -0300 Subject: [PATCH 743/888] Fix checkstyle issues --- .../org/wordpress/android/login/LoginEmailPasswordFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index d02fd06888c..fafab716518 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -40,7 +40,6 @@ import java.util.ArrayList; import dagger.android.support.AndroidSupportInjection; -import kotlin.Suppress; public class LoginEmailPasswordFragment extends LoginBaseFormFragment implements TextWatcher, OnEditorCommitListener { @@ -392,6 +391,7 @@ public void onLoginStateUpdated(LoginState loginState) { onLoginFinished(false); // consume the state so we don't relauch the 2FA dialog if user backs up LoginWpcomService.clearLoginServiceState(); + break; case FAILURE_FETCHING_ACCOUNT: onLoginFinished(false); showError(getString(R.string.error_fetch_my_profile)); From 903d91ff5be16f355aff9d50e6d2222c94dd5799 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 21:12:49 -0300 Subject: [PATCH 744/888] Adjust LoginWpcomService --- .../org/wordpress/android/login/LoginWpcomService.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 9226f025ad7..8e9cbf1838a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -20,6 +20,7 @@ import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; import org.wordpress.android.fluxc.store.AccountStore.OnAccountChanged; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; +import org.wordpress.android.fluxc.store.AccountStore.OnSecurityKeyAuthStarted; import org.wordpress.android.fluxc.store.AccountStore.OnSocialChanged; import org.wordpress.android.fluxc.store.AccountStore.PushSocialPayload; import org.wordpress.android.fluxc.store.SiteStore.FetchSitesPayload; @@ -55,6 +56,7 @@ public enum LoginStep { FETCHING_ACCOUNT(50), FETCHING_SETTINGS(75), FETCHING_SITES(100), + FETCHING_SECURITY_KEY(100), SUCCESS, FAILURE_EMAIL_WRONG_PASSWORD, FAILURE_2FA, @@ -428,4 +430,11 @@ public void onSiteChanged(OnSiteChanged event) { setState(LoginStep.SUCCESS); } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSecurityKeyAuthStarted(OnSecurityKeyAuthStarted event) { + LoginWpcomService.clearLoginServiceState(); + setState(LoginStep.SUCCESS); + } } From c3244f8d7b8105943415e9ce430870adde23c550 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 21:13:20 -0300 Subject: [PATCH 745/888] Handle notification when fetching the security key --- .../main/java/org/wordpress/android/login/LoginWpcomService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 8e9cbf1838a..cd114bf8faa 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -211,6 +211,7 @@ public Notification getNotification(LoginState state) { case FETCHING_ACCOUNT: case FETCHING_SETTINGS: case FETCHING_SITES: + case FETCHING_SECURITY_KEY: return LoginNotification.progress(this, state.getStep().progressPercent); case SUCCESS: return LoginNotification.success(this); From e9379536628c1dd7f6524d32e53fb4bfb48337fd Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 21:26:37 -0300 Subject: [PATCH 746/888] Test adjustment --- .../java/org/wordpress/android/login/LoginWpcomService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index cd114bf8faa..238b5a4b263 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -435,7 +435,7 @@ public void onSiteChanged(OnSiteChanged event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyAuthStarted(OnSecurityKeyAuthStarted event) { - LoginWpcomService.clearLoginServiceState(); + //LoginWpcomService.clearLoginServiceState(); setState(LoginStep.SUCCESS); } } From f617f44affa17db102c11a481cbca4b1c7a1afcd Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 21:37:01 -0300 Subject: [PATCH 747/888] Test adjustment --- .../java/org/wordpress/android/login/LoginWpcomService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 238b5a4b263..121f79b417b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -435,7 +435,7 @@ public void onSiteChanged(OnSiteChanged event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyAuthStarted(OnSecurityKeyAuthStarted event) { - //LoginWpcomService.clearLoginServiceState(); + // LoginWpcomService.clearLoginServiceState(); setState(LoginStep.SUCCESS); } } From a974f1325f9c869dd270bdf9e3ad8971e92d08ba Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 22:24:09 -0300 Subject: [PATCH 748/888] Improve how WPcom Service handles the Security Key event from FluxC --- .../login/LoginEmailPasswordFragment.java | 4 ++-- .../android/login/LoginWpcomService.java | 20 +++++++++++++++---- libs/login/src/main/res/values/strings.xml | 1 + 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index fafab716518..ba394465061 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -22,9 +22,9 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; -import org.wordpress.android.fluxc.store.AccountStore.OnSecurityKeyAuthStarted; import org.wordpress.android.login.LoginWpcomService.LoginState; import org.wordpress.android.login.LoginWpcomService.OnCredentialsOK; +import org.wordpress.android.login.LoginWpcomService.SecurityKeyRequested; import org.wordpress.android.login.util.AvatarHelper; import org.wordpress.android.login.util.AvatarHelper.AvatarRequestListener; import org.wordpress.android.login.util.SiteUtils; @@ -345,7 +345,7 @@ public void onCredentialsOK(OnCredentialsOK event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onSecurityKeyAuthStarted(OnSecurityKeyAuthStarted event) { + public void onSecurityKeyAuthStarted(SecurityKeyRequested event) { mLoginListener.needsSecurityKey(event.userId, event.webauthnNonce); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 121f79b417b..b2eee0b59f6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -56,7 +56,7 @@ public enum LoginStep { FETCHING_ACCOUNT(50), FETCHING_SETTINGS(75), FETCHING_SITES(100), - FETCHING_SECURITY_KEY(100), + SECURITY_KEY_NEEDED, SUCCESS, FAILURE_EMAIL_WRONG_PASSWORD, FAILURE_2FA, @@ -156,6 +156,16 @@ static class OnCredentialsOK { OnCredentialsOK() {} } + static class SecurityKeyRequested{ + public String userId; + public String webauthnNonce; + + SecurityKeyRequested(String userId, String webauthnNonce) { + this.userId = userId; + this.webauthnNonce = webauthnNonce; + } + } + @Inject Dispatcher mDispatcher; @Inject LoginAnalyticsListener mAnalyticsListener; @@ -211,7 +221,6 @@ public Notification getNotification(LoginState state) { case FETCHING_ACCOUNT: case FETCHING_SETTINGS: case FETCHING_SITES: - case FETCHING_SECURITY_KEY: return LoginNotification.progress(this, state.getStep().progressPercent); case SUCCESS: return LoginNotification.success(this); @@ -223,6 +232,8 @@ public Notification getNotification(LoginState state) { return LoginNotification.failure(this, R.string.notification_2fa_needed); case FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL: return LoginNotification.failure(this, R.string.notification_wpcom_username_needed); + case SECURITY_KEY_NEEDED: + return LoginNotification.failure(this, R.string.notification_security_key_needed); case FAILURE_FETCHING_ACCOUNT: case FAILURE_CANNOT_ADD_DUPLICATE_SITE: case FAILURE: @@ -435,7 +446,8 @@ public void onSiteChanged(OnSiteChanged event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyAuthStarted(OnSecurityKeyAuthStarted event) { - // LoginWpcomService.clearLoginServiceState(); - setState(LoginStep.SUCCESS); + signalCredentialsOK(); + setState(LoginStep.SECURITY_KEY_NEEDED); + EventBus.getDefault().post(new SecurityKeyRequested(event.userId, event.webauthnNonce)); } } diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 4a5ff3b6b6c..03b4d58f45a 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -122,6 +122,7 @@ Please provide an authentication code to continue. An error has occurred. Please log in with your username and password. + Please provide your security key to continue. Email address login From ff899a05888238a3d51bfa60eb2ee0eac59cb761 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 22:24:33 -0300 Subject: [PATCH 749/888] Fix checkstyle issues --- .../java/org/wordpress/android/login/LoginWpcomService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index b2eee0b59f6..261ef47da7a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -156,7 +156,7 @@ static class OnCredentialsOK { OnCredentialsOK() {} } - static class SecurityKeyRequested{ + static class SecurityKeyRequested { public String userId; public String webauthnNonce; From 6702597c320d13626502e71e8a9a2dfb0a277e45 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 22:42:12 -0300 Subject: [PATCH 750/888] Adjust error handlign in LoginEmailPasswordFragment --- .../wordpress/android/login/LoginEmailPasswordFragment.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index ba394465061..88390a8c31c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -386,8 +386,7 @@ public void onLoginStateUpdated(LoginState loginState) { // consume the state so we don't relauch the 2FA dialog if user backs up LoginWpcomService.clearLoginServiceState(); break; - case FAILURE_SECURITY_KEY: - // TODO: remove this, not necessary + case SECURITY_KEY_NEEDED: onLoginFinished(false); // consume the state so we don't relauch the 2FA dialog if user backs up LoginWpcomService.clearLoginServiceState(); From 68810df0cb981ef32e6ed61a3c869f2bc2e576f2 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 23 Oct 2023 23:46:32 -0300 Subject: [PATCH 751/888] Update payload references --- .../java/org/wordpress/android/login/Login2FaFragment.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 173e411537e..52f9db65f95 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -33,10 +33,10 @@ import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; import org.wordpress.android.fluxc.store.AccountStore.OnSocialChanged; import org.wordpress.android.fluxc.store.AccountStore.OnWebauthnChallengeReceived; -import org.wordpress.android.fluxc.store.AccountStore.PushSecurityKeyPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialAuthPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialSmsPayload; +import org.wordpress.android.fluxc.store.AccountStore.StartSecurityKeyChallengePayload; import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; @@ -353,8 +353,9 @@ private void doAuthWithSecurityKeyAction() { return; } // TODO: Check if security key is available, if not, trigger PushSecurityKeyPayload - PushSecurityKeyPayload payload = new PushSecurityKeyPayload(mUserId, mWebauthnNonce); - mDispatcher.dispatch(AuthenticationActionBuilder.newAuthenticateSecurityKeyAction(payload)); + StartSecurityKeyChallengePayload payload = new StartSecurityKeyChallengePayload( + mUserId, mWebauthnNonce); + mDispatcher.dispatch(AuthenticationActionBuilder.newSecurityKeyChallengeAction(payload)); } private String getAuthCodeFromClipboard() { From 78af5c307d167085456604957d82c0b6d056e74d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 24 Oct 2023 22:25:22 -0300 Subject: [PATCH 752/888] Adjust LoginListener signature --- .../main/java/org/wordpress/android/login/LoginListener.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 86b33325c96..9a690327adb 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -6,7 +6,6 @@ import androidx.annotation.Nullable; import org.wordpress.android.fluxc.network.MemorizingTrustManager; -import org.wordpress.android.fluxc.network.rest.wpcom.auth.passkey.WebauthnChallengeInfo; import org.wordpress.android.fluxc.store.SiteStore; import org.wordpress.android.fluxc.store.SiteStore.ConnectSiteInfoPayload; @@ -52,7 +51,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); void needsSecurityKey(String userId, String webauthnNonce); - void signSecurityKey(WebauthnChallengeInfo challengeInfo); + void signSecurityKey(String challengeRequestJson); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From 7950443d9ac4597f521ddf0415be49a34554897a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 24 Oct 2023 22:49:46 -0300 Subject: [PATCH 753/888] Update LoginListener to also relay userId and username --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 2 +- .../main/java/org/wordpress/android/login/LoginListener.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 52f9db65f95..d716f96e54b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -579,6 +579,6 @@ public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { // TODO: Handle error return; } - mLoginListener.signSecurityKey(event.challengeInfo); + mLoginListener.signSecurityKey(event.challengeInfo, event.mUserId, mEmailAddress); } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 9a690327adb..fc77ae75546 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -51,7 +51,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); void needsSecurityKey(String userId, String webauthnNonce); - void signSecurityKey(String challengeRequestJson); + void signSecurityKey(String challengeRequestJson, String userId, String username); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From ab550a3703c4ddc22011b7dee3af32ca7757768a Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:15:44 +0530 Subject: [PATCH 754/888] Updated enter_verification_code Reason: https://github.com/wordpress-mobile/WordPress-Android/issues/19442 --- libs/login/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 5857bbe51f2..8a05e024af2 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -20,7 +20,7 @@ Next Check email Open Mail - Almost there! Please enter the verification code from your Authenticator app. + Almost there! Please enter the verification code for WordPress.com from your authenticator app. We sent a text message to the phone number ending in %s. Please enter the verification code in the SMS. Text me a code instead Text me another code instead From 0f826b393b7553771739f2613e7d30535f6bb9cb Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 26 Oct 2023 13:24:49 -0300 Subject: [PATCH 755/888] Adjust AuthenticationAction builder usage when triggering the security challenge payload --- .../java/org/wordpress/android/login/Login2FaFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index d716f96e54b..a8b6f002aaa 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -355,7 +355,8 @@ private void doAuthWithSecurityKeyAction() { // TODO: Check if security key is available, if not, trigger PushSecurityKeyPayload StartSecurityKeyChallengePayload payload = new StartSecurityKeyChallengePayload( mUserId, mWebauthnNonce); - mDispatcher.dispatch(AuthenticationActionBuilder.newSecurityKeyChallengeAction(payload)); + mDispatcher.dispatch(AuthenticationActionBuilder + .newStartSecurityKeyChallengeAction(payload)); } private String getAuthCodeFromClipboard() { From 517bc5b68227a64b08eca460f05714df48c67d92 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Mon, 30 Oct 2023 17:51:45 +0100 Subject: [PATCH 756/888] Remove fetching user subscriptions on login with 2FA enabled --- .../java/org/wordpress/android/login/LoginBaseFormFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java index 1d066d25e4a..b401ba931ab 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginBaseFormFragment.java @@ -339,7 +339,6 @@ public void onAccountChanged(OnAccountChanged event) { FetchSitesPayload payload = SiteUtils.getFetchSitesPayload(isJetpackAppLogin(), isWooAppLogin()); mDispatcher.dispatch(SiteActionBuilder.newFetchSitesAction(payload)); - mDispatcher.dispatch(AccountActionBuilder.newFetchSubscriptionsAction()); } } From 277849f93af35d2ea7140bb961b100261e765a5d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 30 Oct 2023 20:24:26 -0300 Subject: [PATCH 757/888] Define passkey files --- .../org/wordpress/android/login/passkey/PasskeyFIDOHandler.kt | 4 ++++ .../org/wordpress/android/login/passkey/WebauthnModels.kt | 2 ++ 2 files changed, 6 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/passkey/PasskeyFIDOHandler.kt create mode 100644 libs/login/src/main/java/org/wordpress/android/login/passkey/WebauthnModels.kt diff --git a/libs/login/src/main/java/org/wordpress/android/login/passkey/PasskeyFIDOHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/passkey/PasskeyFIDOHandler.kt new file mode 100644 index 00000000000..3706538c0db --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/passkey/PasskeyFIDOHandler.kt @@ -0,0 +1,4 @@ +package org.wordpress.android.login.passkey + +class PasskeyFIDOHandler { +} \ No newline at end of file diff --git a/libs/login/src/main/java/org/wordpress/android/login/passkey/WebauthnModels.kt b/libs/login/src/main/java/org/wordpress/android/login/passkey/WebauthnModels.kt new file mode 100644 index 00000000000..e37da2af0f6 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/passkey/WebauthnModels.kt @@ -0,0 +1,2 @@ +package org.wordpress.android.login.passkey + From 2eecc5501c784f4aa149aa51fb5e131153a71d99 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 30 Oct 2023 20:26:14 -0300 Subject: [PATCH 758/888] Define Base64 functions --- .../org/wordpress/android/login/passkey/Base64Ext.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/passkey/Base64Ext.kt diff --git a/libs/login/src/main/java/org/wordpress/android/login/passkey/Base64Ext.kt b/libs/login/src/main/java/org/wordpress/android/login/passkey/Base64Ext.kt new file mode 100644 index 00000000000..e538788f211 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/passkey/Base64Ext.kt @@ -0,0 +1,11 @@ +package org.wordpress.android.login.passkey + +private val BASE64_FLAG = android.util.Base64.NO_PADDING or android.util.Base64.NO_WRAP or android.util.Base64.URL_SAFE + +fun ByteArray.toBase64(): String { + return android.util.Base64.encodeToString(this, BASE64_FLAG) +} + +fun String.decodeBase64(): ByteArray { + return android.util.Base64.decode(this, BASE64_FLAG) +} \ No newline at end of file From b3bf027db5edee5d1289a516426616ad9d75f3ee Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 30 Oct 2023 20:42:15 -0300 Subject: [PATCH 759/888] Add FIDO library to WPLogiFlow --- libs/login/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 00c90506165..e269176f44d 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -62,6 +62,8 @@ dependencies { implementation "com.github.bumptech.glide:glide:$glideVersion" kapt "com.github.bumptech.glide:compiler:$glideVersion" + implementation 'com.google.android.gms:play-services-auth:20.7.0' + // Dagger implementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" From fc03fa6510f03c59292349ca511bbcaa9a4fbaea Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 31 Oct 2023 17:40:12 -0300 Subject: [PATCH 760/888] Remove FIDO implementation code --- libs/login/build.gradle | 2 -- .../org/wordpress/android/login/passkey/Base64Ext.kt | 11 ----------- .../android/login/passkey/PasskeyFIDOHandler.kt | 4 ---- .../wordpress/android/login/passkey/WebauthnModels.kt | 2 -- 4 files changed, 19 deletions(-) delete mode 100644 libs/login/src/main/java/org/wordpress/android/login/passkey/Base64Ext.kt delete mode 100644 libs/login/src/main/java/org/wordpress/android/login/passkey/PasskeyFIDOHandler.kt delete mode 100644 libs/login/src/main/java/org/wordpress/android/login/passkey/WebauthnModels.kt diff --git a/libs/login/build.gradle b/libs/login/build.gradle index e269176f44d..00c90506165 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -62,8 +62,6 @@ dependencies { implementation "com.github.bumptech.glide:glide:$glideVersion" kapt "com.github.bumptech.glide:compiler:$glideVersion" - implementation 'com.google.android.gms:play-services-auth:20.7.0' - // Dagger implementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" diff --git a/libs/login/src/main/java/org/wordpress/android/login/passkey/Base64Ext.kt b/libs/login/src/main/java/org/wordpress/android/login/passkey/Base64Ext.kt deleted file mode 100644 index e538788f211..00000000000 --- a/libs/login/src/main/java/org/wordpress/android/login/passkey/Base64Ext.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.wordpress.android.login.passkey - -private val BASE64_FLAG = android.util.Base64.NO_PADDING or android.util.Base64.NO_WRAP or android.util.Base64.URL_SAFE - -fun ByteArray.toBase64(): String { - return android.util.Base64.encodeToString(this, BASE64_FLAG) -} - -fun String.decodeBase64(): ByteArray { - return android.util.Base64.decode(this, BASE64_FLAG) -} \ No newline at end of file diff --git a/libs/login/src/main/java/org/wordpress/android/login/passkey/PasskeyFIDOHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/passkey/PasskeyFIDOHandler.kt deleted file mode 100644 index 3706538c0db..00000000000 --- a/libs/login/src/main/java/org/wordpress/android/login/passkey/PasskeyFIDOHandler.kt +++ /dev/null @@ -1,4 +0,0 @@ -package org.wordpress.android.login.passkey - -class PasskeyFIDOHandler { -} \ No newline at end of file diff --git a/libs/login/src/main/java/org/wordpress/android/login/passkey/WebauthnModels.kt b/libs/login/src/main/java/org/wordpress/android/login/passkey/WebauthnModels.kt deleted file mode 100644 index e37da2af0f6..00000000000 --- a/libs/login/src/main/java/org/wordpress/android/login/passkey/WebauthnModels.kt +++ /dev/null @@ -1,2 +0,0 @@ -package org.wordpress.android.login.passkey - From 30a3e339e98468d7e41e46268976b23a3946d5c2 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 31 Oct 2023 18:27:00 -0300 Subject: [PATCH 761/888] Update LoginListener with expected fields --- .../java/org/wordpress/android/login/Login2FaFragment.java | 2 +- .../wordpress/android/login/LoginEmailPasswordFragment.java | 2 +- .../main/java/org/wordpress/android/login/LoginListener.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index a8b6f002aaa..7e7a262634f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -580,6 +580,6 @@ public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { // TODO: Handle error return; } - mLoginListener.signSecurityKey(event.challengeInfo, event.mUserId, mEmailAddress); + mLoginListener.signSecurityKey(event.challengeInfo, event.mUserId); } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 88390a8c31c..17541247e75 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -346,7 +346,7 @@ public void onCredentialsOK(OnCredentialsOK event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyAuthStarted(SecurityKeyRequested event) { - mLoginListener.needsSecurityKey(event.userId, event.webauthnNonce); + mLoginListener.needsSecurityKey(mEmailAddress, mPassword, event.userId, event.webauthnNonce); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index fc77ae75546..1f99444a01a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -50,8 +50,8 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void needs2fa(String email, String password); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); - void needsSecurityKey(String userId, String webauthnNonce); - void signSecurityKey(String challengeRequestJson, String userId, String username); + void needsSecurityKey(String email, String password, String userId, String webauthnNonce); + void signSecurityKey(String challengeRequestJson, String userId); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From 7c740327a4a22d78462d472a31356ca23122f68b Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 31 Oct 2023 19:00:47 -0300 Subject: [PATCH 762/888] Add handling for Security Key check finished --- .../wordpress/android/login/Login2FaFragment.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 7e7a262634f..eed356cd857 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -36,6 +36,7 @@ import org.wordpress.android.fluxc.store.AccountStore.PushSocialAuthPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialSmsPayload; +import org.wordpress.android.fluxc.store.AccountStore.SecurityKeyCheckFinished; import org.wordpress.android.fluxc.store.AccountStore.StartSecurityKeyChallengePayload; import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.widgets.WPLoginInputRow; @@ -578,8 +579,20 @@ private void setTextForSms() { public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { if (event.isError()) { // TODO: Handle error + endProgress(); return; } mLoginListener.signSecurityKey(event.challengeInfo, event.mUserId); } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSecurityKeyCheckFinished(SecurityKeyCheckFinished event) { + if (event.isError()) { + handleAuthError(event.error.type, event.error.message); + endProgress(); + return; + } + doFinishLogin(); + } } From 0b5864ff55c6ba998ce79f11378b336532aa7ca7 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 31 Oct 2023 19:21:12 -0300 Subject: [PATCH 763/888] Add debug error messages to Login2FaFragment --- .../org/wordpress/android/login/Login2FaFragment.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index eed356cd857..0a6c9c1171a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -13,6 +13,7 @@ import android.widget.Button; import android.widget.EditText; import android.widget.TextView; +import android.widget.Toast; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; @@ -50,6 +51,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static android.app.ProgressDialog.show; import static android.content.Context.CLIPBOARD_SERVICE; import dagger.android.support.AndroidSupportInjection; @@ -579,6 +581,7 @@ private void setTextForSms() { public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { if (event.isError()) { // TODO: Handle error + Toast.makeText(requireContext(), "Login failed", Toast.LENGTH_SHORT).show(); endProgress(); return; } @@ -589,10 +592,12 @@ public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyCheckFinished(SecurityKeyCheckFinished event) { if (event.isError()) { - handleAuthError(event.error.type, event.error.message); - endProgress(); + Toast.makeText(requireContext(), "Login failed", Toast.LENGTH_SHORT).show(); + // handleAuthError(event.error.type, event.error.message); + // endProgress(); return; } - doFinishLogin(); + Toast.makeText(requireContext(), "Login succeeded", Toast.LENGTH_SHORT).show(); + // doFinishLogin(); } } From 76ef21268a2f55015657f83d84b163fa3eae5b77 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 31 Oct 2023 19:28:54 -0300 Subject: [PATCH 764/888] Fix checkstyle --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 0a6c9c1171a..77ea49196bb 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -51,7 +51,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static android.app.ProgressDialog.show; import static android.content.Context.CLIPBOARD_SERVICE; import dagger.android.support.AndroidSupportInjection; From c3264d9aa0ce6b2736d7f2766dd2031236c3745a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 31 Oct 2023 20:02:21 -0300 Subject: [PATCH 765/888] Restore error handling and login final step in Login2FaFragment --- .../java/org/wordpress/android/login/Login2FaFragment.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 77ea49196bb..9d9e39bdf2e 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -592,11 +592,11 @@ public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { public void onSecurityKeyCheckFinished(SecurityKeyCheckFinished event) { if (event.isError()) { Toast.makeText(requireContext(), "Login failed", Toast.LENGTH_SHORT).show(); - // handleAuthError(event.error.type, event.error.message); - // endProgress(); + handleAuthError(event.error.type, event.error.message); + endProgress(); return; } Toast.makeText(requireContext(), "Login succeeded", Toast.LENGTH_SHORT).show(); - // doFinishLogin(); + doFinishLogin(); } } From 23c39c11821c196764e244ae77183dff9af88f4a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 31 Oct 2023 20:02:46 -0300 Subject: [PATCH 766/888] Add login progress steps into security key start --- .../org/wordpress/android/login/LoginEmailPasswordFragment.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 17541247e75..e0ea857b762 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -346,7 +346,9 @@ public void onCredentialsOK(OnCredentialsOK event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyAuthStarted(SecurityKeyRequested event) { + onLoginFinished(false); mLoginListener.needsSecurityKey(mEmailAddress, mPassword, event.userId, event.webauthnNonce); + LoginWpcomService.clearLoginServiceState(); } From 55b2c4e47390d4a068c48957c832d00dd123b9f6 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 31 Oct 2023 20:05:40 -0300 Subject: [PATCH 767/888] Fix missing start progress --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 9d9e39bdf2e..de88d1e0779 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -584,6 +584,7 @@ public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { endProgress(); return; } + startProgress(); mLoginListener.signSecurityKey(event.challengeInfo, event.mUserId); } From 1093d110ab15798f34f6e81bcc82da295b53ef83 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 14:23:39 -0300 Subject: [PATCH 768/888] Set Security Key state to be considered an error --- .../org/wordpress/android/login/Login2FaFragment.java | 5 ++--- .../org/wordpress/android/login/LoginWpcomService.java | 9 ++------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index de88d1e0779..e2e2f8492be 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -354,7 +354,6 @@ private void doAuthWithSecurityKeyAction() { if (!NetworkUtils.checkConnection(getActivity())) { return; } - // TODO: Check if security key is available, if not, trigger PushSecurityKeyPayload StartSecurityKeyChallengePayload payload = new StartSecurityKeyChallengePayload( mUserId, mWebauthnNonce); mDispatcher.dispatch(AuthenticationActionBuilder @@ -584,17 +583,17 @@ public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { endProgress(); return; } - startProgress(); + startProgress(false); mLoginListener.signSecurityKey(event.challengeInfo, event.mUserId); } @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyCheckFinished(SecurityKeyCheckFinished event) { + endProgress(); if (event.isError()) { Toast.makeText(requireContext(), "Login failed", Toast.LENGTH_SHORT).show(); handleAuthError(event.error.type, event.error.message); - endProgress(); return; } Toast.makeText(requireContext(), "Login succeeded", Toast.LENGTH_SHORT).show(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 261ef47da7a..4bb1fc0c41d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -62,7 +62,6 @@ public enum LoginStep { FAILURE_2FA, FAILURE_SOCIAL_2FA, FAILURE_SECURITY_KEY, - FAILURE_SOCIAL_SECURITY_KEY, FAILURE_FETCHING_ACCOUNT, FAILURE_CANNOT_ADD_DUPLICATE_SITE, FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL, @@ -106,6 +105,7 @@ public boolean isError() { || mStep == LoginStep.FAILURE_EMAIL_WRONG_PASSWORD || mStep == LoginStep.FAILURE_2FA || mStep == LoginStep.FAILURE_SOCIAL_2FA + || mStep == LoginStep.FAILURE_SECURITY_KEY || mStep == LoginStep.FAILURE_FETCHING_ACCOUNT || mStep == LoginStep.FAILURE_CANNOT_ADD_DUPLICATE_SITE || mStep == LoginStep.FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL; @@ -321,12 +321,7 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) case NEEDS_SECURITY_KEY: // login credentials were correct anyway so, offer to save to SmartLock signalCredentialsOK(); - - if (mIsSocialLogin) { - setState(LoginStep.FAILURE_SOCIAL_SECURITY_KEY); - } else { - setState(LoginStep.FAILURE_SECURITY_KEY); - } + setState(LoginStep.FAILURE_SECURITY_KEY); break; case EMAIL_LOGIN_NOT_ALLOWED: setState(LoginStep.FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL); From 33adebe2d0a5125321538e82a917a6da261bb0cc Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 14:53:28 -0300 Subject: [PATCH 769/888] Fix LoginWpcomService.isError --- .../java/org/wordpress/android/login/LoginWpcomService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 4bb1fc0c41d..2bfe9f49535 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -105,7 +105,7 @@ public boolean isError() { || mStep == LoginStep.FAILURE_EMAIL_WRONG_PASSWORD || mStep == LoginStep.FAILURE_2FA || mStep == LoginStep.FAILURE_SOCIAL_2FA - || mStep == LoginStep.FAILURE_SECURITY_KEY + || mStep == LoginStep.SECURITY_KEY_NEEDED || mStep == LoginStep.FAILURE_FETCHING_ACCOUNT || mStep == LoginStep.FAILURE_CANNOT_ADD_DUPLICATE_SITE || mStep == LoginStep.FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL; From e969383580fa471fb3d66881e6329c24b140cd3a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 15:16:13 -0300 Subject: [PATCH 770/888] Update mOldSitesIDs value when authenticating through Security keys --- .../java/org/wordpress/android/login/Login2FaFragment.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index e2e2f8492be..dd0cbf11e73 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -354,6 +354,9 @@ private void doAuthWithSecurityKeyAction() { if (!NetworkUtils.checkConnection(getActivity())) { return; } + + mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); + StartSecurityKeyChallengePayload payload = new StartSecurityKeyChallengePayload( mUserId, mWebauthnNonce); mDispatcher.dispatch(AuthenticationActionBuilder From 8fec88a1cc38821c01456a3b4c09b21a30659e5e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 19:07:05 -0300 Subject: [PATCH 771/888] Update FluxC version --- .../android/login/Login2FaFragment.java | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index dd0cbf11e73..a27314b70a9 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -33,12 +33,12 @@ import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; import org.wordpress.android.fluxc.store.AccountStore.OnSocialChanged; -import org.wordpress.android.fluxc.store.AccountStore.OnWebauthnChallengeReceived; import org.wordpress.android.fluxc.store.AccountStore.PushSocialAuthPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialPayload; import org.wordpress.android.fluxc.store.AccountStore.PushSocialSmsPayload; -import org.wordpress.android.fluxc.store.AccountStore.SecurityKeyCheckFinished; -import org.wordpress.android.fluxc.store.AccountStore.StartSecurityKeyChallengePayload; +import org.wordpress.android.fluxc.store.AccountStore.StartWebauthnChallengePayload; +import org.wordpress.android.fluxc.store.AccountStore.WebauthnChallengeReceived; +import org.wordpress.android.fluxc.store.AccountStore.WebauthnPasskeyAuthenticated; import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; @@ -350,19 +350,6 @@ private void doAuthAction(@StringRes int messageId, String twoStepCode, boolean } } - private void doAuthWithSecurityKeyAction() { - if (!NetworkUtils.checkConnection(getActivity())) { - return; - } - - mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); - - StartSecurityKeyChallengePayload payload = new StartSecurityKeyChallengePayload( - mUserId, mWebauthnNonce); - mDispatcher.dispatch(AuthenticationActionBuilder - .newStartSecurityKeyChallengeAction(payload)); - } - private String getAuthCodeFromClipboard() { ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(CLIPBOARD_SERVICE); @@ -577,25 +564,36 @@ private void setTextForSms() { mSentSmsCode = true; } + private void doAuthWithSecurityKeyAction() { + if (!NetworkUtils.checkConnection(getActivity())) { + return; + } + + startProgress(false); + mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); + + StartWebauthnChallengePayload payload = new StartWebauthnChallengePayload( + mUserId, mWebauthnNonce); + mDispatcher.dispatch(AuthenticationActionBuilder + .newStartSecurityKeyChallengeAction(payload)); + } + @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onWebauthnChallengeReceived(OnWebauthnChallengeReceived event) { + public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { if (event.isError()) { - // TODO: Handle error - Toast.makeText(requireContext(), "Login failed", Toast.LENGTH_SHORT).show(); endProgress(); + handleAuthError(event.error.type, event.error.message); return; } - startProgress(false); mLoginListener.signSecurityKey(event.challengeInfo, event.mUserId); } @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onSecurityKeyCheckFinished(SecurityKeyCheckFinished event) { + public void onSecurityKeyCheckFinished(WebauthnPasskeyAuthenticated event) { endProgress(); if (event.isError()) { - Toast.makeText(requireContext(), "Login failed", Toast.LENGTH_SHORT).show(); handleAuthError(event.error.type, event.error.message); return; } From c78dae420d14d0a763bff24250021e4fbfc13454 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 19:13:42 -0300 Subject: [PATCH 772/888] Keep progress until login view is called --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index a27314b70a9..6492d05dc07 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -592,9 +592,9 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyCheckFinished(WebauthnPasskeyAuthenticated event) { - endProgress(); if (event.isError()) { handleAuthError(event.error.type, event.error.message); + endProgress(); return; } Toast.makeText(requireContext(), "Login succeeded", Toast.LENGTH_SHORT).show(); From 5bff10e245535e45a5419a15ea6d1a540077f29d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 19:19:09 -0300 Subject: [PATCH 773/888] Configure security key button to be hidden by default --- .../wordpress/android/login/Login2FaFragment.java | 13 +++++++------ .../android/login/LoginAnalyticsListener.kt | 1 - 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 6492d05dc07..7f7b79879c3 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -77,6 +77,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private static final String ARG_EMAIL_ADDRESS = "ARG_EMAIL_ADDRESS"; private static final String ARG_PASSWORD = "ARG_PASSWORD"; private static final String ARG_WEBAUTHN_NONCE = "WEBAUTHN_NONCE"; + private static final String ARG_DISPLAY_SECURITY_KEY_BUTTON = "ARG_DISPLAY_SECURITY_KEY_BUTTON"; private static final int LENGTH_NONCE_AUTHENTICATOR = 6; private static final int LENGTH_NONCE_BACKUP = 8; private static final int LENGTH_NONCE_SMS = 7; @@ -114,6 +115,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private boolean mIsSocialLogin; private boolean mIsSocialLoginConnect; private boolean mSentSmsCode; + private boolean mIsSecurityKeyEnabled; public static Login2FaFragment newInstance(String emailAddress, String password) { Login2FaFragment fragment = new Login2FaFragment(); @@ -132,6 +134,7 @@ public static Login2FaFragment newInstanceSecurityKey(String emailAddress, Strin args.putString(ARG_PASSWORD, password); args.putString(ARG_2FA_USER_ID, userId); args.putString(ARG_WEBAUTHN_NONCE, webauthnNonce); + args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, true); fragment.setArguments(args); return fragment; } @@ -207,10 +210,8 @@ public void onClick(View v) { }); mSecurityKeyButton = rootView.findViewById(R.id.login_security_key_button); - mSecurityKeyButton.setOnClickListener(view -> { - mAnalyticsListener.trackContinueWithSecurityKeyClicked(); - doAuthWithSecurityKeyAction(); - }); + mSecurityKeyButton.setVisibility(mIsSecurityKeyEnabled ? View.VISIBLE : View.GONE); + mSecurityKeyButton.setOnClickListener(view -> doAuthWithSecurityKeyAction()); } @Override @@ -260,6 +261,7 @@ public void onCreate(Bundle savedInstanceState) { mIsSocialLoginConnect = getArguments().getBoolean(ARG_2FA_IS_SOCIAL_CONNECT); mService = getArguments().getString(ARG_2FA_SOCIAL_SERVICE); mWebauthnNonce = getArguments().getString(ARG_WEBAUTHN_NONCE); + mIsSecurityKeyEnabled = getArguments().getBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, false); if (savedInstanceState != null) { // Overwrite argument nonce values with saved state values on device rotation. @@ -593,11 +595,10 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyCheckFinished(WebauthnPasskeyAuthenticated event) { if (event.isError()) { - handleAuthError(event.error.type, event.error.message); endProgress(); + handleAuthError(event.error.type, event.error.message); return; } - Toast.makeText(requireContext(), "Login succeeded", Toast.LENGTH_SHORT).show(); doFinishLogin(); } } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt index ded0e4367e7..a5dc2d5eb9d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt @@ -55,7 +55,6 @@ interface LoginAnalyticsListener { fun trackConnectedSiteInfoSucceeded(properties: Map) fun trackFailure(message: String?) fun trackSendCodeWithTextClicked() - fun trackContinueWithSecurityKeyClicked() fun trackSubmit2faCodeClicked() fun trackSubmitClicked() fun trackRequestMagicLinkClick() From d9a1a1b04d8227c9a05689da1d527bf2008d541b Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 19:26:25 -0300 Subject: [PATCH 774/888] Fix checkstyle issues --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 7f7b79879c3..0039f4c1278 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -13,7 +13,6 @@ import android.widget.Button; import android.widget.EditText; import android.widget.TextView; -import android.widget.Toast; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; From b16acb56820d81c304bde420f048a37fb830ee12 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 19:29:10 -0300 Subject: [PATCH 775/888] Remove unnecessary WpcomService error --- .../org/wordpress/android/login/LoginWpcomService.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 2bfe9f49535..ea9e60db0cd 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -56,12 +56,11 @@ public enum LoginStep { FETCHING_ACCOUNT(50), FETCHING_SETTINGS(75), FETCHING_SITES(100), - SECURITY_KEY_NEEDED, SUCCESS, FAILURE_EMAIL_WRONG_PASSWORD, FAILURE_2FA, FAILURE_SOCIAL_2FA, - FAILURE_SECURITY_KEY, + SECURITY_KEY_NEEDED, FAILURE_FETCHING_ACCOUNT, FAILURE_CANNOT_ADD_DUPLICATE_SITE, FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL, @@ -318,11 +317,6 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) setState(LoginStep.FAILURE_2FA); } break; - case NEEDS_SECURITY_KEY: - // login credentials were correct anyway so, offer to save to SmartLock - signalCredentialsOK(); - setState(LoginStep.FAILURE_SECURITY_KEY); - break; case EMAIL_LOGIN_NOT_ALLOWED: setState(LoginStep.FAILURE_USE_WPCOM_USERNAME_INSTEAD_OF_EMAIL); break; From a3bf997e98425288526977c33bfee923281b2fd7 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 21:02:33 -0300 Subject: [PATCH 776/888] Refactor LoginWpcomService method positioning --- .../android/login/LoginWpcomService.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index ea9e60db0cd..01d87aa8e04 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -340,6 +340,14 @@ private void signalCredentialsOK() { EventBus.getDefault().post(new OnCredentialsOK()); } + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSecurityKeyAuthStarted(OnSecurityKeyAuthStarted event) { + signalCredentialsOK(); + setState(LoginStep.SECURITY_KEY_NEEDED); + EventBus.getDefault().post(new SecurityKeyRequested(event.userId, event.webauthnNonce)); + } + // OnChanged events @SuppressWarnings("unused") @@ -431,12 +439,4 @@ public void onSiteChanged(OnSiteChanged event) { setState(LoginStep.SUCCESS); } - - @SuppressWarnings("unused") - @Subscribe(threadMode = ThreadMode.MAIN) - public void onSecurityKeyAuthStarted(OnSecurityKeyAuthStarted event) { - signalCredentialsOK(); - setState(LoginStep.SECURITY_KEY_NEEDED); - EventBus.getDefault().post(new SecurityKeyRequested(event.userId, event.webauthnNonce)); - } } From 8e732d0a1da51d566fe53930e98a07d4a32a617f Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 1 Nov 2023 21:02:51 -0300 Subject: [PATCH 777/888] Update LoginListener to follow new FluxC models --- .../java/org/wordpress/android/login/Login2FaFragment.java | 2 +- .../main/java/org/wordpress/android/login/LoginListener.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 0039f4c1278..bc449e44263 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -587,7 +587,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { handleAuthError(event.error.type, event.error.message); return; } - mLoginListener.signSecurityKey(event.challengeInfo, event.mUserId); + mLoginListener.signSecurityKey(event.mChallengeInfo, event.mUserId); } @SuppressWarnings("unused") diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 1f99444a01a..14fa6af821b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -6,6 +6,7 @@ import androidx.annotation.Nullable; import org.wordpress.android.fluxc.network.MemorizingTrustManager; +import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnChallengeInfo; import org.wordpress.android.fluxc.store.SiteStore; import org.wordpress.android.fluxc.store.SiteStore.ConnectSiteInfoPayload; @@ -51,7 +52,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); void needsSecurityKey(String email, String password, String userId, String webauthnNonce); - void signSecurityKey(String challengeRequestJson, String userId); + void signSecurityKey(WebauthnChallengeInfo challengeInfo, String userId); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From fe05d520cb0da094a3a8664b8246c420d590ac41 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 2 Nov 2023 00:44:48 -0300 Subject: [PATCH 778/888] Add FIDO lib to Login lib --- libs/login/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 00c90506165..97edb02ce5d 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -62,6 +62,8 @@ dependencies { implementation "com.github.bumptech.glide:glide:$glideVersion" kapt "com.github.bumptech.glide:compiler:$glideVersion" + implementation "com.google.android.gms:play-services-fido:$fidoVersion" + // Dagger implementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" From b478eb3d75401b7e18c92a9a8fccfceca15d075f Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 2 Nov 2023 00:45:24 -0300 Subject: [PATCH 779/888] Define PasskeyCredentialsHandler.kt --- .../webauthn/PasskeyCredentialsHandler.kt | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt new file mode 100644 index 00000000000..5d64d166164 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt @@ -0,0 +1,68 @@ +package org.wordpress.android.login.webauthn + +import android.content.Context +import android.util.Base64 +import androidx.activity.result.IntentSenderRequest +import com.google.android.gms.fido.Fido +import com.google.android.gms.fido.common.Transport +import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential +import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialDescriptor +import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions +import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialType.PUBLIC_KEY +import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnChallengeInfo +import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnCredentialResponse +import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload + +class PasskeyCredentialsHandler( + private val userId: String, + private val challengeInfo: WebauthnChallengeInfo +) { + fun createIntentSender( + context: Context, + onPasskeyRequestReady: (IntentSenderRequest) -> Unit + ) { + val options = PublicKeyCredentialRequestOptions.Builder() + .setRpId(challengeInfo.rpId) + .setAllowList(challengeInfo.allowCredentials.map(::parseToCredentialDescriptor)) + .setChallenge(challengeInfo.challenge.decodeBase64()) + .setTimeoutSeconds(challengeInfo.timeout.toDouble()) + .build() + + Fido.getFido2ApiClient(context) + .getSignPendingIntent(options) + .addOnSuccessListener { + val intentSender = IntentSenderRequest + .Builder(it.intentSender) + .build() + + onPasskeyRequestReady(intentSender) + } + } + + fun onCredentialsAvailable(keyCredential: PublicKeyCredential): FinishWebauthnChallengePayload { + return FinishWebauthnChallengePayload().apply { + this.mUserId = userId + this.mTwoStepNonce = challengeInfo.twoStepNonce + this.mClientData = keyCredential.toJson() + } + } + + private fun parseToCredentialDescriptor(credential: WebauthnCredentialResponse) = + PublicKeyCredentialDescriptor( + PUBLIC_KEY.toString(), + credential.id.decodeBase64(), + allTransports + ) + + private val allTransports = listOf( + Transport.USB, + Transport.NFC, + Transport.BLUETOOTH_LOW_ENERGY, + Transport.HYBRID, + Transport.INTERNAL + ) + + private fun String.decodeBase64(): ByteArray { + return Base64.decode(this, Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE) + } +} From 89ec75925635c6ded575c43b2aec6392d86e5c88 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 2 Nov 2023 00:46:19 -0300 Subject: [PATCH 780/888] Add passkey handling capabilities to Login2FaFragment --- .../android/login/Login2FaFragment.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index bc449e44263..5eda689ae7d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -2,6 +2,7 @@ import android.content.ClipboardManager; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; @@ -14,6 +15,9 @@ import android.widget.EditText; import android.widget.TextView; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.IntentSenderRequest; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -22,6 +26,8 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; +import com.google.android.gms.fido.Fido; +import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.greenrobot.eventbus.Subscribe; @@ -30,6 +36,7 @@ import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder; import org.wordpress.android.fluxc.store.AccountStore.AuthenticatePayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; +import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; import org.wordpress.android.fluxc.store.AccountStore.OnSocialChanged; import org.wordpress.android.fluxc.store.AccountStore.PushSocialAuthPayload; @@ -39,6 +46,7 @@ import org.wordpress.android.fluxc.store.AccountStore.WebauthnChallengeReceived; import org.wordpress.android.fluxc.store.AccountStore.WebauthnPasskeyAuthenticated; import org.wordpress.android.login.util.SiteUtils; +import org.wordpress.android.login.webauthn.PasskeyCredentialsHandler; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; import org.wordpress.android.util.AppLog; @@ -50,6 +58,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static android.app.Activity.RESULT_OK; import static android.content.Context.CLIPBOARD_SERVICE; import dagger.android.support.AndroidSupportInjection; @@ -115,6 +124,8 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private boolean mIsSocialLoginConnect; private boolean mSentSmsCode; private boolean mIsSecurityKeyEnabled; + @Nullable private PasskeyCredentialsHandler mPasskeyCredentialsHandler = null; + @Nullable private ActivityResultLauncher mResultLauncher = null; public static Login2FaFragment newInstance(String emailAddress, String password) { Login2FaFragment fragment = new Login2FaFragment(); @@ -272,6 +283,14 @@ public void onCreate(Bundle savedInstanceState) { mPhoneNumber = savedInstanceState.getString(KEY_SMS_NUMBER); mSentSmsCode = savedInstanceState.getBoolean(KEY_SMS_SENT); } + + mResultLauncher = + registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(), + result -> { + if (result.getResultCode() == RESULT_OK && result.getData() != null) { + onCredentialsResultAvailable(result.getData()); + } + }); } @Override @@ -587,7 +606,31 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { handleAuthError(event.error.type, event.error.message); return; } - mLoginListener.signSecurityKey(event.mChallengeInfo, event.mUserId); + mPasskeyCredentialsHandler = new PasskeyCredentialsHandler( + event.mUserId, + event.mChallengeInfo + ); + mPasskeyCredentialsHandler.createIntentSender( + requireContext(), + intent -> { + assert mResultLauncher != null; + mResultLauncher.launch(intent); + return null; + }); + } + + private void onCredentialsResultAvailable(@NonNull Intent resultData) { + if (resultData.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)) { + byte[] credentialBytes = resultData.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA); + assert credentialBytes != null; + PublicKeyCredential credentials = + PublicKeyCredential.deserializeFromBytes(credentialBytes); + assert mPasskeyCredentialsHandler != null; + FinishWebauthnChallengePayload payload = + mPasskeyCredentialsHandler.onCredentialsAvailable(credentials); + mDispatcher.dispatch( + AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(payload)); + } } @SuppressWarnings("unused") From c4b32f623cb22cc38cb2804e85ba4cbacbd378ef Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 2 Nov 2023 00:47:34 -0300 Subject: [PATCH 781/888] Use same nonce for webauthn and common 2FA --- .../java/org/wordpress/android/login/Login2FaFragment.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 5eda689ae7d..46b77c30ec9 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -111,7 +111,6 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private String mIdToken; private String mNonce; private String mNonceAuthenticator; - private String mWebauthnNonce; private String mNonceBackup; private String mNonceSms; private String mPassword; @@ -270,7 +269,6 @@ public void onCreate(Bundle savedInstanceState) { mIsSocialLogin = getArguments().getBoolean(ARG_2FA_IS_SOCIAL); mIsSocialLoginConnect = getArguments().getBoolean(ARG_2FA_IS_SOCIAL_CONNECT); mService = getArguments().getString(ARG_2FA_SOCIAL_SERVICE); - mWebauthnNonce = getArguments().getString(ARG_WEBAUTHN_NONCE); mIsSecurityKeyEnabled = getArguments().getBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, false); if (savedInstanceState != null) { @@ -593,7 +591,7 @@ private void doAuthWithSecurityKeyAction() { mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); StartWebauthnChallengePayload payload = new StartWebauthnChallengePayload( - mUserId, mWebauthnNonce); + mUserId, mNonce); mDispatcher.dispatch(AuthenticationActionBuilder .newStartSecurityKeyChallengeAction(payload)); } From 1c1ae820bb3625093965f864fba16008ea62d5d0 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 2 Nov 2023 01:09:16 -0300 Subject: [PATCH 782/888] Revert webauthn nonce back --- .../java/org/wordpress/android/login/Login2FaFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 46b77c30ec9..5eda689ae7d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -111,6 +111,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private String mIdToken; private String mNonce; private String mNonceAuthenticator; + private String mWebauthnNonce; private String mNonceBackup; private String mNonceSms; private String mPassword; @@ -269,6 +270,7 @@ public void onCreate(Bundle savedInstanceState) { mIsSocialLogin = getArguments().getBoolean(ARG_2FA_IS_SOCIAL); mIsSocialLoginConnect = getArguments().getBoolean(ARG_2FA_IS_SOCIAL_CONNECT); mService = getArguments().getString(ARG_2FA_SOCIAL_SERVICE); + mWebauthnNonce = getArguments().getString(ARG_WEBAUTHN_NONCE); mIsSecurityKeyEnabled = getArguments().getBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, false); if (savedInstanceState != null) { @@ -591,7 +593,7 @@ private void doAuthWithSecurityKeyAction() { mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); StartWebauthnChallengePayload payload = new StartWebauthnChallengePayload( - mUserId, mNonce); + mUserId, mWebauthnNonce); mDispatcher.dispatch(AuthenticationActionBuilder .newStartSecurityKeyChallengeAction(payload)); } From ad4b32da2bac21ae67ee8ad36dec1784c1687f9b Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 2 Nov 2023 09:29:03 -0300 Subject: [PATCH 783/888] Set webauthn nounce as the authenticator nounce too --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 5eda689ae7d..bab4e69abad 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -144,6 +144,7 @@ public static Login2FaFragment newInstanceSecurityKey(String emailAddress, Strin args.putString(ARG_PASSWORD, password); args.putString(ARG_2FA_USER_ID, userId); args.putString(ARG_WEBAUTHN_NONCE, webauthnNonce); + args.putString(ARG_2FA_NONCE_AUTHENTICATOR, webauthnNonce); args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, true); fragment.setArguments(args); return fragment; From e6cd1d3da3622370c59e4ee2d269365e321b5a0d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 2 Nov 2023 09:29:48 -0300 Subject: [PATCH 784/888] Update webauthn calls from LoginListener --- .../wordpress/android/login/LoginEmailPasswordFragment.java | 2 +- .../main/java/org/wordpress/android/login/LoginListener.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index e0ea857b762..0da8a6ca5e0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -347,7 +347,7 @@ public void onCredentialsOK(OnCredentialsOK event) { @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyAuthStarted(SecurityKeyRequested event) { onLoginFinished(false); - mLoginListener.needsSecurityKey(mEmailAddress, mPassword, event.userId, event.webauthnNonce); + mLoginListener.needs2faSecurityKey(mEmailAddress, mPassword, event.userId, event.webauthnNonce); LoginWpcomService.clearLoginServiceState(); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 14fa6af821b..b79cd3f907b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -6,7 +6,6 @@ import androidx.annotation.Nullable; import org.wordpress.android.fluxc.network.MemorizingTrustManager; -import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnChallengeInfo; import org.wordpress.android.fluxc.store.SiteStore; import org.wordpress.android.fluxc.store.SiteStore.ConnectSiteInfoPayload; @@ -51,8 +50,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void needs2fa(String email, String password); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); - void needsSecurityKey(String email, String password, String userId, String webauthnNonce); - void signSecurityKey(WebauthnChallengeInfo challengeInfo, String userId); + void needs2faSecurityKey(String email, String password, String userId, String webauthnNonce); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From eca9be0c71d01c246f16188b75651d3de1d36026 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 2 Nov 2023 09:57:49 -0300 Subject: [PATCH 785/888] Fix incorrect password field usage in LoginEmailPasswordFragment --- .../org/wordpress/android/login/LoginEmailPasswordFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 0da8a6ca5e0..2a5c6682897 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -347,7 +347,7 @@ public void onCredentialsOK(OnCredentialsOK event) { @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyAuthStarted(SecurityKeyRequested event) { onLoginFinished(false); - mLoginListener.needs2faSecurityKey(mEmailAddress, mPassword, event.userId, event.webauthnNonce); + mLoginListener.needs2faSecurityKey(mEmailAddress, mRequestedPassword, event.userId, event.webauthnNonce); LoginWpcomService.clearLoginServiceState(); } From 13a06134d8d8eb82f4e5495df16acb1d50dbe116 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 6 Nov 2023 13:57:14 -0300 Subject: [PATCH 786/888] Use a interface listener for better Java interop --- .../org/wordpress/android/login/Login2FaFragment.java | 1 - .../android/login/webauthn/PasskeyCredentialsHandler.kt | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index bab4e69abad..18c169fd40d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -616,7 +616,6 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { intent -> { assert mResultLauncher != null; mResultLauncher.launch(intent); - return null; }); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt index 5d64d166164..8afb9e5d043 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt @@ -13,13 +13,17 @@ import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnChal import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnCredentialResponse import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload +interface OnPasskeyRequestReadyListener { + fun onPasskeyRequestReady(intentSenderRequest: IntentSenderRequest) +} + class PasskeyCredentialsHandler( private val userId: String, private val challengeInfo: WebauthnChallengeInfo ) { fun createIntentSender( context: Context, - onPasskeyRequestReady: (IntentSenderRequest) -> Unit + listener: OnPasskeyRequestReadyListener ) { val options = PublicKeyCredentialRequestOptions.Builder() .setRpId(challengeInfo.rpId) @@ -35,7 +39,7 @@ class PasskeyCredentialsHandler( .Builder(it.intentSender) .build() - onPasskeyRequestReady(intentSender) + listener.onPasskeyRequestReady(intentSender) } } From 831f0aa96f7bbe9857ce7177e22e948b92f2991d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 6 Nov 2023 14:03:40 -0300 Subject: [PATCH 787/888] Add transport parsing function --- .../login/webauthn/PasskeyCredentialsHandler.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt index 8afb9e5d043..f25b27c7955 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt @@ -69,4 +69,17 @@ class PasskeyCredentialsHandler( private fun String.decodeBase64(): ByteArray { return Base64.decode(this, Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE) } + + private fun List.asTransports(): List { + return mapNotNull { + when (it) { + "usb" -> Transport.USB + "nfc" -> Transport.NFC + "ble" -> Transport.BLUETOOTH_LOW_ENERGY + "internal" -> Transport.INTERNAL + "hybrid" -> Transport.HYBRID + else -> null + } + }.takeIf { it.isNotEmpty() } ?: allTransports + } } From 1a31c63a8898c9f0eff35b53b54f1b1397ef1709 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 6 Nov 2023 14:04:33 -0300 Subject: [PATCH 788/888] Adjust transports parsing --- .../android/login/webauthn/PasskeyCredentialsHandler.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt index f25b27c7955..66a2d28bab4 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt @@ -55,7 +55,7 @@ class PasskeyCredentialsHandler( PublicKeyCredentialDescriptor( PUBLIC_KEY.toString(), credential.id.decodeBase64(), - allTransports + credential.transports.asParsedTransports() ) private val allTransports = listOf( @@ -70,7 +70,7 @@ class PasskeyCredentialsHandler( return Base64.decode(this, Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE) } - private fun List.asTransports(): List { + private fun List.asParsedTransports(): List { return mapNotNull { when (it) { "usb" -> Transport.USB From 9d6c3bc21f3d1bb1517c925e0df2a258309aba85 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 6 Nov 2023 14:08:31 -0300 Subject: [PATCH 789/888] Add Transports fallback if none is available or known --- .../login/webauthn/PasskeyCredentialsHandler.kt | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt index 66a2d28bab4..388d7f0e051 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt @@ -58,14 +58,6 @@ class PasskeyCredentialsHandler( credential.transports.asParsedTransports() ) - private val allTransports = listOf( - Transport.USB, - Transport.NFC, - Transport.BLUETOOTH_LOW_ENERGY, - Transport.HYBRID, - Transport.INTERNAL - ) - private fun String.decodeBase64(): ByteArray { return Base64.decode(this, Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE) } @@ -80,6 +72,12 @@ class PasskeyCredentialsHandler( "hybrid" -> Transport.HYBRID else -> null } - }.takeIf { it.isNotEmpty() } ?: allTransports + }.takeIf { it.isNotEmpty() } ?: listOf( + Transport.USB, + Transport.NFC, + Transport.BLUETOOTH_LOW_ENERGY, + Transport.HYBRID, + Transport.INTERNAL + ) } } From c6885190eb8545ff72d9574aa8429c5257c03c67 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 6 Nov 2023 20:47:47 -0300 Subject: [PATCH 790/888] Introduce Social Security key auth event to LoginListener --- .../src/main/java/org/wordpress/android/login/LoginListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index b79cd3f907b..e2b3ae8dc6c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -51,6 +51,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); void needs2faSecurityKey(String email, String password, String userId, String webauthnNonce); + void needs2faSocialSecurityKey(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms, String webauthnNonce); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From 039527985933bc9ac6ee68217ca5df2e0735377b Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 6 Nov 2023 20:48:00 -0300 Subject: [PATCH 791/888] Add Login2FaFragment newInstance call for Social Security Key scenario --- .../android/login/Login2FaFragment.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 18c169fd40d..5d2dafa698b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -150,6 +150,23 @@ public static Login2FaFragment newInstanceSecurityKey(String emailAddress, Strin return fragment; } + public static Login2FaFragment newInstanceSocialSecurityKey(String emailAddress, String userId, + String nonceAuthenticator, + String nonceBackup, String nonceSms, + String webauthnNonce) { + Login2FaFragment fragment = new Login2FaFragment(); + Bundle args = new Bundle(); + args.putString(ARG_EMAIL_ADDRESS, emailAddress); + args.putString(ARG_2FA_USER_ID, userId); + args.putString(ARG_2FA_NONCE_AUTHENTICATOR, nonceAuthenticator); + args.putString(ARG_2FA_NONCE_BACKUP, nonceBackup); + args.putString(ARG_2FA_NONCE_SMS, nonceSms); + args.putString(ARG_WEBAUTHN_NONCE, webauthnNonce); + args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, true); + fragment.setArguments(args); + return fragment; + } + public static Login2FaFragment newInstanceSocial(String emailAddress, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms) { From a36ac6ab30ae23f00f9b045d71120b58048468be Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 7 Nov 2023 19:18:36 -0300 Subject: [PATCH 792/888] Update LoginListener with webauthn nonce parameter --- .../java/org/wordpress/android/login/LoginGoogleFragment.java | 2 +- .../main/java/org/wordpress/android/login/LoginListener.java | 2 +- .../java/org/wordpress/android/login/SignupGoogleFragment.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index c4823512b5b..f828d76c8c0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -239,7 +239,7 @@ public void onSocialChanged(OnSocialChanged event) { } else if (event.requiresTwoStepAuth || Login2FaFragment.TWO_FACTOR_TYPE_SMS.equals(event.notificationSent)) { AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - needs 2fa"); mLoginListener.needs2faSocial(mGoogleEmail, event.userId, event.nonceAuthenticator, event.nonceBackup, - event.nonceSms); + event.nonceSms, event.nonceWebauthn); } else { AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - success"); mGoogleListener.onGoogleLoginFinished(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index e2b3ae8dc6c..36f89d3a0b2 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -48,7 +48,7 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void forgotPassword(String url); void useMagicLinkInstead(String email, boolean verifyEmail); void needs2fa(String email, String password); - void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); + void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms, String nonceWebauthn); void needs2faSocialConnect(String email, String password, String idToken, String service); void needs2faSecurityKey(String email, String password, String userId, String webauthnNonce); void needs2faSocialSecurityKey(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms, String webauthnNonce); diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java index 7754778f71c..d6dca8507f7 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java @@ -269,7 +269,7 @@ public void onSocialChanged(OnSocialChanged event) { AppLog.d(T.MAIN, "GOOGLE SIGNUP: onSocialChanged - 2fa required"); mAnalyticsListener.trackSignupSocialToLogin(); mLoginListener.needs2faSocial(mGoogleEmail, event.userId, event.nonceAuthenticator, event.nonceBackup, - event.nonceSms); + event.nonceSms, event.nonceWebauthn); finishFlow(); } else { AppLog.d(T.MAIN, "GOOGLE SIGNUP: onSocialChanged - google login success"); From 925e0d27366a7fe9e459d7342bbf21a56b394316 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 7 Nov 2023 19:18:52 -0300 Subject: [PATCH 793/888] Update Login2FaFragment.newInstanceSocial with webauthn parameter --- .../android/login/Login2FaFragment.java | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 5d2dafa698b..ddd2603c299 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -150,26 +150,9 @@ public static Login2FaFragment newInstanceSecurityKey(String emailAddress, Strin return fragment; } - public static Login2FaFragment newInstanceSocialSecurityKey(String emailAddress, String userId, - String nonceAuthenticator, - String nonceBackup, String nonceSms, - String webauthnNonce) { - Login2FaFragment fragment = new Login2FaFragment(); - Bundle args = new Bundle(); - args.putString(ARG_EMAIL_ADDRESS, emailAddress); - args.putString(ARG_2FA_USER_ID, userId); - args.putString(ARG_2FA_NONCE_AUTHENTICATOR, nonceAuthenticator); - args.putString(ARG_2FA_NONCE_BACKUP, nonceBackup); - args.putString(ARG_2FA_NONCE_SMS, nonceSms); - args.putString(ARG_WEBAUTHN_NONCE, webauthnNonce); - args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, true); - fragment.setArguments(args); - return fragment; - } - public static Login2FaFragment newInstanceSocial(String emailAddress, String userId, String nonceAuthenticator, String nonceBackup, - String nonceSms) { + String nonceSms, String nonceWebauthn) { Login2FaFragment fragment = new Login2FaFragment(); Bundle args = new Bundle(); args.putString(ARG_EMAIL_ADDRESS, emailAddress); @@ -177,9 +160,11 @@ public static Login2FaFragment newInstanceSocial(String emailAddress, String use args.putString(ARG_2FA_NONCE_AUTHENTICATOR, nonceAuthenticator); args.putString(ARG_2FA_NONCE_BACKUP, nonceBackup); args.putString(ARG_2FA_NONCE_SMS, nonceSms); + args.putString(ARG_WEBAUTHN_NONCE, nonceWebauthn); args.putBoolean(ARG_2FA_IS_SOCIAL, true); // Social account connected, connect call not needed. args.putBoolean(ARG_2FA_IS_SOCIAL_CONNECT, false); + args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, nonceWebauthn != null && !nonceWebauthn.isEmpty()); fragment.setArguments(args); return fragment; } From 8bf1127389d10c6bf352d1e001f91cdba8eb096f Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 7 Nov 2023 19:27:00 -0300 Subject: [PATCH 794/888] Fix checkstyle --- .../java/org/wordpress/android/login/LoginListener.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 36f89d3a0b2..9132b5ebce1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -48,10 +48,12 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void forgotPassword(String url); void useMagicLinkInstead(String email, boolean verifyEmail); void needs2fa(String email, String password); - void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms, String nonceWebauthn); + void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, + String nonceSms, String nonceWebauthn); void needs2faSocialConnect(String email, String password, String idToken, String service); void needs2faSecurityKey(String email, String password, String userId, String webauthnNonce); - void needs2faSocialSecurityKey(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms, String webauthnNonce); + void needs2faSocialSecurityKey(String email, String userId, String nonceAuthenticator, + String nonceBackup, String nonceSms, String webauthnNonce); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From 5c3f0fdd7d5f116438a4da17162e26b6359c1462 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 7 Nov 2023 19:27:10 -0300 Subject: [PATCH 795/888] Remove unused function --- .../main/java/org/wordpress/android/login/LoginListener.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 9132b5ebce1..498438f30fe 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -52,8 +52,6 @@ void needs2faSocial(String email, String userId, String nonceAuthenticator, Stri String nonceSms, String nonceWebauthn); void needs2faSocialConnect(String email, String password, String idToken, String service); void needs2faSecurityKey(String email, String password, String userId, String webauthnNonce); - void needs2faSocialSecurityKey(String email, String userId, String nonceAuthenticator, - String nonceBackup, String nonceSms, String webauthnNonce); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); From 8d725d8d47c1ea16b602946da2e73f30b1f77a15 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 8 Nov 2023 13:55:08 -0300 Subject: [PATCH 796/888] Adjust security key loading to allow dismissal --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 18c169fd40d..93a2903f70d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -590,7 +590,7 @@ private void doAuthWithSecurityKeyAction() { return; } - startProgress(false); + startProgress(); mOldSitesIDs = SiteUtils.getCurrentSiteIds(mSiteStore, false); StartWebauthnChallengePayload payload = new StartWebauthnChallengePayload( From ca550b76a115347f47724eb02de8c586f671a460 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 8 Nov 2023 16:57:58 -0300 Subject: [PATCH 797/888] Handle Security key fetching error --- .../java/org/wordpress/android/login/Login2FaFragment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 93a2903f70d..fa2a9eaf57b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -290,6 +290,10 @@ public void onCreate(Bundle savedInstanceState) { result -> { if (result.getResultCode() == RESULT_OK && result.getData() != null) { onCredentialsResultAvailable(result.getData()); + } else { + String errorMessage = getString(R.string.notification_security_key_needed); + endProgress(); + handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, errorMessage); } }); } From 6508b9a0aae8159f319cee40c931a61b189dac85 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 8 Nov 2023 17:01:31 -0300 Subject: [PATCH 798/888] Update LoginAnalyticsListener with Security key track scenarios --- .../org/wordpress/android/login/LoginAnalyticsListener.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt index a5dc2d5eb9d..d33c360d854 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt @@ -72,6 +72,10 @@ interface LoginAnalyticsListener { fun magicLinkRequestScreenResumed() fun magicLinkSentScreenResumed() fun usernamePasswordScreenResumed() + fun trackLoginSecurityKeyNeeded() + fun trackLoginSecurityKeySuccess() + fun trackLoginSecurityKeyFailure() + fun trackUseSecurityKeyClicked() enum class CreatedAccountSource { EMAIL, From ef0e281c57c3d49a1d057f35ab36569148e785e0 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 8 Nov 2023 17:04:22 -0300 Subject: [PATCH 799/888] Update Login2FaFragment with Security Key tracks event calls --- .../java/org/wordpress/android/login/Login2FaFragment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index fa2a9eaf57b..09b1f3bf633 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -457,6 +457,8 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) break; case INVALID_REQUEST: // TODO: FluxC: could be specific? + case WEBAUTHN_FAILED: + mAnalyticsListener.trackLoginSecurityKeyFailure(); default: AppLog.e(T.NUX, "Server response: " + errorMessage); mAnalyticsListener.trackFailure(errorMessage); @@ -590,6 +592,7 @@ private void setTextForSms() { } private void doAuthWithSecurityKeyAction() { + mAnalyticsListener.trackUseSecurityKeyClicked(); if (!NetworkUtils.checkConnection(getActivity())) { return; } @@ -645,6 +648,7 @@ public void onSecurityKeyCheckFinished(WebauthnPasskeyAuthenticated event) { handleAuthError(event.error.type, event.error.message); return; } + mAnalyticsListener.trackLoginSecurityKeySuccess(); doFinishLogin(); } } From 851ff5c485cbfc1ae5139a0b95c2f9359127ba04 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 8 Nov 2023 17:09:01 -0300 Subject: [PATCH 800/888] Improve error handling message for Security key usage --- .../org/wordpress/android/login/Login2FaFragment.java | 8 +++++--- libs/login/src/main/res/values/strings.xml | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 09b1f3bf633..6fd50720197 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -291,7 +291,7 @@ public void onCreate(Bundle savedInstanceState) { if (result.getResultCode() == RESULT_OK && result.getData() != null) { onCredentialsResultAvailable(result.getData()); } else { - String errorMessage = getString(R.string.notification_security_key_needed); + String errorMessage = getString(R.string.login_error_security_key); endProgress(); handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, errorMessage); } @@ -459,6 +459,8 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) // TODO: FluxC: could be specific? case WEBAUTHN_FAILED: mAnalyticsListener.trackLoginSecurityKeyFailure(); + ToastUtils.showToast(getActivity(), + errorMessage == null ? getString(R.string.error_generic) : errorMessage); default: AppLog.e(T.NUX, "Server response: " + errorMessage); mAnalyticsListener.trackFailure(errorMessage); @@ -611,7 +613,7 @@ private void doAuthWithSecurityKeyAction() { public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { if (event.isError()) { endProgress(); - handleAuthError(event.error.type, event.error.message); + handleAuthError(event.error.type, getString(R.string.login_error_security_key)); return; } mPasskeyCredentialsHandler = new PasskeyCredentialsHandler( @@ -645,7 +647,7 @@ private void onCredentialsResultAvailable(@NonNull Intent resultData) { public void onSecurityKeyCheckFinished(WebauthnPasskeyAuthenticated event) { if (event.isError()) { endProgress(); - handleAuthError(event.error.type, event.error.message); + handleAuthError(event.error.type, getString(R.string.login_error_security_key)); return; } mAnalyticsListener.trackLoginSecurityKeySuccess(); diff --git a/libs/login/src/main/res/values/strings.xml b/libs/login/src/main/res/values/strings.xml index 17be988f1b2..c87ed615a4e 100644 --- a/libs/login/src/main/res/values/strings.xml +++ b/libs/login/src/main/res/values/strings.xml @@ -70,6 +70,7 @@ We\'ve made too many attempts to send an SMS verification code — take a break, and request a new one in a minute. Google login could not be started. \nMaybe try a different account? + There was some trouble with the Security key login Sign Up There was some trouble sending the email. You can retry now or close and try again later. Close From 76c6fd9e4d879f1868892a96468b6f0a0d91361c Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 8 Nov 2023 17:09:34 -0300 Subject: [PATCH 801/888] Fix checkstyle issues --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 6fd50720197..9a928940d18 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -461,6 +461,7 @@ private void handleAuthError(AuthenticationErrorType error, String errorMessage) mAnalyticsListener.trackLoginSecurityKeyFailure(); ToastUtils.showToast(getActivity(), errorMessage == null ? getString(R.string.error_generic) : errorMessage); + break; default: AppLog.e(T.NUX, "Server response: " + errorMessage); mAnalyticsListener.trackFailure(errorMessage); From 959b876b68d9daf447ee51370147116feed8f312 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 8 Nov 2023 19:03:45 -0300 Subject: [PATCH 802/888] Simplify empty assertion of transports inside PasskeyCredentialsHandler --- .../login/webauthn/PasskeyCredentialsHandler.kt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt index 388d7f0e051..ad92a7dcd85 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt @@ -72,12 +72,8 @@ class PasskeyCredentialsHandler( "hybrid" -> Transport.HYBRID else -> null } - }.takeIf { it.isNotEmpty() } ?: listOf( - Transport.USB, - Transport.NFC, - Transport.BLUETOOTH_LOW_ENERGY, - Transport.HYBRID, - Transport.INTERNAL - ) + }.ifEmpty { + listOf(Transport.USB, Transport.NFC, Transport.BLUETOOTH_LOW_ENERGY, Transport.HYBRID, Transport.INTERNAL) + } } } From fe6271fa0d82f148580898fb5e091e514adfc72d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 8 Nov 2023 19:08:28 -0300 Subject: [PATCH 803/888] Remove assert usage from Login2FaFragment --- .../wordpress/android/login/Login2FaFragment.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 9a928940d18..25825d46b61 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -624,18 +624,24 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { mPasskeyCredentialsHandler.createIntentSender( requireContext(), intent -> { - assert mResultLauncher != null; - mResultLauncher.launch(intent); + if (mResultLauncher != null) { + mResultLauncher.launch(intent); + } }); } private void onCredentialsResultAvailable(@NonNull Intent resultData) { if (resultData.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)) { byte[] credentialBytes = resultData.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA); - assert credentialBytes != null; + if (credentialBytes == null || mPasskeyCredentialsHandler == null) { + endProgress(); + handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, + getString(R.string.login_error_security_key)); + return; + } + PublicKeyCredential credentials = PublicKeyCredential.deserializeFromBytes(credentialBytes); - assert mPasskeyCredentialsHandler != null; FinishWebauthnChallengePayload payload = mPasskeyCredentialsHandler.onCredentialsAvailable(credentials); mDispatcher.dispatch( From a8fae1e8f0c1008c062a9d0d35d4803c0cc023d7 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 8 Nov 2023 19:11:26 -0300 Subject: [PATCH 804/888] Refactor webauthn error handling --- .../wordpress/android/login/Login2FaFragment.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 25825d46b61..a9f0fb18b54 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -291,9 +291,7 @@ public void onCreate(Bundle savedInstanceState) { if (result.getResultCode() == RESULT_OK && result.getData() != null) { onCredentialsResultAvailable(result.getData()); } else { - String errorMessage = getString(R.string.login_error_security_key); - endProgress(); - handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, errorMessage); + handleWebauthnError(); } }); } @@ -634,9 +632,7 @@ private void onCredentialsResultAvailable(@NonNull Intent resultData) { if (resultData.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)) { byte[] credentialBytes = resultData.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA); if (credentialBytes == null || mPasskeyCredentialsHandler == null) { - endProgress(); - handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, - getString(R.string.login_error_security_key)); + handleWebauthnError(); return; } @@ -660,4 +656,10 @@ public void onSecurityKeyCheckFinished(WebauthnPasskeyAuthenticated event) { mAnalyticsListener.trackLoginSecurityKeySuccess(); doFinishLogin(); } + + private void handleWebauthnError() { + String errorMessage = getString(R.string.login_error_security_key); + endProgress(); + handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, errorMessage); + } } From 55c198e5b4f36855f844dd77951cc360125d5386 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 9 Nov 2023 18:42:19 -0300 Subject: [PATCH 805/888] Adjust parameters for event flow --- .../login/LoginEmailPasswordFragment.java | 4 ++-- .../android/login/LoginWpcomService.java | 23 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 2a5c6682897..e67940ccd56 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -24,7 +24,7 @@ import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.login.LoginWpcomService.LoginState; import org.wordpress.android.login.LoginWpcomService.OnCredentialsOK; -import org.wordpress.android.login.LoginWpcomService.SecurityKeyRequested; +import org.wordpress.android.login.LoginWpcomService.TwoFactorRequested; import org.wordpress.android.login.util.AvatarHelper; import org.wordpress.android.login.util.AvatarHelper.AvatarRequestListener; import org.wordpress.android.login.util.SiteUtils; @@ -345,7 +345,7 @@ public void onCredentialsOK(OnCredentialsOK event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onSecurityKeyAuthStarted(SecurityKeyRequested event) { + public void onSecurityKeyAuthStarted(TwoFactorRequested event) { onLoginFinished(false); mLoginListener.needs2faSecurityKey(mEmailAddress, mRequestedPassword, event.userId, event.webauthnNonce); LoginWpcomService.clearLoginServiceState(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 01d87aa8e04..da0dd5db0d6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -20,8 +20,8 @@ import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; import org.wordpress.android.fluxc.store.AccountStore.OnAccountChanged; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; -import org.wordpress.android.fluxc.store.AccountStore.OnSecurityKeyAuthStarted; import org.wordpress.android.fluxc.store.AccountStore.OnSocialChanged; +import org.wordpress.android.fluxc.store.AccountStore.OnTwoFactorAuthStarted; import org.wordpress.android.fluxc.store.AccountStore.PushSocialPayload; import org.wordpress.android.fluxc.store.SiteStore.FetchSitesPayload; import org.wordpress.android.fluxc.store.SiteStore.OnSiteChanged; @@ -155,13 +155,20 @@ static class OnCredentialsOK { OnCredentialsOK() {} } - static class SecurityKeyRequested { - public String userId; - public String webauthnNonce; + static class TwoFactorRequested { + public final String userId; + public final String webauthnNonce; + public final String backupNonce; + public final String authenticatorNonce; + public final String pushNonce; - SecurityKeyRequested(String userId, String webauthnNonce) { + TwoFactorRequested(String userId, String webauthnNonce, String backupNonce, + String authenticatorNonce, String pushNonce) { this.userId = userId; this.webauthnNonce = webauthnNonce; + this.backupNonce = backupNonce; + this.authenticatorNonce = authenticatorNonce; + this.pushNonce = pushNonce; } } @@ -342,10 +349,12 @@ private void signalCredentialsOK() { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onSecurityKeyAuthStarted(OnSecurityKeyAuthStarted event) { + public void onTwoFactorAuthStarted(OnTwoFactorAuthStarted event) { signalCredentialsOK(); setState(LoginStep.SECURITY_KEY_NEEDED); - EventBus.getDefault().post(new SecurityKeyRequested(event.userId, event.webauthnNonce)); + TwoFactorRequested twoFactorRequest = new TwoFactorRequested(event.userId, event.webauthnNonce, + event.mBackupNonce, event.authenticatorNonce, event.pushNonce); + EventBus.getDefault().post(twoFactorRequest); } // OnChanged events From f2a171a0ca4916e7b02bc6ea778a6e74b74347ba Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 9 Nov 2023 18:45:36 -0300 Subject: [PATCH 806/888] Rework how 2FA parameters are handled and delivered --- .../wordpress/android/login/LoginEmailPasswordFragment.java | 5 +++-- .../main/java/org/wordpress/android/login/LoginListener.java | 2 +- .../java/org/wordpress/android/login/LoginWpcomService.java | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index e67940ccd56..5a9792f9483 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -345,9 +345,10 @@ public void onCredentialsOK(OnCredentialsOK event) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onSecurityKeyAuthStarted(TwoFactorRequested event) { + public void onTwoFactorAuthStarted(TwoFactorRequested event) { onLoginFinished(false); - mLoginListener.needs2faSecurityKey(mEmailAddress, mRequestedPassword, event.userId, event.webauthnNonce); + mLoginListener.needs2fa(mEmailAddress, mRequestedPassword, event.userId, + event.webauthnNonce, event.authenticatorNonce, event.backupNonce, event.pushNonce); LoginWpcomService.clearLoginServiceState(); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index b79cd3f907b..d83a8a58f39 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -48,9 +48,9 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void forgotPassword(String url); void useMagicLinkInstead(String email, boolean verifyEmail); void needs2fa(String email, String password); + void needs2fa(String email, String password, String userId, String webauthnNonce, String nonceAuthenticator, String nonceBackup, String noncePush); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); - void needs2faSecurityKey(String email, String password, String userId, String webauthnNonce); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index da0dd5db0d6..c945f05b01a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -352,8 +352,8 @@ private void signalCredentialsOK() { public void onTwoFactorAuthStarted(OnTwoFactorAuthStarted event) { signalCredentialsOK(); setState(LoginStep.SECURITY_KEY_NEEDED); - TwoFactorRequested twoFactorRequest = new TwoFactorRequested(event.userId, event.webauthnNonce, - event.mBackupNonce, event.authenticatorNonce, event.pushNonce); + TwoFactorRequested twoFactorRequest = new TwoFactorRequested(event.userId, + event.webauthnNonce, event.mBackupNonce, event.authenticatorNonce, event.pushNonce); EventBus.getDefault().post(twoFactorRequest); } From 879cc7bff42d17bc4bec5fd5e4ee4336de535106 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 9 Nov 2023 18:48:55 -0300 Subject: [PATCH 807/888] Add newInstance function to Login2FaFragment --- .../wordpress/android/login/Login2FaFragment.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index a9f0fb18b54..80315bde3a7 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -136,16 +136,21 @@ public static Login2FaFragment newInstance(String emailAddress, String password) return fragment; } - public static Login2FaFragment newInstanceSecurityKey(String emailAddress, String password, - String userId, String webauthnNonce) { + public static Login2FaFragment newInstance(String emailAddress, String password, + String userId, String webauthnNonce, + String authenticatorNonce, String backupNonce, + String smsNonce) { + boolean supportsWebauthn = webauthnNonce != null && !webauthnNonce.isEmpty(); Login2FaFragment fragment = new Login2FaFragment(); Bundle args = new Bundle(); args.putString(ARG_EMAIL_ADDRESS, emailAddress); args.putString(ARG_PASSWORD, password); args.putString(ARG_2FA_USER_ID, userId); args.putString(ARG_WEBAUTHN_NONCE, webauthnNonce); - args.putString(ARG_2FA_NONCE_AUTHENTICATOR, webauthnNonce); - args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, true); + args.putString(ARG_2FA_NONCE_AUTHENTICATOR, authenticatorNonce); + args.putString(ARG_2FA_NONCE_BACKUP, backupNonce); + args.putString(ARG_2FA_NONCE_SMS, smsNonce); + args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, supportsWebauthn); fragment.setArguments(args); return fragment; } From c727e3007048028b830bd4a561bb38c8a86e855a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 9 Nov 2023 18:49:24 -0300 Subject: [PATCH 808/888] Fix checkstyle --- .../main/java/org/wordpress/android/login/LoginListener.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index d83a8a58f39..15ee803f056 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -48,7 +48,8 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void forgotPassword(String url); void useMagicLinkInstead(String email, boolean verifyEmail); void needs2fa(String email, String password); - void needs2fa(String email, String password, String userId, String webauthnNonce, String nonceAuthenticator, String nonceBackup, String noncePush); + void needs2fa(String email, String password, String userId, String webauthnNonce, + String nonceAuthenticator, String nonceBackup, String noncePush); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); void loggedInViaPassword(ArrayList oldSitesIds); From 3a0b3805cf7edac268db06b914850bbef4a5e8c1 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 9 Nov 2023 20:53:46 -0300 Subject: [PATCH 809/888] Correctly trigger expected payload when submitting 2FA --- .../org/wordpress/android/login/Login2FaFragment.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 80315bde3a7..306ba2cfad1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -35,6 +35,7 @@ import org.wordpress.android.fluxc.generated.AccountActionBuilder; import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder; import org.wordpress.android.fluxc.store.AccountStore.AuthenticatePayload; +import org.wordpress.android.fluxc.store.AccountStore.AuthenticateTwoFactorPayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; @@ -371,10 +372,10 @@ private void doAuthAction(@StringRes int messageId, String twoStepCode, boolean mDispatcher.dispatch(AccountActionBuilder.newPushSocialAuthAction(payload)); } } else { - AuthenticatePayload payload = new AuthenticatePayload(mEmailAddress, mPassword); - payload.twoStepCode = twoStepCode; - payload.shouldSendTwoStepSms = shouldSendTwoStepSMS; - mDispatcher.dispatch(AuthenticationActionBuilder.newAuthenticateAction(payload)); + AuthenticateTwoFactorPayload payload = new AuthenticateTwoFactorPayload(mEmailAddress, + mPassword, twoStepCode, shouldSendTwoStepSMS); + mDispatcher.dispatch(AuthenticationActionBuilder + .newAuthenticateTwoFactorAction(payload)); } } From 7d4adec9634cdde9ec5958e55991ffc9ab6a17ff Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 9 Nov 2023 20:55:48 -0300 Subject: [PATCH 810/888] Fix checkstyle issue --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 306ba2cfad1..ba5872695b0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -34,7 +34,6 @@ import org.greenrobot.eventbus.ThreadMode; import org.wordpress.android.fluxc.generated.AccountActionBuilder; import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder; -import org.wordpress.android.fluxc.store.AccountStore.AuthenticatePayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticateTwoFactorPayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload; From cf5920dee86f88d95e4a13f5a13c91e03f8233ed Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 9 Nov 2023 22:09:32 -0300 Subject: [PATCH 811/888] Implement auth types parameter in Login2FaFragment --- .../android/login/Login2FaFragment.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index ba5872695b0..6b66af0c04b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -55,6 +55,7 @@ import org.wordpress.android.util.ToastUtils; import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -86,6 +87,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private static final String ARG_PASSWORD = "ARG_PASSWORD"; private static final String ARG_WEBAUTHN_NONCE = "WEBAUTHN_NONCE"; private static final String ARG_DISPLAY_SECURITY_KEY_BUTTON = "ARG_DISPLAY_SECURITY_KEY_BUTTON"; + private static final String ARG_2FA_SUPPORTED_AUTH_TYPES = "ARG_2FA_SUPPORTED_AUTH_TYPES"; private static final int LENGTH_NONCE_AUTHENTICATOR = 6; private static final int LENGTH_NONCE_BACKUP = 8; private static final int LENGTH_NONCE_SMS = 7; @@ -124,6 +126,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private boolean mIsSocialLoginConnect; private boolean mSentSmsCode; private boolean mIsSecurityKeyEnabled; + private List mSupportedAuthTypes; @Nullable private PasskeyCredentialsHandler mPasskeyCredentialsHandler = null; @Nullable private ActivityResultLauncher mResultLauncher = null; @@ -139,7 +142,7 @@ public static Login2FaFragment newInstance(String emailAddress, String password) public static Login2FaFragment newInstance(String emailAddress, String password, String userId, String webauthnNonce, String authenticatorNonce, String backupNonce, - String smsNonce) { + String smsNonce, List authTypes) { boolean supportsWebauthn = webauthnNonce != null && !webauthnNonce.isEmpty(); Login2FaFragment fragment = new Login2FaFragment(); Bundle args = new Bundle(); @@ -151,6 +154,7 @@ public static Login2FaFragment newInstance(String emailAddress, String password, args.putString(ARG_2FA_NONCE_BACKUP, backupNonce); args.putString(ARG_2FA_NONCE_SMS, smsNonce); args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, supportsWebauthn); + args.putStringArrayList(ARG_2FA_SUPPORTED_AUTH_TYPES, new ArrayList<>(authTypes)); fragment.setArguments(args); return fragment; } @@ -278,6 +282,8 @@ public void onCreate(Bundle savedInstanceState) { mService = getArguments().getString(ARG_2FA_SOCIAL_SERVICE); mWebauthnNonce = getArguments().getString(ARG_WEBAUTHN_NONCE); mIsSecurityKeyEnabled = getArguments().getBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, false); + mSupportedAuthTypes = handleSupportedAuthTypesParameter( + getArguments().getStringArrayList(ARG_2FA_SUPPORTED_AUTH_TYPES)); if (savedInstanceState != null) { // Overwrite argument nonce values with saved state values on device rotation. @@ -667,4 +673,41 @@ private void handleWebauthnError() { endProgress(); handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, errorMessage); } + + @NonNull private static ArrayList handleSupportedAuthTypesParameter( + ArrayList supportedTypes) { + ArrayList supportedAuthTypes = new ArrayList<>(); + if (supportedTypes != null) { + for (String type : supportedTypes) { + SupportedAuthTypes parsedType = SupportedAuthTypes.fromString(type); + if (parsedType != SupportedAuthTypes.UNKNOWN) { + supportedAuthTypes.add(parsedType); + } + } + } + return supportedAuthTypes; + } + + public enum SupportedAuthTypes { + WEBAUTHN, + BACKUP, + AUTHENTICATOR, + PUSH, + UNKNOWN; + + static SupportedAuthTypes fromString(String value) { + switch (value) { + case "webauthn": + return WEBAUTHN; + case "backup": + return BACKUP; + case "authenticator": + return AUTHENTICATOR; + case "push": + return PUSH; + default: + return UNKNOWN; + } + } + } } From 1638c69345083427a333962c3b81e20e2fbd6ff0 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 9 Nov 2023 22:14:48 -0300 Subject: [PATCH 812/888] Add 2fa fields visibility control --- .../org/wordpress/android/login/Login2FaFragment.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 6b66af0c04b..d8a4d376076 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -86,7 +86,6 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private static final String ARG_EMAIL_ADDRESS = "ARG_EMAIL_ADDRESS"; private static final String ARG_PASSWORD = "ARG_PASSWORD"; private static final String ARG_WEBAUTHN_NONCE = "WEBAUTHN_NONCE"; - private static final String ARG_DISPLAY_SECURITY_KEY_BUTTON = "ARG_DISPLAY_SECURITY_KEY_BUTTON"; private static final String ARG_2FA_SUPPORTED_AUTH_TYPES = "ARG_2FA_SUPPORTED_AUTH_TYPES"; private static final int LENGTH_NONCE_AUTHENTICATOR = 6; private static final int LENGTH_NONCE_BACKUP = 8; @@ -125,7 +124,6 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private boolean mIsSocialLogin; private boolean mIsSocialLoginConnect; private boolean mSentSmsCode; - private boolean mIsSecurityKeyEnabled; private List mSupportedAuthTypes; @Nullable private PasskeyCredentialsHandler mPasskeyCredentialsHandler = null; @Nullable private ActivityResultLauncher mResultLauncher = null; @@ -153,7 +151,6 @@ public static Login2FaFragment newInstance(String emailAddress, String password, args.putString(ARG_2FA_NONCE_AUTHENTICATOR, authenticatorNonce); args.putString(ARG_2FA_NONCE_BACKUP, backupNonce); args.putString(ARG_2FA_NONCE_SMS, smsNonce); - args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, supportsWebauthn); args.putStringArrayList(ARG_2FA_SUPPORTED_AUTH_TYPES, new ArrayList<>(authTypes)); fragment.setArguments(args); return fragment; @@ -217,7 +214,9 @@ protected void setupContent(ViewGroup rootView) { // restrict the allowed input chars to just numbers m2FaInput.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789")); + boolean isSmsEnabled = mSupportedAuthTypes.contains(SupportedAuthTypes.PUSH); mOtpButton = rootView.findViewById(R.id.login_otp_button); + mOtpButton.setVisibility(isSmsEnabled ? View.VISIBLE : View.GONE); mOtpButton.setText(mSentSmsCode ? R.string.login_text_otp_another : R.string.login_text_otp); mOtpButton.setOnClickListener(new OnClickListener() { @Override @@ -229,8 +228,9 @@ public void onClick(View v) { } }); + boolean isSecurityKeyEnabled = mSupportedAuthTypes.contains(SupportedAuthTypes.WEBAUTHN); mSecurityKeyButton = rootView.findViewById(R.id.login_security_key_button); - mSecurityKeyButton.setVisibility(mIsSecurityKeyEnabled ? View.VISIBLE : View.GONE); + mSecurityKeyButton.setVisibility(isSecurityKeyEnabled ? View.VISIBLE : View.GONE); mSecurityKeyButton.setOnClickListener(view -> doAuthWithSecurityKeyAction()); } @@ -281,7 +281,6 @@ public void onCreate(Bundle savedInstanceState) { mIsSocialLoginConnect = getArguments().getBoolean(ARG_2FA_IS_SOCIAL_CONNECT); mService = getArguments().getString(ARG_2FA_SOCIAL_SERVICE); mWebauthnNonce = getArguments().getString(ARG_WEBAUTHN_NONCE); - mIsSecurityKeyEnabled = getArguments().getBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, false); mSupportedAuthTypes = handleSupportedAuthTypesParameter( getArguments().getStringArrayList(ARG_2FA_SUPPORTED_AUTH_TYPES)); @@ -674,7 +673,7 @@ private void handleWebauthnError() { handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, errorMessage); } - @NonNull private static ArrayList handleSupportedAuthTypesParameter( + @NonNull private ArrayList handleSupportedAuthTypesParameter( ArrayList supportedTypes) { ArrayList supportedAuthTypes = new ArrayList<>(); if (supportedTypes != null) { From b00ae742ef37d94acdf5beb0cf267741d94aae1d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 9 Nov 2023 22:20:04 -0300 Subject: [PATCH 813/888] Update payload call stack to include supported Auth types --- .../android/login/LoginEmailPasswordFragment.java | 3 ++- .../java/org/wordpress/android/login/LoginListener.java | 4 +++- .../org/wordpress/android/login/LoginWpcomService.java | 9 +++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java index 5a9792f9483..62cfc53e750 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginEmailPasswordFragment.java @@ -348,7 +348,8 @@ public void onCredentialsOK(OnCredentialsOK event) { public void onTwoFactorAuthStarted(TwoFactorRequested event) { onLoginFinished(false); mLoginListener.needs2fa(mEmailAddress, mRequestedPassword, event.userId, - event.webauthnNonce, event.authenticatorNonce, event.backupNonce, event.pushNonce); + event.webauthnNonce, event.authenticatorNonce, event.backupNonce, + event.pushNonce, event.supportedAuthTypes); LoginWpcomService.clearLoginServiceState(); } diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 15ee803f056..77965ab0dab 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -10,6 +10,7 @@ import org.wordpress.android.fluxc.store.SiteStore.ConnectSiteInfoPayload; import java.util.ArrayList; +import java.util.List; public interface LoginListener { interface SelfSignedSSLCallback { @@ -49,7 +50,8 @@ void gotUnregisteredSocialAccount(String email, String displayName, String idTok void useMagicLinkInstead(String email, boolean verifyEmail); void needs2fa(String email, String password); void needs2fa(String email, String password, String userId, String webauthnNonce, - String nonceAuthenticator, String nonceBackup, String noncePush); + String nonceAuthenticator, String nonceBackup, String noncePush, + List supportedAuthTypes); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, String nonceSms); void needs2faSocialConnect(String email, String password, String idToken, String service); void loggedInViaPassword(ArrayList oldSitesIds); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index c945f05b01a..8d2f55c7505 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -34,6 +34,7 @@ import org.wordpress.android.util.AutoForegroundNotification; import org.wordpress.android.util.ToastUtils; +import java.util.List; import java.util.Map; import javax.inject.Inject; @@ -161,14 +162,17 @@ static class TwoFactorRequested { public final String backupNonce; public final String authenticatorNonce; public final String pushNonce; + public final List supportedAuthTypes; TwoFactorRequested(String userId, String webauthnNonce, String backupNonce, - String authenticatorNonce, String pushNonce) { + String authenticatorNonce, String pushNonce, + List supportedAuthTypes) { this.userId = userId; this.webauthnNonce = webauthnNonce; this.backupNonce = backupNonce; this.authenticatorNonce = authenticatorNonce; this.pushNonce = pushNonce; + this.supportedAuthTypes = supportedAuthTypes; } } @@ -353,7 +357,8 @@ public void onTwoFactorAuthStarted(OnTwoFactorAuthStarted event) { signalCredentialsOK(); setState(LoginStep.SECURITY_KEY_NEEDED); TwoFactorRequested twoFactorRequest = new TwoFactorRequested(event.userId, - event.webauthnNonce, event.mBackupNonce, event.authenticatorNonce, event.pushNonce); + event.webauthnNonce, event.mBackupNonce, event.authenticatorNonce, + event.pushNonce, event.mSupportedAuthTypes); EventBus.getDefault().post(twoFactorRequest); } From bd267afd48060e851973833777d465dde0821364 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Fri, 10 Nov 2023 12:05:16 -0300 Subject: [PATCH 814/888] Update LoginAnalyticsListener --- .../java/org/wordpress/android/login/LoginAnalyticsListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt index d33c360d854..954cae5bd21 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginAnalyticsListener.kt @@ -72,7 +72,7 @@ interface LoginAnalyticsListener { fun magicLinkRequestScreenResumed() fun magicLinkSentScreenResumed() fun usernamePasswordScreenResumed() - fun trackLoginSecurityKeyNeeded() + fun trackLogin2faNeeded() fun trackLoginSecurityKeySuccess() fun trackLoginSecurityKeyFailure() fun trackUseSecurityKeyClicked() From 2ca11d0b7e76edeebc66a23b17f5f399067b5af3 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 13 Nov 2023 17:47:07 -0300 Subject: [PATCH 815/888] Update newInstanceSocial to request the auth types --- .../java/org/wordpress/android/login/Login2FaFragment.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index a590cc1252d..64c003e9ac4 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -158,7 +158,8 @@ public static Login2FaFragment newInstance(String emailAddress, String password, public static Login2FaFragment newInstanceSocial(String emailAddress, String userId, String nonceAuthenticator, String nonceBackup, - String nonceSms, String nonceWebauthn) { + String nonceSms, String nonceWebauthn, + List authTypes) { Login2FaFragment fragment = new Login2FaFragment(); Bundle args = new Bundle(); args.putString(ARG_EMAIL_ADDRESS, emailAddress); @@ -170,7 +171,7 @@ public static Login2FaFragment newInstanceSocial(String emailAddress, String use args.putBoolean(ARG_2FA_IS_SOCIAL, true); // Social account connected, connect call not needed. args.putBoolean(ARG_2FA_IS_SOCIAL_CONNECT, false); - args.putBoolean(ARG_DISPLAY_SECURITY_KEY_BUTTON, nonceWebauthn != null && !nonceWebauthn.isEmpty()); + args.putStringArrayList(ARG_2FA_SUPPORTED_AUTH_TYPES, new ArrayList<>(authTypes)); fragment.setArguments(args); return fragment; } From a47f1b0295944deecf3884025f0a7f053ca36abc Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 13 Nov 2023 17:52:39 -0300 Subject: [PATCH 816/888] Update LoginListener to receive the two step auth types list --- .../java/org/wordpress/android/login/LoginGoogleFragment.java | 2 +- .../main/java/org/wordpress/android/login/LoginListener.java | 2 +- .../java/org/wordpress/android/login/SignupGoogleFragment.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index f828d76c8c0..5df4707fde6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -239,7 +239,7 @@ public void onSocialChanged(OnSocialChanged event) { } else if (event.requiresTwoStepAuth || Login2FaFragment.TWO_FACTOR_TYPE_SMS.equals(event.notificationSent)) { AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - needs 2fa"); mLoginListener.needs2faSocial(mGoogleEmail, event.userId, event.nonceAuthenticator, event.nonceBackup, - event.nonceSms, event.nonceWebauthn); + event.nonceSms, event.twoStepTypes); } else { AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - success"); mGoogleListener.onGoogleLoginFinished(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index ac5a5e5e56c..2d75ae148e3 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -53,7 +53,7 @@ void needs2fa(String email, String password, String userId, String webauthnNonce String nonceAuthenticator, String nonceBackup, String noncePush, List supportedAuthTypes); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, - String nonceSms, String nonceWebauthn); + String nonceSms, List supportedAuthTypes); void needs2faSocialConnect(String email, String password, String idToken, String service); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java index d6dca8507f7..467be0ec618 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java @@ -269,7 +269,7 @@ public void onSocialChanged(OnSocialChanged event) { AppLog.d(T.MAIN, "GOOGLE SIGNUP: onSocialChanged - 2fa required"); mAnalyticsListener.trackSignupSocialToLogin(); mLoginListener.needs2faSocial(mGoogleEmail, event.userId, event.nonceAuthenticator, event.nonceBackup, - event.nonceSms, event.nonceWebauthn); + event.nonceSms, event.twoStepTypes); finishFlow(); } else { AppLog.d(T.MAIN, "GOOGLE SIGNUP: onSocialChanged - google login success"); From 1fb6f7f6ccb4e1bfb162038697410cce23320e9d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 13 Nov 2023 18:16:35 -0300 Subject: [PATCH 817/888] Move webauthn nonce parameter back with auth types --- .../java/org/wordpress/android/login/LoginGoogleFragment.java | 2 +- .../main/java/org/wordpress/android/login/LoginListener.java | 2 +- .../java/org/wordpress/android/login/SignupGoogleFragment.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java index 5df4707fde6..302701f6ed4 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginGoogleFragment.java @@ -239,7 +239,7 @@ public void onSocialChanged(OnSocialChanged event) { } else if (event.requiresTwoStepAuth || Login2FaFragment.TWO_FACTOR_TYPE_SMS.equals(event.notificationSent)) { AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - needs 2fa"); mLoginListener.needs2faSocial(mGoogleEmail, event.userId, event.nonceAuthenticator, event.nonceBackup, - event.nonceSms, event.twoStepTypes); + event.nonceSms, event.nonceWebauthn, event.twoStepTypes); } else { AppLog.d(T.MAIN, "GOOGLE LOGIN: onSocialChanged - success"); mGoogleListener.onGoogleLoginFinished(); diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 2d75ae148e3..25e85e121ec 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -53,7 +53,7 @@ void needs2fa(String email, String password, String userId, String webauthnNonce String nonceAuthenticator, String nonceBackup, String noncePush, List supportedAuthTypes); void needs2faSocial(String email, String userId, String nonceAuthenticator, String nonceBackup, - String nonceSms, List supportedAuthTypes); + String nonceSms, String nonceWebauthn, List supportedAuthTypes); void needs2faSocialConnect(String email, String password, String idToken, String service); void loggedInViaPassword(ArrayList oldSitesIds); void helpEmailPasswordScreen(String email); diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java index 467be0ec618..f37551cda78 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupGoogleFragment.java @@ -269,7 +269,7 @@ public void onSocialChanged(OnSocialChanged event) { AppLog.d(T.MAIN, "GOOGLE SIGNUP: onSocialChanged - 2fa required"); mAnalyticsListener.trackSignupSocialToLogin(); mLoginListener.needs2faSocial(mGoogleEmail, event.userId, event.nonceAuthenticator, event.nonceBackup, - event.nonceSms, event.twoStepTypes); + event.nonceSms, event.nonceWebauthn, event.twoStepTypes); finishFlow(); } else { AppLog.d(T.MAIN, "GOOGLE SIGNUP: onSocialChanged - google login success"); From 170e55eb42135d1edacbe1930f1beceb7d434093 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 15 Jan 2024 04:42:37 -0300 Subject: [PATCH 818/888] Add Credential Manager libs --- libs/login/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 97edb02ce5d..639cd124872 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -64,6 +64,9 @@ dependencies { implementation "com.google.android.gms:play-services-fido:$fidoVersion" + implementation "androidx.credentials:credentials:1.2.0" + implementation "androidx.credentials:credentials-play-services-auth:1.2.0" + // Dagger implementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" From 4e559b50ba1d5d9f3068f89ff5f43f70fcfdc047 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 15 Jan 2024 04:43:13 -0300 Subject: [PATCH 819/888] Add compile configs for Java version in build.gradle --- libs/login/build.gradle | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 639cd124872..70f42af00d9 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -21,6 +21,15 @@ repositories { } android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlin { + jvmToolchain(17) + } + namespace "org.wordpress.android.login" compileSdkVersion rootProject.compileSdkVersion From c89440104971635df71bffeac90fa56994da1c6e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 15 Jan 2024 04:43:48 -0300 Subject: [PATCH 820/888] Temporary fix for deprecated usage of options menu --- .../org/wordpress/android/login/SignupConfirmationFragment.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt index b0b5492b49c..0afb4bee5f9 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt @@ -76,7 +76,8 @@ class SignupConfirmationFragment : Fragment() { mPhotoUrl = it.getString(ARG_SOCIAL_PHOTO_URL) mService = it.getString(ARG_SOCIAL_SERVICE) } - setHasOptionsMenu(true) + //TODO: Migrate this to current SDK requirement, this one is deprecated + //setHasOptionsMenu(true) } override fun onCreateView( From 4e4497600b6240af08362046b111a06c6c262307 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 15 Jan 2024 04:54:35 -0300 Subject: [PATCH 821/888] Add credential manager version build variable --- libs/login/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 70f42af00d9..7fdee9495b4 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -73,8 +73,8 @@ dependencies { implementation "com.google.android.gms:play-services-fido:$fidoVersion" - implementation "androidx.credentials:credentials:1.2.0" - implementation "androidx.credentials:credentials-play-services-auth:1.2.0" + implementation "androidx.credentials:credentials:$credentialManagerVersion" + implementation "androidx.credentials:credentials-play-services-auth:$credentialManagerVersion" // Dagger implementation "com.google.dagger:dagger:$daggerVersion" From 9872068549f153b805439bb6ff528a20bbbddfe9 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 15 Jan 2024 04:55:23 -0300 Subject: [PATCH 822/888] Fix checkstyle issues --- .../org/wordpress/android/login/SignupConfirmationFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt index 0afb4bee5f9..2170189c715 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt @@ -76,8 +76,8 @@ class SignupConfirmationFragment : Fragment() { mPhotoUrl = it.getString(ARG_SOCIAL_PHOTO_URL) mService = it.getString(ARG_SOCIAL_SERVICE) } - //TODO: Migrate this to current SDK requirement, this one is deprecated - //setHasOptionsMenu(true) + // TODO: Migrate this to current SDK requirement, this one is deprecated + // setHasOptionsMenu(true) } override fun onCreateView( From fe859fc716498c4a8c1bb96f28316dadd243fd59 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 18 Jan 2024 18:04:58 -0300 Subject: [PATCH 823/888] Define CredentialManagerHandler type --- .../login/webauthn/CredentialManagerHandler.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt new file mode 100644 index 00000000000..638450e4cf8 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -0,0 +1,14 @@ +package org.wordpress.android.login.webauthn + +import android.content.Context +import android.util.Log +import androidx.annotation.RequiresApi +import androidx.credentials.CredentialManager +import androidx.credentials.GetCredentialRequest +import androidx.credentials.GetCredentialResponse +import androidx.credentials.GetPasswordOption +import androidx.credentials.GetPublicKeyCredentialOption +import androidx.credentials.exceptions.GetCredentialException + +class CredentialManagerHandler { +} From f7694b76675a107b3d6a1fbd6ff1067ed1354283 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 18 Jan 2024 18:05:19 -0300 Subject: [PATCH 824/888] Introduce initial basic Credential Manager implementation --- .../webauthn/CredentialManagerHandler.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index 638450e4cf8..228cdbacc27 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -11,4 +11,25 @@ import androidx.credentials.GetPublicKeyCredentialOption import androidx.credentials.exceptions.GetCredentialException class CredentialManagerHandler { + @RequiresApi(34) + private suspend fun CredentialManager.createPasskey( + context: Context, + requestJson: String + ): GetCredentialResponse? { + val password = GetPasswordOption() + val publicKeyCred = GetPublicKeyCredentialOption(requestJson) + val getCredRequest = GetCredentialRequest( + listOf(password, publicKeyCred) + ) + + return try { + getCredential( + request = getCredRequest, + context = context, + ) + } catch (e: GetCredentialException) { + Log.e("Error", e.stackTraceToString()) + null + } + } } From 22b51a45dcc29eb7c3370aa6a1ea9747857d92d5 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 18 Jan 2024 18:10:07 -0300 Subject: [PATCH 825/888] Start migration towards Credential Manager implementation without coroutines --- .../webauthn/CredentialManagerHandler.kt | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index 228cdbacc27..e1cfdb4622d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -4,15 +4,20 @@ import android.content.Context import android.util.Log import androidx.annotation.RequiresApi import androidx.credentials.CredentialManager +import androidx.credentials.CredentialManagerCallback import androidx.credentials.GetCredentialRequest import androidx.credentials.GetCredentialResponse import androidx.credentials.GetPasswordOption import androidx.credentials.GetPublicKeyCredentialOption import androidx.credentials.exceptions.GetCredentialException -class CredentialManagerHandler { +class CredentialManagerHandler( + private val context: Context +) { + val credentialManager = CredentialManager.create(context) + @RequiresApi(34) - private suspend fun CredentialManager.createPasskey( + private fun CredentialManager.createPasskey( context: Context, requestJson: String ): GetCredentialResponse? { @@ -23,9 +28,18 @@ class CredentialManagerHandler { ) return try { - getCredential( + getCredentialAsync( request = getCredRequest, context = context, + callback = object : CredentialManagerCallback() { + override fun onError(e: GetCredentialException) { + TODO("Not yet implemented") + } + + override fun onResult(result: GetCredentialResponse) { + TODO("Not yet implemented") + } + } ) } catch (e: GetCredentialException) { Log.e("Error", e.stackTraceToString()) From e23bd55ef382f238ea1f59f0a655198cb401f6a5 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 18 Jan 2024 18:16:41 -0300 Subject: [PATCH 826/888] Add async operation structure inside the CredentialManagerHandler --- .../webauthn/CredentialManagerHandler.kt | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index e1cfdb4622d..2091e78c3c4 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -1,6 +1,7 @@ package org.wordpress.android.login.webauthn import android.content.Context +import android.os.CancellationSignal import android.util.Log import androidx.annotation.RequiresApi import androidx.credentials.CredentialManager @@ -10,40 +11,33 @@ import androidx.credentials.GetCredentialResponse import androidx.credentials.GetPasswordOption import androidx.credentials.GetPublicKeyCredentialOption import androidx.credentials.exceptions.GetCredentialException +import java.util.concurrent.Executors class CredentialManagerHandler( private val context: Context ) { - val credentialManager = CredentialManager.create(context) + private val credentialManager = CredentialManager.create(context) + private val executor = Executors.newSingleThreadExecutor() @RequiresApi(34) private fun CredentialManager.createPasskey( context: Context, - requestJson: String - ): GetCredentialResponse? { + requestJson: String, + onResult: (Result) -> Unit + ) { val password = GetPasswordOption() val publicKeyCred = GetPublicKeyCredentialOption(requestJson) val getCredRequest = GetCredentialRequest( listOf(password, publicKeyCred) ) - return try { - getCredentialAsync( - request = getCredRequest, - context = context, - callback = object : CredentialManagerCallback() { - override fun onError(e: GetCredentialException) { - TODO("Not yet implemented") - } + val signal = CancellationSignal() + + try { - override fun onResult(result: GetCredentialResponse) { - TODO("Not yet implemented") - } - } - ) } catch (e: GetCredentialException) { Log.e("Error", e.stackTraceToString()) - null + onResult(Result.failure(e)) } } } From 3f9bd53fff8e41903fa3e9879af223f77551911b Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 18 Jan 2024 18:17:25 -0300 Subject: [PATCH 827/888] Implement expected callback responses for createPasskey function --- .../login/webauthn/CredentialManagerHandler.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index 2091e78c3c4..fcc78277cd3 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -34,7 +34,21 @@ class CredentialManagerHandler( val signal = CancellationSignal() try { + getCredentialAsync( + request = getCredRequest, + context = context, + cancellationSignal = signal, + executor = executor, + callback = object : CredentialManagerCallback { + override fun onError(e: GetCredentialException) { + onResult(Result.failure(e)) + } + override fun onResult(result: GetCredentialResponse) { + onResult(Result.success(result)) + } + } + ) } catch (e: GetCredentialException) { Log.e("Error", e.stackTraceToString()) onResult(Result.failure(e)) From 0c69835762bace0c36c68513ae26122745ed0355 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 18 Jan 2024 18:17:59 -0300 Subject: [PATCH 828/888] Refactor CredentialManagerHandler function visibilities --- .../android/login/webauthn/CredentialManagerHandler.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index fcc78277cd3..318ad3d1fd9 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -20,7 +20,7 @@ class CredentialManagerHandler( private val executor = Executors.newSingleThreadExecutor() @RequiresApi(34) - private fun CredentialManager.createPasskey( + fun fetchPasskey( context: Context, requestJson: String, onResult: (Result) -> Unit @@ -34,7 +34,7 @@ class CredentialManagerHandler( val signal = CancellationSignal() try { - getCredentialAsync( + credentialManager.getCredentialAsync( request = getCredRequest, context = context, cancellationSignal = signal, From b24736d891fc8f85aab5e0a2109af07cfe9aca46 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 22 Jan 2024 20:12:55 -0300 Subject: [PATCH 829/888] Migrate menu provider implementation inside SignupConfirmationFragment --- .../android/login/SignupConfirmationFragment.kt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt index 2170189c715..1bbbe7dfc31 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt @@ -13,13 +13,15 @@ import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.AppCompatButton import androidx.appcompat.widget.Toolbar +import androidx.core.view.MenuProvider import androidx.fragment.app.Fragment +import androidx.lifecycle.Lifecycle import dagger.android.support.AndroidSupportInjection import org.wordpress.android.login.util.AvatarHelper.AvatarRequestListener import org.wordpress.android.login.util.AvatarHelper.loadAvatarFromUrl import javax.inject.Inject -class SignupConfirmationFragment : Fragment() { +class SignupConfirmationFragment : Fragment(), MenuProvider { private var mLoginListener: LoginListener? = null private var mEmail: String? = null @@ -76,8 +78,8 @@ class SignupConfirmationFragment : Fragment() { mPhotoUrl = it.getString(ARG_SOCIAL_PHOTO_URL) mService = it.getString(ARG_SOCIAL_SERVICE) } - // TODO: Migrate this to current SDK requirement, this one is deprecated - // setHasOptionsMenu(true) + + requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED) } override fun onCreateView( @@ -130,11 +132,11 @@ class SignupConfirmationFragment : Fragment() { mLoginListener = null } - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + override fun onCreateMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.menu_login, menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { + override fun onMenuItemSelected(item: MenuItem): Boolean { if (item.itemId == R.id.help) { mAnalyticsListener.trackShowHelpClick() if (mLoginListener != null) { From aa03af1b44f06112ea7bc9b38478c36bb570d004 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 22 Jan 2024 22:06:18 -0300 Subject: [PATCH 830/888] Rename PasskeyCredentialsHandler.kt to Fido2ClientHandler --- .../{PasskeyCredentialsHandler.kt => Fido2ClientHandler.kt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename libs/login/src/main/java/org/wordpress/android/login/webauthn/{PasskeyCredentialsHandler.kt => Fido2ClientHandler.kt} (98%) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/Fido2ClientHandler.kt similarity index 98% rename from libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt rename to libs/login/src/main/java/org/wordpress/android/login/webauthn/Fido2ClientHandler.kt index ad92a7dcd85..e19779e5ec1 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyCredentialsHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/Fido2ClientHandler.kt @@ -17,7 +17,7 @@ interface OnPasskeyRequestReadyListener { fun onPasskeyRequestReady(intentSenderRequest: IntentSenderRequest) } -class PasskeyCredentialsHandler( +class Fido2ClientHandler( private val userId: String, private val challengeInfo: WebauthnChallengeInfo ) { From 4a3c601ee3d7ead70e07ad44a4e5bd2d5aa5592a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 22 Jan 2024 22:07:20 -0300 Subject: [PATCH 831/888] Adjust Login2FaFragment to correctly reference the FIDO2 handler --- .../wordpress/android/login/Login2FaFragment.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 64c003e9ac4..b541c2845db 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -46,7 +46,7 @@ import org.wordpress.android.fluxc.store.AccountStore.WebauthnChallengeReceived; import org.wordpress.android.fluxc.store.AccountStore.WebauthnPasskeyAuthenticated; import org.wordpress.android.login.util.SiteUtils; -import org.wordpress.android.login.webauthn.PasskeyCredentialsHandler; +import org.wordpress.android.login.webauthn.Fido2ClientHandler; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; import org.wordpress.android.util.AppLog; @@ -125,7 +125,7 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private boolean mIsSocialLoginConnect; private boolean mSentSmsCode; private List mSupportedAuthTypes; - @Nullable private PasskeyCredentialsHandler mPasskeyCredentialsHandler = null; + @Nullable private Fido2ClientHandler mFido2ClientHandler = null; @Nullable private ActivityResultLauncher mResultLauncher = null; public static Login2FaFragment newInstance(String emailAddress, String password) { @@ -628,11 +628,11 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { handleAuthError(event.error.type, getString(R.string.login_error_security_key)); return; } - mPasskeyCredentialsHandler = new PasskeyCredentialsHandler( + mFido2ClientHandler = new Fido2ClientHandler( event.mUserId, event.mChallengeInfo ); - mPasskeyCredentialsHandler.createIntentSender( + mFido2ClientHandler.createIntentSender( requireContext(), intent -> { if (mResultLauncher != null) { @@ -644,7 +644,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { private void onCredentialsResultAvailable(@NonNull Intent resultData) { if (resultData.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)) { byte[] credentialBytes = resultData.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA); - if (credentialBytes == null || mPasskeyCredentialsHandler == null) { + if (credentialBytes == null || mFido2ClientHandler == null) { handleWebauthnError(); return; } @@ -652,7 +652,7 @@ private void onCredentialsResultAvailable(@NonNull Intent resultData) { PublicKeyCredential credentials = PublicKeyCredential.deserializeFromBytes(credentialBytes); FinishWebauthnChallengePayload payload = - mPasskeyCredentialsHandler.onCredentialsAvailable(credentials); + mFido2ClientHandler.onCredentialsAvailable(credentials); mDispatcher.dispatch( AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(payload)); } From 1663479ff8369cb8a87c5d38d1ccd7d955d2ed08 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 22 Jan 2024 22:07:27 -0300 Subject: [PATCH 832/888] Introduce PasskeyHandler --- .../android/login/webauthn/PasskeyHandler.kt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt new file mode 100644 index 00000000000..4b25b25a32c --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt @@ -0,0 +1,25 @@ +package org.wordpress.android.login.webauthn + +import android.app.Activity +import androidx.activity.result.ActivityResult +import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult +import androidx.fragment.app.Fragment + +class PasskeyHandler { + fun fetch(requestingFragment: Fragment, onResult: (PasskeyDataResult) -> Unit) { + requestingFragment.registerForActivityResult( + StartIntentSenderForResult() + ) + { result: ActivityResult -> + if (result.resultCode == Activity.RESULT_OK && result.data != null) { + onResult(PasskeyDataResult(isFailure = false)) + } else { + onResult(PasskeyDataResult(isFailure = true)) + } + } + } + + data class PasskeyDataResult( + val isFailure: Boolean + ) +} From 8e7610770d08138d56c20280d63bf4fa3bad7627 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 22 Jan 2024 22:20:27 -0300 Subject: [PATCH 833/888] Add FIDO2 handling inside PasskeyHandler --- .../android/login/webauthn/PasskeyHandler.kt | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt index 4b25b25a32c..d0c3fa7081a 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt @@ -1,12 +1,21 @@ package org.wordpress.android.login.webauthn import android.app.Activity +import android.content.Intent import androidx.activity.result.ActivityResult import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult import androidx.fragment.app.Fragment +import com.google.android.gms.fido.Fido +import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential +import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnChallengeInfo class PasskeyHandler { - fun fetch(requestingFragment: Fragment, onResult: (PasskeyDataResult) -> Unit) { + fun fetch( + requestingFragment: Fragment, + userId: String, + challengeInfo: WebauthnChallengeInfo, + onResult: (PasskeyDataResult) -> Unit + ) { requestingFragment.registerForActivityResult( StartIntentSenderForResult() ) @@ -19,7 +28,27 @@ class PasskeyHandler { } } + private fun parseFIDO2IntentData( + resultData: Intent, + userId: String, + challengeInfo: WebauthnChallengeInfo + ): PasskeyDataResult? = + resultData.takeIf { it.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA) } + ?.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA) + ?.let { PublicKeyCredential.deserializeFromBytes(it).toJson() } + ?.let { clientData -> + PasskeyDataResult( + isFailure = false, + userId = userId, + twoStepNonce = challengeInfo.twoStepNonce, + clientData = clientData + ) + } + data class PasskeyDataResult( - val isFailure: Boolean + val isFailure: Boolean, + val userId: String, + val twoStepNonce: String, + val clientData: String ) } From 467296ce7b9fb92e536e25f215cf6d07917eaeb5 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 22 Jan 2024 22:20:57 -0300 Subject: [PATCH 834/888] Add nullability to PasskeyDataResult --- .../org/wordpress/android/login/webauthn/PasskeyHandler.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt index d0c3fa7081a..7fd7ed784d7 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt @@ -47,8 +47,8 @@ class PasskeyHandler { data class PasskeyDataResult( val isFailure: Boolean, - val userId: String, - val twoStepNonce: String, - val clientData: String + val userId: String? = null, + val twoStepNonce: String? = null, + val clientData: String? = null ) } From 6df78008897276a650247f67778457a4098436e9 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 22 Jan 2024 22:22:29 -0300 Subject: [PATCH 835/888] Finish FIDO2 basic handling in PasskeyHandler --- .../android/login/webauthn/PasskeyHandler.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt index 7fd7ed784d7..8636626683d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt @@ -21,7 +21,7 @@ class PasskeyHandler { ) { result: ActivityResult -> if (result.resultCode == Activity.RESULT_OK && result.data != null) { - onResult(PasskeyDataResult(isFailure = false)) + onResult(parseFIDO2IntentData(result.data, userId, challengeInfo)) } else { onResult(PasskeyDataResult(isFailure = true)) } @@ -29,11 +29,12 @@ class PasskeyHandler { } private fun parseFIDO2IntentData( - resultData: Intent, + resultData: Intent?, userId: String, challengeInfo: WebauthnChallengeInfo - ): PasskeyDataResult? = - resultData.takeIf { it.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA) } + ): PasskeyDataResult = + resultData + ?.takeIf { it.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA) } ?.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA) ?.let { PublicKeyCredential.deserializeFromBytes(it).toJson() } ?.let { clientData -> @@ -43,7 +44,7 @@ class PasskeyHandler { twoStepNonce = challengeInfo.twoStepNonce, clientData = clientData ) - } + } ?: PasskeyDataResult(isFailure = true) data class PasskeyDataResult( val isFailure: Boolean, From 8551fdc0a0c6e380b183d38e2ecfcc63825e44ef Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 23 Jan 2024 15:27:28 -0300 Subject: [PATCH 836/888] Correctly handle credential results from Credential Manager --- .../login/webauthn/CredentialManagerHandler.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index 318ad3d1fd9..dfbb8b827ea 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -11,6 +11,7 @@ import androidx.credentials.GetCredentialResponse import androidx.credentials.GetPasswordOption import androidx.credentials.GetPublicKeyCredentialOption import androidx.credentials.exceptions.GetCredentialException +import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload import java.util.concurrent.Executors class CredentialManagerHandler( @@ -21,9 +22,10 @@ class CredentialManagerHandler( @RequiresApi(34) fun fetchPasskey( - context: Context, + userId: String, + twoStepNonce: String, requestJson: String, - onResult: (Result) -> Unit + onResult: (Result) -> Unit ) { val password = GetPasswordOption() val publicKeyCred = GetPublicKeyCredentialOption(requestJson) @@ -45,7 +47,11 @@ class CredentialManagerHandler( } override fun onResult(result: GetCredentialResponse) { - onResult(Result.success(result)) + FinishWebauthnChallengePayload().apply { + mUserId = userId + mTwoStepNonce = twoStepNonce + mClientData = result.toString() + }.let { onResult(Result.success(it)) } } } ) From 86248c2b38a588179376320f447a7320aae217d1 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 23 Jan 2024 15:47:27 -0300 Subject: [PATCH 837/888] Parse result from CredentialManager --- .../login/webauthn/CredentialManagerHandler.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index dfbb8b827ea..71bf94149e8 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -10,6 +10,7 @@ import androidx.credentials.GetCredentialRequest import androidx.credentials.GetCredentialResponse import androidx.credentials.GetPasswordOption import androidx.credentials.GetPublicKeyCredentialOption +import androidx.credentials.PublicKeyCredential import androidx.credentials.exceptions.GetCredentialException import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload import java.util.concurrent.Executors @@ -50,7 +51,7 @@ class CredentialManagerHandler( FinishWebauthnChallengePayload().apply { mUserId = userId mTwoStepNonce = twoStepNonce - mClientData = result.toString() + mClientData = result.toJson().orEmpty() }.let { onResult(Result.success(it)) } } } @@ -60,4 +61,14 @@ class CredentialManagerHandler( onResult(Result.failure(e)) } } + + private fun GetCredentialResponse.toJson(): String? { + return when (val credential = this.credential) { + is PublicKeyCredential -> credential.authenticationResponseJson + else -> { + Log.e("Credential Manager", "Unexpected type of credential") + null + } + } + } } From edae551ec9fa336bdf6be8fb418b451340566682 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 23 Jan 2024 15:53:37 -0300 Subject: [PATCH 838/888] Adjust CredentialManagerHandler to properly connect with Login2FaFragment --- .../android/login/Login2FaFragment.java | 39 ++++++++++++++----- .../webauthn/CredentialManagerHandler.kt | 9 +++-- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index b541c2845db..3bee4956ff0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -3,6 +3,8 @@ import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; @@ -46,6 +48,7 @@ import org.wordpress.android.fluxc.store.AccountStore.WebauthnChallengeReceived; import org.wordpress.android.fluxc.store.AccountStore.WebauthnPasskeyAuthenticated; import org.wordpress.android.login.util.SiteUtils; +import org.wordpress.android.login.webauthn.CredentialManagerHandler; import org.wordpress.android.login.webauthn.Fido2ClientHandler; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; @@ -628,17 +631,33 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { handleAuthError(event.error.type, getString(R.string.login_error_security_key)); return; } - mFido2ClientHandler = new Fido2ClientHandler( - event.mUserId, - event.mChallengeInfo - ); - mFido2ClientHandler.createIntentSender( - requireContext(), - intent -> { - if (mResultLauncher != null) { - mResultLauncher.launch(intent); +// mFido2ClientHandler = new Fido2ClientHandler( +// event.mUserId, +// event.mChallengeInfo +// ); +// mFido2ClientHandler.createIntentSender( +// requireContext(), +// intent -> { +// if (mResultLauncher != null) { +// mResultLauncher.launch(intent); +// } +// }); + CredentialManagerHandler handler = new CredentialManagerHandler(requireContext()); + if (VERSION.SDK_INT >= VERSION_CODES.UPSIDE_DOWN_CAKE) { + handler.fetchPasskey( + event.mUserId, + event.mChallengeInfo.getTwoStepNonce(), + event.mChallengeInfo.getChallenge(), + result -> { + FinishWebauthnChallengePayload payload = result; + return null; + }, + error -> { + handleWebauthnError(); + return null; } - }); + ); + } } private void onCredentialsResultAvailable(@NonNull Intent resultData) { diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index 71bf94149e8..70871e330b5 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -26,7 +26,8 @@ class CredentialManagerHandler( userId: String, twoStepNonce: String, requestJson: String, - onResult: (Result) -> Unit + onSuccess: (FinishWebauthnChallengePayload) -> Unit, + onFailure: (Throwable) -> Unit ) { val password = GetPasswordOption() val publicKeyCred = GetPublicKeyCredentialOption(requestJson) @@ -44,7 +45,7 @@ class CredentialManagerHandler( executor = executor, callback = object : CredentialManagerCallback { override fun onError(e: GetCredentialException) { - onResult(Result.failure(e)) + onFailure(e) } override fun onResult(result: GetCredentialResponse) { @@ -52,13 +53,13 @@ class CredentialManagerHandler( mUserId = userId mTwoStepNonce = twoStepNonce mClientData = result.toJson().orEmpty() - }.let { onResult(Result.success(it)) } + }.let { onSuccess(it) } } } ) } catch (e: GetCredentialException) { Log.e("Error", e.stackTraceToString()) - onResult(Result.failure(e)) + onFailure(e) } } From f3ae6f94a460418aa4bf98ee98c3e5a0ab2f61d2 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 24 Jan 2024 18:25:03 -0300 Subject: [PATCH 839/888] Add API version check to PasskeyHandler --- .../wordpress/android/login/webauthn/PasskeyHandler.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt index 8636626683d..4dbfe16e741 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt @@ -10,12 +10,18 @@ import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnChallengeInfo class PasskeyHandler { - fun fetch( + fun onFragmentCreation( requestingFragment: Fragment, userId: String, challengeInfo: WebauthnChallengeInfo, onResult: (PasskeyDataResult) -> Unit ) { + // run only if API is 34 or above + if (android.os.Build.VERSION.SDK_INT >= 34) { + onResult(PasskeyDataResult(isFailure = true)) + return + } + requestingFragment.registerForActivityResult( StartIntentSenderForResult() ) From fa435c11f59c2bd4782f345dfe517598d15496ea Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 24 Jan 2024 18:25:17 -0300 Subject: [PATCH 840/888] Dispatch challenge payload after interception --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 3bee4956ff0..db104f42899 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -650,6 +650,8 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { event.mChallengeInfo.getChallenge(), result -> { FinishWebauthnChallengePayload payload = result; + mDispatcher.dispatch( + AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(payload)); return null; }, error -> { From 0fff5ccaab6366ca01eb17435f871379e6d72742 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Fri, 26 Jan 2024 13:36:08 -0300 Subject: [PATCH 841/888] Force Credential Manager to run on lower API levels --- .../android/login/Login2FaFragment.java | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index db104f42899..ce14823335c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -1,5 +1,6 @@ package org.wordpress.android.login; +import android.annotation.SuppressLint; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; @@ -623,7 +624,7 @@ private void doAuthWithSecurityKeyAction() { .newStartSecurityKeyChallengeAction(payload)); } - @SuppressWarnings("unused") + @SuppressLint("NewApi") @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { if (event.isError()) { @@ -643,23 +644,21 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { // } // }); CredentialManagerHandler handler = new CredentialManagerHandler(requireContext()); - if (VERSION.SDK_INT >= VERSION_CODES.UPSIDE_DOWN_CAKE) { - handler.fetchPasskey( - event.mUserId, - event.mChallengeInfo.getTwoStepNonce(), - event.mChallengeInfo.getChallenge(), - result -> { - FinishWebauthnChallengePayload payload = result; - mDispatcher.dispatch( - AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(payload)); - return null; - }, - error -> { - handleWebauthnError(); - return null; - } - ); - } + handler.fetchPasskey( + event.mUserId, + event.mChallengeInfo.getTwoStepNonce(), + event.mChallengeInfo.getChallenge(), + result -> { + FinishWebauthnChallengePayload payload = result; + mDispatcher.dispatch( + AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(payload)); + return null; + }, + error -> { + handleWebauthnError(); + return null; + } + ); } private void onCredentialsResultAvailable(@NonNull Intent resultData) { From 964977c0ec9ffca2895ddaa1a3cbebb7ca830070 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Fri, 26 Jan 2024 13:36:59 -0300 Subject: [PATCH 842/888] Adjust unnecessary API check in CredentialManagerHandler --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 - .../wordpress/android/login/webauthn/CredentialManagerHandler.kt | 1 - 2 files changed, 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index ce14823335c..293b921de5c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -624,7 +624,6 @@ private void doAuthWithSecurityKeyAction() { .newStartSecurityKeyChallengeAction(payload)); } - @SuppressLint("NewApi") @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { if (event.isError()) { diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index 70871e330b5..c3d916a5d70 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -21,7 +21,6 @@ class CredentialManagerHandler( private val credentialManager = CredentialManager.create(context) private val executor = Executors.newSingleThreadExecutor() - @RequiresApi(34) fun fetchPasskey( userId: String, twoStepNonce: String, From 2921cd1211699c2c3955a3bdbb52158c125f43ec Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Fri, 26 Jan 2024 13:37:24 -0300 Subject: [PATCH 843/888] Refactor redundant code --- .../java/org/wordpress/android/login/Login2FaFragment.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 293b921de5c..7c5eac0ea35 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -648,9 +648,8 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { event.mChallengeInfo.getTwoStepNonce(), event.mChallengeInfo.getChallenge(), result -> { - FinishWebauthnChallengePayload payload = result; mDispatcher.dispatch( - AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(payload)); + AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(result)); return null; }, error -> { From 995e70783fe87bdae2a6bb3f417e28a20554c99e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Fri, 26 Jan 2024 14:21:59 -0300 Subject: [PATCH 844/888] Fix lint issues --- .../java/org/wordpress/android/login/Login2FaFragment.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 7c5eac0ea35..668bae03ba0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -1,11 +1,8 @@ package org.wordpress.android.login; -import android.annotation.SuppressLint; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; From dbb633dc051f54fbb2d858d83227ab803af9c67e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Sun, 28 Jan 2024 20:30:06 -0300 Subject: [PATCH 845/888] Update Credential Manager with raw JSON data from challenge --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 668bae03ba0..ad9e55f81ad 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -643,7 +643,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { handler.fetchPasskey( event.mUserId, event.mChallengeInfo.getTwoStepNonce(), - event.mChallengeInfo.getChallenge(), + event.mRawChallengeInfoJson, result -> { mDispatcher.dispatch( AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(result)); From 637256ecee670e875ed5b48d1158f9d2e14972e2 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Sun, 28 Jan 2024 22:14:43 -0300 Subject: [PATCH 846/888] Add logs for errors coming from Credential the Manager API --- .../android/login/webauthn/CredentialManagerHandler.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt index c3d916a5d70..ed37104be88 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt @@ -3,7 +3,6 @@ package org.wordpress.android.login.webauthn import android.content.Context import android.os.CancellationSignal import android.util.Log -import androidx.annotation.RequiresApi import androidx.credentials.CredentialManager import androidx.credentials.CredentialManagerCallback import androidx.credentials.GetCredentialRequest @@ -45,6 +44,7 @@ class CredentialManagerHandler( callback = object : CredentialManagerCallback { override fun onError(e: GetCredentialException) { onFailure(e) + Log.e("Credential Manager error", e.stackTraceToString()) } override fun onResult(result: GetCredentialResponse) { @@ -57,7 +57,7 @@ class CredentialManagerHandler( } ) } catch (e: GetCredentialException) { - Log.e("Error", e.stackTraceToString()) + Log.e("Credential Manager error", e.stackTraceToString()) onFailure(e) } } From a115ccc27a77a317bc27b74a42e64f91e089847e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 30 Jan 2024 12:02:44 -0300 Subject: [PATCH 847/888] Refactor CredentialManagerHandler.kt to PasskeyRequest --- .../android/login/Login2FaFragment.java | 23 ++++++----------- ...ialManagerHandler.kt => PasskeyRequest.kt} | 25 ++++++++----------- 2 files changed, 18 insertions(+), 30 deletions(-) rename libs/login/src/main/java/org/wordpress/android/login/webauthn/{CredentialManagerHandler.kt => PasskeyRequest.kt} (85%) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index ad9e55f81ad..9ce2fb3bd84 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -46,7 +46,7 @@ import org.wordpress.android.fluxc.store.AccountStore.WebauthnChallengeReceived; import org.wordpress.android.fluxc.store.AccountStore.WebauthnPasskeyAuthenticated; import org.wordpress.android.login.util.SiteUtils; -import org.wordpress.android.login.webauthn.CredentialManagerHandler; +import org.wordpress.android.login.webauthn.PasskeyRequest; import org.wordpress.android.login.webauthn.Fido2ClientHandler; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; @@ -628,32 +628,23 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { handleAuthError(event.error.type, getString(R.string.login_error_security_key)); return; } -// mFido2ClientHandler = new Fido2ClientHandler( -// event.mUserId, -// event.mChallengeInfo -// ); -// mFido2ClientHandler.createIntentSender( -// requireContext(), -// intent -> { -// if (mResultLauncher != null) { -// mResultLauncher.launch(intent); -// } -// }); - CredentialManagerHandler handler = new CredentialManagerHandler(requireContext()); - handler.fetchPasskey( + + new PasskeyRequest( + requireContext(), event.mUserId, event.mChallengeInfo.getTwoStepNonce(), event.mRawChallengeInfoJson, result -> { mDispatcher.dispatch( - AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(result)); + AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction( + result)); return null; }, error -> { handleWebauthnError(); return null; } - ); + ); } private void onCredentialsResultAvailable(@NonNull Intent resultData) { diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt similarity index 85% rename from libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt rename to libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt index ed37104be88..9244e7af3cf 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/CredentialManagerHandler.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt @@ -14,27 +14,24 @@ import androidx.credentials.exceptions.GetCredentialException import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload import java.util.concurrent.Executors -class CredentialManagerHandler( - private val context: Context +class PasskeyRequest( + context: Context, + userId: String, + twoStepNonce: String, + requestJson: String, + onSuccess: (FinishWebauthnChallengePayload) -> Unit, + onFailure: (Throwable) -> Unit ) { - private val credentialManager = CredentialManager.create(context) - private val executor = Executors.newSingleThreadExecutor() - - fun fetchPasskey( - userId: String, - twoStepNonce: String, - requestJson: String, - onSuccess: (FinishWebauthnChallengePayload) -> Unit, - onFailure: (Throwable) -> Unit - ) { + init { + val credentialManager = CredentialManager.create(context) + val executor = Executors.newSingleThreadExecutor() + val signal = CancellationSignal() val password = GetPasswordOption() val publicKeyCred = GetPublicKeyCredentialOption(requestJson) val getCredRequest = GetCredentialRequest( listOf(password, publicKeyCred) ) - val signal = CancellationSignal() - try { credentialManager.getCredentialAsync( request = getCredRequest, From 6c49a9e59e10e17830d8c6d7e8a55e436c051cd4 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 30 Jan 2024 12:30:37 -0300 Subject: [PATCH 848/888] Refactor PasskeyRequest excessive parameters --- .../android/login/Login2FaFragment.java | 4 +- .../android/login/webauthn/PasskeyRequest.kt | 42 +++++++++---------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 9ce2fb3bd84..d1e0231f9e0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -631,9 +631,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { new PasskeyRequest( requireContext(), - event.mUserId, - event.mChallengeInfo.getTwoStepNonce(), - event.mRawChallengeInfoJson, + event, result -> { mDispatcher.dispatch( AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction( diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt index 9244e7af3cf..63e91bfef4b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt @@ -12,46 +12,44 @@ import androidx.credentials.GetPublicKeyCredentialOption import androidx.credentials.PublicKeyCredential import androidx.credentials.exceptions.GetCredentialException import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload +import org.wordpress.android.fluxc.store.AccountStore.WebauthnChallengeReceived import java.util.concurrent.Executors class PasskeyRequest( context: Context, - userId: String, - twoStepNonce: String, - requestJson: String, + challengeEvent: WebauthnChallengeReceived, onSuccess: (FinishWebauthnChallengePayload) -> Unit, onFailure: (Throwable) -> Unit ) { init { - val credentialManager = CredentialManager.create(context) val executor = Executors.newSingleThreadExecutor() val signal = CancellationSignal() - val password = GetPasswordOption() - val publicKeyCred = GetPublicKeyCredentialOption(requestJson) val getCredRequest = GetCredentialRequest( - listOf(password, publicKeyCred) + listOf(GetPasswordOption(), GetPublicKeyCredentialOption(challengeEvent.mRawChallengeInfoJson)) ) + val passkeyRequestCallback = object : CredentialManagerCallback { + override fun onError(e: GetCredentialException) { + onFailure(e) + Log.e("Credential Manager error", e.stackTraceToString()) + } + + override fun onResult(result: GetCredentialResponse) { + FinishWebauthnChallengePayload().apply { + mUserId = challengeEvent.mUserId + mTwoStepNonce = challengeEvent.mChallengeInfo.twoStepNonce + mClientData = result.toJson().orEmpty() + }.let { onSuccess(it) } + } + } + try { - credentialManager.getCredentialAsync( + CredentialManager.create(context).getCredentialAsync( request = getCredRequest, context = context, cancellationSignal = signal, executor = executor, - callback = object : CredentialManagerCallback { - override fun onError(e: GetCredentialException) { - onFailure(e) - Log.e("Credential Manager error", e.stackTraceToString()) - } - - override fun onResult(result: GetCredentialResponse) { - FinishWebauthnChallengePayload().apply { - mUserId = userId - mTwoStepNonce = twoStepNonce - mClientData = result.toJson().orEmpty() - }.let { onSuccess(it) } - } - } + callback = passkeyRequestCallback ) } catch (e: GetCredentialException) { Log.e("Credential Manager error", e.stackTraceToString()) From d8d681a8d63d17e560db218b6d2598bdf04a469d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 30 Jan 2024 12:39:27 -0300 Subject: [PATCH 849/888] Add log tag into PasskeyRequest --- .../wordpress/android/login/webauthn/PasskeyRequest.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt index 63e91bfef4b..f812554271d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt @@ -31,7 +31,7 @@ class PasskeyRequest( val passkeyRequestCallback = object : CredentialManagerCallback { override fun onError(e: GetCredentialException) { onFailure(e) - Log.e("Credential Manager error", e.stackTraceToString()) + Log.e(TAG, e.stackTraceToString()) } override fun onResult(result: GetCredentialResponse) { @@ -52,7 +52,7 @@ class PasskeyRequest( callback = passkeyRequestCallback ) } catch (e: GetCredentialException) { - Log.e("Credential Manager error", e.stackTraceToString()) + Log.e(TAG, e.stackTraceToString()) onFailure(e) } } @@ -61,9 +61,13 @@ class PasskeyRequest( return when (val credential = this.credential) { is PublicKeyCredential -> credential.authenticationResponseJson else -> { - Log.e("Credential Manager", "Unexpected type of credential") + Log.e(TAG, "Unexpected type of credential") null } } } + + companion object { + const val TAG = "PasskeyRequest" + } } From 5ee08ba05caf45193dedf5adea17b8ddf1e3379e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 30 Jan 2024 12:42:35 -0300 Subject: [PATCH 850/888] Introduce PasskeyRequestData model --- .../wordpress/android/login/Login2FaFragment.java | 9 ++++++++- .../android/login/webauthn/PasskeyRequest.kt | 15 ++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index d1e0231f9e0..15f86c747a3 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -48,6 +48,7 @@ import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.webauthn.PasskeyRequest; import org.wordpress.android.login.webauthn.Fido2ClientHandler; +import org.wordpress.android.login.webauthn.PasskeyRequest.PasskeyRequestData; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; import org.wordpress.android.util.AppLog; @@ -629,9 +630,15 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { return; } + PasskeyRequestData passkeyRequestData = new PasskeyRequestData( + event.mUserId, + event.mChallengeInfo.getTwoStepNonce(), + event.mRawChallengeInfoJson + ); + new PasskeyRequest( requireContext(), - event, + passkeyRequestData, result -> { mDispatcher.dispatch( AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction( diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt index f812554271d..32ec570921d 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt @@ -12,12 +12,11 @@ import androidx.credentials.GetPublicKeyCredentialOption import androidx.credentials.PublicKeyCredential import androidx.credentials.exceptions.GetCredentialException import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload -import org.wordpress.android.fluxc.store.AccountStore.WebauthnChallengeReceived import java.util.concurrent.Executors class PasskeyRequest( context: Context, - challengeEvent: WebauthnChallengeReceived, + requestData: PasskeyRequestData, onSuccess: (FinishWebauthnChallengePayload) -> Unit, onFailure: (Throwable) -> Unit ) { @@ -25,7 +24,7 @@ class PasskeyRequest( val executor = Executors.newSingleThreadExecutor() val signal = CancellationSignal() val getCredRequest = GetCredentialRequest( - listOf(GetPasswordOption(), GetPublicKeyCredentialOption(challengeEvent.mRawChallengeInfoJson)) + listOf(GetPasswordOption(), GetPublicKeyCredentialOption(requestData.requestJson)) ) val passkeyRequestCallback = object : CredentialManagerCallback { @@ -36,8 +35,8 @@ class PasskeyRequest( override fun onResult(result: GetCredentialResponse) { FinishWebauthnChallengePayload().apply { - mUserId = challengeEvent.mUserId - mTwoStepNonce = challengeEvent.mChallengeInfo.twoStepNonce + mUserId = requestData.userId + mTwoStepNonce = requestData.twoStepNonce mClientData = result.toJson().orEmpty() }.let { onSuccess(it) } } @@ -67,6 +66,12 @@ class PasskeyRequest( } } + data class PasskeyRequestData( + val userId: String, + val twoStepNonce: String, + val requestJson: String + ) + companion object { const val TAG = "PasskeyRequest" } From 96d7a201bfb3f7c1166d6cdc1f268feee5c4c7e3 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 31 Jan 2024 19:12:11 -0300 Subject: [PATCH 851/888] Adjust PasskeyRequest construction strategy --- .../wordpress/android/login/webauthn/PasskeyRequest.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt index 32ec570921d..01cad891462 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt @@ -14,7 +14,7 @@ import androidx.credentials.exceptions.GetCredentialException import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload import java.util.concurrent.Executors -class PasskeyRequest( +class PasskeyRequest private constructor( context: Context, requestData: PasskeyRequestData, onSuccess: (FinishWebauthnChallengePayload) -> Unit, @@ -74,5 +74,13 @@ class PasskeyRequest( companion object { const val TAG = "PasskeyRequest" + fun create( + context: Context, + requestData: PasskeyRequestData, + onSuccess: (FinishWebauthnChallengePayload) -> Unit, + onFailure: (Throwable) -> Unit + ) { + PasskeyRequest(context, requestData, onSuccess, onFailure) + } } } From 97d5db5851c97cb728932f835bb90aad6c080f70 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 31 Jan 2024 19:17:32 -0300 Subject: [PATCH 852/888] Adopt static usage of PasskeyRequest --- .../java/org/wordpress/android/login/Login2FaFragment.java | 2 +- .../org/wordpress/android/login/webauthn/PasskeyRequest.kt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 15f86c747a3..14df389354f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -636,7 +636,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { event.mRawChallengeInfoJson ); - new PasskeyRequest( + PasskeyRequest.create( requireContext(), passkeyRequestData, result -> { diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt index 01cad891462..e1df99828e0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt @@ -73,7 +73,9 @@ class PasskeyRequest private constructor( ) companion object { - const val TAG = "PasskeyRequest" + private const val TAG = "PasskeyRequest" + + @JvmStatic fun create( context: Context, requestData: PasskeyRequestData, From b35b46eed981e2f522f14f4ede3d70b4d2c8a716 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 31 Jan 2024 19:18:10 -0300 Subject: [PATCH 853/888] Remove Password argument from CredentialManager request creation --- .../java/org/wordpress/android/login/webauthn/PasskeyRequest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt index e1df99828e0..5032b740b6b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt @@ -24,7 +24,7 @@ class PasskeyRequest private constructor( val executor = Executors.newSingleThreadExecutor() val signal = CancellationSignal() val getCredRequest = GetCredentialRequest( - listOf(GetPasswordOption(), GetPublicKeyCredentialOption(requestData.requestJson)) + listOf(GetPublicKeyCredentialOption(requestData.requestJson)) ) val passkeyRequestCallback = object : CredentialManagerCallback { From 8c9b2d504f51eef8dea8b18a28265e23fb32139c Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 31 Jan 2024 20:00:32 -0300 Subject: [PATCH 854/888] Wrap Credential Manager failure in main thread coroutines call --- .../org/wordpress/android/login/webauthn/PasskeyRequest.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt index 5032b740b6b..21e83e31ba6 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt @@ -11,6 +11,9 @@ import androidx.credentials.GetPasswordOption import androidx.credentials.GetPublicKeyCredentialOption import androidx.credentials.PublicKeyCredential import androidx.credentials.exceptions.GetCredentialException +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload import java.util.concurrent.Executors @@ -29,7 +32,7 @@ class PasskeyRequest private constructor( val passkeyRequestCallback = object : CredentialManagerCallback { override fun onError(e: GetCredentialException) { - onFailure(e) + CoroutineScope(Dispatchers.Main).launch { onFailure(e) } Log.e(TAG, e.stackTraceToString()) } From 00b7f5892a8489fb778af49abbbabb2aba02c9f6 Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Thu, 1 Feb 2024 02:33:05 +0300 Subject: [PATCH 855/888] Fix Smart Lock Login with 2FA issue --- .../login/LoginUsernamePasswordFragment.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java index f8012864bfc..32ba26c091f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginUsernamePasswordFragment.java @@ -30,6 +30,7 @@ import org.wordpress.android.fluxc.store.AccountStore.AuthenticatePayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; +import org.wordpress.android.fluxc.store.AccountStore.OnTwoFactorAuthStarted; import org.wordpress.android.fluxc.store.SiteStore.OnProfileFetched; import org.wordpress.android.fluxc.store.SiteStore.OnSiteChanged; import org.wordpress.android.fluxc.store.SiteStore.RefreshSitesXMLRPCPayload; @@ -504,13 +505,7 @@ private void handleAuthError(AuthenticationErrorType error, XmlRpcErrorType xmlR case INVALID_TOKEN: case AUTHORIZATION_REQUIRED: case NEEDS_2FA: - if (mIsWpcom) { - if (mLoginListener != null) { - mLoginListener.needs2fa(mRequestedUsername, mRequestedPassword); - } - } else { - showError("2FA not supported for self-hosted sites. Please use an app-password."); - } + handle2fa(); break; default: AppLog.e(T.NUX, "Server response: " + errorMessage); @@ -521,8 +516,26 @@ private void handleAuthError(AuthenticationErrorType error, XmlRpcErrorType xmlR } } + private void handle2fa() { + if (mIsWpcom) { + if (mLoginListener != null) { + mLoginListener.needs2fa(mRequestedUsername, mRequestedPassword); + } + } else { + showError("2FA not supported for self-hosted sites. Please use an app-password."); + } + } + // OnChanged events + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onTwoFactorAuthStarted(OnTwoFactorAuthStarted event) { + mLoginStarted = false; + handle2fa(); + endProgress(); + } + @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onAuthenticationChanged(OnAuthenticationChanged event) { From e087ec860c1f78553379234d0e9330e8de12c4e8 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 1 Feb 2024 22:14:11 -0300 Subject: [PATCH 856/888] Remove the PasskeyHandler --- .../android/login/webauthn/PasskeyHandler.kt | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt deleted file mode 100644 index 4dbfe16e741..00000000000 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyHandler.kt +++ /dev/null @@ -1,61 +0,0 @@ -package org.wordpress.android.login.webauthn - -import android.app.Activity -import android.content.Intent -import androidx.activity.result.ActivityResult -import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult -import androidx.fragment.app.Fragment -import com.google.android.gms.fido.Fido -import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential -import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnChallengeInfo - -class PasskeyHandler { - fun onFragmentCreation( - requestingFragment: Fragment, - userId: String, - challengeInfo: WebauthnChallengeInfo, - onResult: (PasskeyDataResult) -> Unit - ) { - // run only if API is 34 or above - if (android.os.Build.VERSION.SDK_INT >= 34) { - onResult(PasskeyDataResult(isFailure = true)) - return - } - - requestingFragment.registerForActivityResult( - StartIntentSenderForResult() - ) - { result: ActivityResult -> - if (result.resultCode == Activity.RESULT_OK && result.data != null) { - onResult(parseFIDO2IntentData(result.data, userId, challengeInfo)) - } else { - onResult(PasskeyDataResult(isFailure = true)) - } - } - } - - private fun parseFIDO2IntentData( - resultData: Intent?, - userId: String, - challengeInfo: WebauthnChallengeInfo - ): PasskeyDataResult = - resultData - ?.takeIf { it.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA) } - ?.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA) - ?.let { PublicKeyCredential.deserializeFromBytes(it).toJson() } - ?.let { clientData -> - PasskeyDataResult( - isFailure = false, - userId = userId, - twoStepNonce = challengeInfo.twoStepNonce, - clientData = clientData - ) - } ?: PasskeyDataResult(isFailure = true) - - data class PasskeyDataResult( - val isFailure: Boolean, - val userId: String? = null, - val twoStepNonce: String? = null, - val clientData: String? = null - ) -} From f2475e22641a2cabb76112f32940f29cb9e8e44a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 1 Feb 2024 22:15:50 -0300 Subject: [PATCH 857/888] Delete FIDO2 usage code --- .../android/login/Login2FaFragment.java | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 14df389354f..dd16d305332 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -127,8 +127,6 @@ public class Login2FaFragment extends LoginBaseFormFragment imple private boolean mIsSocialLoginConnect; private boolean mSentSmsCode; private List mSupportedAuthTypes; - @Nullable private Fido2ClientHandler mFido2ClientHandler = null; - @Nullable private ActivityResultLauncher mResultLauncher = null; public static Login2FaFragment newInstance(String emailAddress, String password) { Login2FaFragment fragment = new Login2FaFragment(); @@ -299,16 +297,6 @@ public void onCreate(Bundle savedInstanceState) { mPhoneNumber = savedInstanceState.getString(KEY_SMS_NUMBER); mSentSmsCode = savedInstanceState.getBoolean(KEY_SMS_SENT); } - - mResultLauncher = - registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(), - result -> { - if (result.getResultCode() == RESULT_OK && result.getData() != null) { - onCredentialsResultAvailable(result.getData()); - } else { - handleWebauthnError(); - } - }); } @Override @@ -652,23 +640,6 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { ); } - private void onCredentialsResultAvailable(@NonNull Intent resultData) { - if (resultData.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)) { - byte[] credentialBytes = resultData.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA); - if (credentialBytes == null || mFido2ClientHandler == null) { - handleWebauthnError(); - return; - } - - PublicKeyCredential credentials = - PublicKeyCredential.deserializeFromBytes(credentialBytes); - FinishWebauthnChallengePayload payload = - mFido2ClientHandler.onCredentialsAvailable(credentials); - mDispatcher.dispatch( - AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(payload)); - } - } - @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyCheckFinished(WebauthnPasskeyAuthenticated event) { From 839a5426af1377f48c9ebf4193b0311c36633404 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 1 Feb 2024 22:15:57 -0300 Subject: [PATCH 858/888] Remove Fido2ClientHandler.kt --- .../login/webauthn/Fido2ClientHandler.kt | 79 ------------------- 1 file changed, 79 deletions(-) delete mode 100644 libs/login/src/main/java/org/wordpress/android/login/webauthn/Fido2ClientHandler.kt diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/Fido2ClientHandler.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/Fido2ClientHandler.kt deleted file mode 100644 index e19779e5ec1..00000000000 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/Fido2ClientHandler.kt +++ /dev/null @@ -1,79 +0,0 @@ -package org.wordpress.android.login.webauthn - -import android.content.Context -import android.util.Base64 -import androidx.activity.result.IntentSenderRequest -import com.google.android.gms.fido.Fido -import com.google.android.gms.fido.common.Transport -import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential -import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialDescriptor -import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions -import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialType.PUBLIC_KEY -import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnChallengeInfo -import org.wordpress.android.fluxc.network.rest.wpcom.auth.webauthn.WebauthnCredentialResponse -import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload - -interface OnPasskeyRequestReadyListener { - fun onPasskeyRequestReady(intentSenderRequest: IntentSenderRequest) -} - -class Fido2ClientHandler( - private val userId: String, - private val challengeInfo: WebauthnChallengeInfo -) { - fun createIntentSender( - context: Context, - listener: OnPasskeyRequestReadyListener - ) { - val options = PublicKeyCredentialRequestOptions.Builder() - .setRpId(challengeInfo.rpId) - .setAllowList(challengeInfo.allowCredentials.map(::parseToCredentialDescriptor)) - .setChallenge(challengeInfo.challenge.decodeBase64()) - .setTimeoutSeconds(challengeInfo.timeout.toDouble()) - .build() - - Fido.getFido2ApiClient(context) - .getSignPendingIntent(options) - .addOnSuccessListener { - val intentSender = IntentSenderRequest - .Builder(it.intentSender) - .build() - - listener.onPasskeyRequestReady(intentSender) - } - } - - fun onCredentialsAvailable(keyCredential: PublicKeyCredential): FinishWebauthnChallengePayload { - return FinishWebauthnChallengePayload().apply { - this.mUserId = userId - this.mTwoStepNonce = challengeInfo.twoStepNonce - this.mClientData = keyCredential.toJson() - } - } - - private fun parseToCredentialDescriptor(credential: WebauthnCredentialResponse) = - PublicKeyCredentialDescriptor( - PUBLIC_KEY.toString(), - credential.id.decodeBase64(), - credential.transports.asParsedTransports() - ) - - private fun String.decodeBase64(): ByteArray { - return Base64.decode(this, Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE) - } - - private fun List.asParsedTransports(): List { - return mapNotNull { - when (it) { - "usb" -> Transport.USB - "nfc" -> Transport.NFC - "ble" -> Transport.BLUETOOTH_LOW_ENERGY - "internal" -> Transport.INTERNAL - "hybrid" -> Transport.HYBRID - else -> null - } - }.ifEmpty { - listOf(Transport.USB, Transport.NFC, Transport.BLUETOOTH_LOW_ENERGY, Transport.HYBRID, Transport.INTERNAL) - } - } -} From 006965c4df24cfd758e671694451c2b54cc072f0 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 1 Feb 2024 22:17:09 -0300 Subject: [PATCH 859/888] Delete FIDO2 library --- libs/login/build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 7fdee9495b4..4bfc5964db5 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -71,8 +71,6 @@ dependencies { implementation "com.github.bumptech.glide:glide:$glideVersion" kapt "com.github.bumptech.glide:compiler:$glideVersion" - implementation "com.google.android.gms:play-services-fido:$fidoVersion" - implementation "androidx.credentials:credentials:$credentialManagerVersion" implementation "androidx.credentials:credentials-play-services-auth:$credentialManagerVersion" From 84f27169722dbec892806445ca5e0cea2e095a42 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 1 Feb 2024 22:17:50 -0300 Subject: [PATCH 860/888] Clear unused imports --- .../java/org/wordpress/android/login/Login2FaFragment.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index dd16d305332..a7ef48f219c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -15,9 +15,6 @@ import android.widget.EditText; import android.widget.TextView; -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.IntentSenderRequest; -import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -26,8 +23,6 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; -import com.google.android.gms.fido.Fido; -import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.greenrobot.eventbus.Subscribe; @@ -36,7 +31,6 @@ import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder; import org.wordpress.android.fluxc.store.AccountStore.AuthenticateTwoFactorPayload; import org.wordpress.android.fluxc.store.AccountStore.AuthenticationErrorType; -import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; import org.wordpress.android.fluxc.store.AccountStore.OnSocialChanged; import org.wordpress.android.fluxc.store.AccountStore.PushSocialAuthPayload; @@ -47,7 +41,6 @@ import org.wordpress.android.fluxc.store.AccountStore.WebauthnPasskeyAuthenticated; import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.webauthn.PasskeyRequest; -import org.wordpress.android.login.webauthn.Fido2ClientHandler; import org.wordpress.android.login.webauthn.PasskeyRequest.PasskeyRequestData; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; From 6a2f6b860eaf8a08932cbc036767740274aee757 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Thu, 1 Feb 2024 22:18:24 -0300 Subject: [PATCH 861/888] Fix checkstyle issues --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index a7ef48f219c..34ce2d8ce38 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -2,7 +2,6 @@ import android.content.ClipboardManager; import android.content.Context; -import android.content.Intent; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; @@ -54,7 +53,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static android.app.Activity.RESULT_OK; import static android.content.Context.CLIPBOARD_SERVICE; import dagger.android.support.AndroidSupportInjection; From d7a1c9535ef6aacd805f4aefeb644771364748f1 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Fri, 2 Feb 2024 17:55:42 -0300 Subject: [PATCH 862/888] Trigger popBackStack when an Passkey error is triggered --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 34ce2d8ce38..c2c610cc0bb 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -626,6 +626,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { }, error -> { handleWebauthnError(); + getParentFragmentManager().popBackStack(); return null; } ); From be669b01efcbb9496c385007caef317a4bfbedf8 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Fri, 2 Feb 2024 17:59:07 -0300 Subject: [PATCH 863/888] Refactor payload creation inside PasskeyRequest --- .../org/wordpress/android/login/Login2FaFragment.java | 5 +---- .../android/login/webauthn/PasskeyRequest.kt | 11 +++++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index c2c610cc0bb..0722d5f0d41 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -619,14 +619,11 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { requireContext(), passkeyRequestData, result -> { - mDispatcher.dispatch( - AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction( - result)); + mDispatcher.dispatch(result); return null; }, error -> { handleWebauthnError(); - getParentFragmentManager().popBackStack(); return null; } ); diff --git a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt index 21e83e31ba6..096a006112c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/webauthn/PasskeyRequest.kt @@ -7,20 +7,21 @@ import androidx.credentials.CredentialManager import androidx.credentials.CredentialManagerCallback import androidx.credentials.GetCredentialRequest import androidx.credentials.GetCredentialResponse -import androidx.credentials.GetPasswordOption import androidx.credentials.GetPublicKeyCredentialOption import androidx.credentials.PublicKeyCredential import androidx.credentials.exceptions.GetCredentialException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.wordpress.android.fluxc.annotations.action.Action +import org.wordpress.android.fluxc.generated.AuthenticationActionBuilder import org.wordpress.android.fluxc.store.AccountStore.FinishWebauthnChallengePayload import java.util.concurrent.Executors class PasskeyRequest private constructor( context: Context, requestData: PasskeyRequestData, - onSuccess: (FinishWebauthnChallengePayload) -> Unit, + onSuccess: (Action) -> Unit, onFailure: (Throwable) -> Unit ) { init { @@ -41,7 +42,9 @@ class PasskeyRequest private constructor( mUserId = requestData.userId mTwoStepNonce = requestData.twoStepNonce mClientData = result.toJson().orEmpty() - }.let { onSuccess(it) } + }.let { + AuthenticationActionBuilder.newFinishSecurityKeyChallengeAction(it) + }.let(onSuccess) } } @@ -82,7 +85,7 @@ class PasskeyRequest private constructor( fun create( context: Context, requestData: PasskeyRequestData, - onSuccess: (FinishWebauthnChallengePayload) -> Unit, + onSuccess: (Action) -> Unit, onFailure: (Throwable) -> Unit ) { PasskeyRequest(context, requestData, onSuccess, onFailure) From 95669008f04304bd74fb5762345f19e7f3387733 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Fri, 2 Feb 2024 17:59:27 -0300 Subject: [PATCH 864/888] Add popBackStack action when the Passkey request fails --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 0722d5f0d41..387fa4b3ca0 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -624,6 +624,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { }, error -> { handleWebauthnError(); + getParentFragmentManager().popBackStack(); return null; } ); From 68c1cf17123fd753edc9af7d12a0b9c325449f20 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 5 Feb 2024 15:09:42 -0300 Subject: [PATCH 865/888] Update LoginListener with security key failed handling --- .../main/java/org/wordpress/android/login/LoginListener.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 25e85e121ec..b04d1d1f16f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -92,4 +92,6 @@ void helpHandleDiscoveryError(String siteAddress, String endpointAddress, String void showSignupMagicLink(String email); void showSignupSocial(String email, String displayName, String idToken, String photoUrl, String service); void showSignupToLoginMessage(); + + void securityKey2FAFailed(); } From dd16b70ab47ae7acc8c28115ee3c597752692200 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 5 Feb 2024 15:10:17 -0300 Subject: [PATCH 866/888] Trigger security key failure during Passkey fetching --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 387fa4b3ca0..d14cc010669 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -624,7 +624,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { }, error -> { handleWebauthnError(); - getParentFragmentManager().popBackStack(); + mLoginListener.securityKey2FAFailed(); return null; } ); From 3d213ba45be6b73227a814cd6b906cbcb3c7f3b2 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Mon, 5 Feb 2024 20:08:44 -0300 Subject: [PATCH 867/888] Add popBackStack back to error handling --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index d14cc010669..055f9bc483b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -625,6 +625,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { error -> { handleWebauthnError(); mLoginListener.securityKey2FAFailed(); + getParentFragmentManager().popBackStack(); return null; } ); From 2bddb1c44163f7e713dc41c46b4b12edba1eb84b Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 6 Feb 2024 18:32:06 -0300 Subject: [PATCH 868/888] migrate PasskeyRequestData to use new webauthn challenge data structure --- .../java/org/wordpress/android/login/Login2FaFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 34ce2d8ce38..90a12bfd61f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -611,8 +611,8 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { PasskeyRequestData passkeyRequestData = new PasskeyRequestData( event.mUserId, - event.mChallengeInfo.getTwoStepNonce(), - event.mRawChallengeInfoJson + event.getWebauthnNonce(), + event.mJsonResponse.toString() ); PasskeyRequest.create( From 8b6a42d773d8bfee6ac8a9ef1d6a4eaf343316e2 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 7 Feb 2024 18:53:12 -0300 Subject: [PATCH 869/888] Remove LoginListener usage for Passkey error and directly call popBackStack --- .../java/org/wordpress/android/login/Login2FaFragment.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index f78c65fe449..7764ee1f44e 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -624,8 +624,6 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { }, error -> { handleWebauthnError(); - mLoginListener.securityKey2FAFailed(); - getParentFragmentManager().popBackStack(); return null; } ); @@ -647,6 +645,7 @@ private void handleWebauthnError() { String errorMessage = getString(R.string.login_error_security_key); endProgress(); handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, errorMessage); + getParentFragmentManager().popBackStack(); } @NonNull private ArrayList handleSupportedAuthTypesParameter( From e7e6896e32a802b3c7525680e27c2fcacaefbf62 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 7 Feb 2024 18:53:27 -0300 Subject: [PATCH 870/888] Remove Security key error function from LoginListener --- .../main/java/org/wordpress/android/login/LoginListener.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index b04d1d1f16f..25e85e121ec 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -92,6 +92,4 @@ void helpHandleDiscoveryError(String siteAddress, String endpointAddress, String void showSignupMagicLink(String email); void showSignupSocial(String email, String displayName, String idToken, String photoUrl, String service); void showSignupToLoginMessage(); - - void securityKey2FAFailed(); } From 94f870f890c0b795b442c0874dac1f9611cdc353 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 7 Feb 2024 19:11:51 -0300 Subject: [PATCH 871/888] Add remaining error handling during webauthn flow --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 7764ee1f44e..221da4b8303 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -606,6 +606,7 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { if (event.isError()) { endProgress(); handleAuthError(event.error.type, getString(R.string.login_error_security_key)); + getParentFragmentManager().popBackStack(); return; } @@ -635,6 +636,7 @@ public void onSecurityKeyCheckFinished(WebauthnPasskeyAuthenticated event) { if (event.isError()) { endProgress(); handleAuthError(event.error.type, getString(R.string.login_error_security_key)); + getParentFragmentManager().popBackStack(); return; } mAnalyticsListener.trackLoginSecurityKeySuccess(); From 560bac8b9c801bf3c90c65f7c7c23e1516102e23 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 7 Feb 2024 19:14:17 -0300 Subject: [PATCH 872/888] Refactor and centralize webauthn error scenario calls --- .../android/login/Login2FaFragment.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 221da4b8303..5fc4ecdbd3b 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -604,9 +604,7 @@ private void doAuthWithSecurityKeyAction() { @Subscribe(threadMode = ThreadMode.MAIN) public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { if (event.isError()) { - endProgress(); - handleAuthError(event.error.type, getString(R.string.login_error_security_key)); - getParentFragmentManager().popBackStack(); + handleWebauthnError(event.error.type, getString(R.string.login_error_security_key)); return; } @@ -624,7 +622,8 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { return null; }, error -> { - handleWebauthnError(); + String errorMessage = getString(R.string.login_error_security_key); + handleWebauthnError(AuthenticationErrorType.WEBAUTHN_FAILED, errorMessage); return null; } ); @@ -634,19 +633,16 @@ public void onWebauthnChallengeReceived(WebauthnChallengeReceived event) { @Subscribe(threadMode = ThreadMode.MAIN) public void onSecurityKeyCheckFinished(WebauthnPasskeyAuthenticated event) { if (event.isError()) { - endProgress(); - handleAuthError(event.error.type, getString(R.string.login_error_security_key)); - getParentFragmentManager().popBackStack(); + handleWebauthnError(event.error.type, getString(R.string.login_error_security_key)); return; } mAnalyticsListener.trackLoginSecurityKeySuccess(); doFinishLogin(); } - private void handleWebauthnError() { - String errorMessage = getString(R.string.login_error_security_key); + private void handleWebauthnError(AuthenticationErrorType errorType, String errorMessage) { endProgress(); - handleAuthError(AuthenticationErrorType.WEBAUTHN_FAILED, errorMessage); + handleAuthError(errorType, errorMessage); getParentFragmentManager().popBackStack(); } From 776321b8f8f385837bde0b713c3f3d1012923172 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 20 Feb 2024 20:10:32 -0300 Subject: [PATCH 873/888] Move `addMenuProvider` from `onCreate` to `onViewCreated` --- .../org/wordpress/android/login/SignupConfirmationFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt index 1bbbe7dfc31..6d07973b1c4 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/SignupConfirmationFragment.kt @@ -78,8 +78,6 @@ class SignupConfirmationFragment : Fragment(), MenuProvider { mPhotoUrl = it.getString(ARG_SOCIAL_PHOTO_URL) mService = it.getString(ARG_SOCIAL_SERVICE) } - - requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED) } override fun onCreateView( @@ -118,6 +116,8 @@ class SignupConfirmationFragment : Fragment(), MenuProvider { if (savedInstanceState == null) { mAnalyticsListener.trackSocialSignupConfirmationViewed() } + + requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED) } @Suppress("DEPRECATION", "OVERRIDE_DEPRECATION") From 8de1ee23f007857b82d5ccc0b4b29f0ea72d3c07 Mon Sep 17 00:00:00 2001 From: Maxime Biais Date: Wed, 3 Apr 2024 18:34:30 +0200 Subject: [PATCH 874/888] Add Gravatar library dependency and use it to replace GravatarUtils that will be removed from WordPress-Utils --- libs/login/build.gradle | 2 ++ .../org/wordpress/android/login/util/AvatarHelper.kt | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 4bfc5964db5..a7348a9e862 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -12,6 +12,7 @@ repositories { includeGroup "org.wordpress" includeGroup "org.wordpress.fluxc" includeGroup "org.wordpress.wellsql" + includeGroup "com.gravatar" } } mavenCentral() @@ -49,6 +50,7 @@ dependencies { implementation ("org.wordpress:utils:$wordpressUtilsVersion") { exclude group: "com.android.volley" } + implementation ("com.gravatar:gravatar:$gravatarSdkVersion") implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" implementation "androidx.vectordrawable:vectordrawable-animated:$androidxVectorDrawableAnimatedVersion" diff --git a/libs/login/src/main/java/org/wordpress/android/login/util/AvatarHelper.kt b/libs/login/src/main/java/org/wordpress/android/login/util/AvatarHelper.kt index f44ad461d0d..2f9b8e28132 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/util/AvatarHelper.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/util/AvatarHelper.kt @@ -9,9 +9,11 @@ import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.Target +import com.gravatar.AvatarQueryOptions +import com.gravatar.AvatarUrl +import com.gravatar.DefaultAvatarOption.Status404 +import com.gravatar.types.Email import org.wordpress.android.login.R -import org.wordpress.android.util.GravatarUtils -import org.wordpress.android.util.GravatarUtils.DefaultImage.STATUS_404 object AvatarHelper { @JvmStatic fun loadAvatarFromEmail( @@ -21,7 +23,8 @@ object AvatarHelper { listener: AvatarRequestListener ) { val avatarSize = fragment.resources.getDimensionPixelSize(R.dimen.avatar_sz_login) - val avatarUrl = GravatarUtils.gravatarFromEmail(email, avatarSize, STATUS_404) + val avatarUrl = email?.let { AvatarUrl(Email(email), + AvatarQueryOptions(preferredSize = avatarSize, defaultAvatarOption = Status404)).url().toString() } loadAvatarFromUrl(fragment, avatarUrl, avatarView, listener) } From 440ed564f091e46cbdecb7a9009e17e7652933be Mon Sep 17 00:00:00 2001 From: Natalia Drause <60236665+NataliaDrause@users.noreply.github.com> Date: Thu, 13 Jun 2024 18:18:53 +0300 Subject: [PATCH 875/888] fix carrot visibility --- libs/login/src/main/res/layout/login_input_row.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/login/src/main/res/layout/login_input_row.xml b/libs/login/src/main/res/layout/login_input_row.xml index 426cdf5c2ab..23f4ced20d4 100644 --- a/libs/login/src/main/res/layout/login_input_row.xml +++ b/libs/login/src/main/res/layout/login_input_row.xml @@ -19,6 +19,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:drawablePadding="10dp" + android:textCursorDrawable="@null" tools:hint="@string/email_address" /> From 3a1c350cf7bd5b7a3b6c5c5e85f3c29e97f61c76 Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Wed, 10 Jul 2024 18:05:54 +0300 Subject: [PATCH 876/888] Override onTimeout() in LoginWpcomService --- .../java/org/wordpress/android/login/LoginWpcomService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java index 8d2f55c7505..445e10f3ba7 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginWpcomService.java @@ -278,6 +278,12 @@ public void onDestroy() { super.onDestroy(); } + @Override + public void onTimeout(int startId) { + super.onTimeout(startId); + setState(LoginStep.FAILURE); // This will cal stopSelf() + } + @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { if (intent == null) { From 55c69cb54fc076da948af94acef8ac7d71e03366 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 12 Aug 2024 17:30:39 +0300 Subject: [PATCH 877/888] Deps: Replace androidx core ktx dependency with plain core Removing the 'androidx.core.ktx' dependency wasn't enough by itself as the dependency graph got updated with dependencies pointing to other versions. Adding the transient 'androidx.core:core' dependency was actually necessary in order to keep the dependency graph unaffected. ------------------------------------------------------------------------ This replacement was suggested by the dependency analysis report, see below: Advice for :WordPressLoginFlow Unused dependencies which should be removed: implementation 'androidx.core:core-ktx:1.12.0' ... These transitive dependencies should be declared directly: api 'androidx.core:core:1.12.0' ... --- libs/login/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index a7348a9e862..21917b41503 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -61,7 +61,7 @@ dependencies { implementation "androidx.constraintlayout:constraintlayout:$androidxConstraintLayoutVersion" implementation "com.google.android.material:material:$materialVersion" - implementation "androidx.core:core-ktx:$androidxCoreVersion" + implementation "androidx.core:core:$androidxCoreVersion" api "com.google.android.gms:play-services-auth:$playServicesAuthVersion" From 7def45617f0763ebf31133cf82ee9ce494a83a99 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 12 Aug 2024 17:36:48 +0300 Subject: [PATCH 878/888] Deps: Remove androidx gridlayout dependency This dependency is completely unused. FYI: It got introduced as part of this (82f8eaf2693e7b28b47b8adcfd9e7d83eeaf0e3f) commit, which updated the support libs to a newer version (not sure why). ------------------------------------------------------------------------ This removal was suggested by the dependency analysis report, see below: Advice for :WordPressLoginFlow Unused dependencies which should be removed: implementation 'androidx.gridlayout:gridlayout:1.0.0' ... --- libs/login/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 21917b41503..68b80126d03 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -56,7 +56,6 @@ dependencies { implementation "androidx.vectordrawable:vectordrawable-animated:$androidxVectorDrawableAnimatedVersion" implementation "androidx.media:media:$androidxMediaVersion" implementation "androidx.legacy:legacy-support-v13:$androidxLegacySupportV13Version" - implementation "androidx.gridlayout:gridlayout:$androidxGlidLayoutVersion" implementation "androidx.constraintlayout:constraintlayout:$androidxConstraintLayoutVersion" implementation "com.google.android.material:material:$materialVersion" From b3919d82d166bcd5ee521b82861e39917c66e139 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 12 Aug 2024 17:41:26 +0300 Subject: [PATCH 879/888] Deps: Remove androidx legacy support v13 dependency This dependency is completely unused. FYI: It got introduced as part of this (252d89f522875b911c5eb97b1c1a68bc3d2f4423) commit, a part of the AndroidX migration (not sure why). ------------------------------------------------------------------------ This removal was suggested by the dependency analysis report, see below: Advice for :WordPressLoginFlow Unused dependencies which should be removed: implementation 'androidx.legacy:legacy-support-v13:1.0.0' ... --- libs/login/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 68b80126d03..c7a8d52b9db 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -55,7 +55,6 @@ dependencies { implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" implementation "androidx.vectordrawable:vectordrawable-animated:$androidxVectorDrawableAnimatedVersion" implementation "androidx.media:media:$androidxMediaVersion" - implementation "androidx.legacy:legacy-support-v13:$androidxLegacySupportV13Version" implementation "androidx.constraintlayout:constraintlayout:$androidxConstraintLayoutVersion" implementation "com.google.android.material:material:$materialVersion" From e6bb41a9dcfd9d7b15a6cc89119078f262d1afb5 Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 12 Aug 2024 17:45:26 +0300 Subject: [PATCH 880/888] Deps: Remove androidx media dependency This dependency is completely unused. FYI: It got introduced as part of this (82f8eaf2693e7b28b47b8adcfd9e7d83eeaf0e3f and then 252d89f522875b911c5eb97b1c1a68bc3d2f4423 and) commits, first an update to the support libs to a newer version and then as part of the AndroidX migration (not sure why). ------------------------------------------------------------------------ This removal was suggested by the dependency analysis report, see below: Advice for :WordPressLoginFlow Unused dependencies which should be removed: implementation 'androidx.media:media:1.2.1' ... --- libs/login/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index c7a8d52b9db..e94ec1f32c3 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -54,7 +54,6 @@ dependencies { implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" implementation "androidx.vectordrawable:vectordrawable-animated:$androidxVectorDrawableAnimatedVersion" - implementation "androidx.media:media:$androidxMediaVersion" implementation "androidx.constraintlayout:constraintlayout:$androidxConstraintLayoutVersion" implementation "com.google.android.material:material:$materialVersion" From 16b89608e3611805727df1a4a180eaa6f975520d Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 12 Aug 2024 17:53:35 +0300 Subject: [PATCH 881/888] Build: Remove unnecessary vector drawables use support library config Since the 'minSdkVersion' of this project is currently on '24' this vector drawables backward compatibility solution is no longer required. As such, this config is unnecessary and can be now safely removed. For more info see: - Vector drawables backward compatibility solution (Doc): https://developer.android.com/develop/ui/views/graphics/ vector-drawable-resources#vector-drawables-backward-solution - androidx.vectordrawable.graphics.drawable.VectorDrawableCompat (Doc): https://developer.android.com/reference/androidx/vectordrawable/ graphics/drawable/VectorDrawableCompat --- libs/login/build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index e94ec1f32c3..46c3ff9c37e 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -38,8 +38,6 @@ android { defaultConfig { minSdkVersion rootProject.minSdkVersion targetSdkVersion rootProject.targetSdkVersion - - vectorDrawables.useSupportLibrary = true } buildFeatures { buildConfig true From 558de981dd9e8ffb6dc872e2fdb49a1bdd5aaaca Mon Sep 17 00:00:00 2001 From: Petros Paraskevopoulos Date: Mon, 12 Aug 2024 17:56:34 +0300 Subject: [PATCH 882/888] Deps: Remove androidx vectordrawable animated dependency This dependency is completely unused. FYI: It got introduced as part of this (82f8eaf2693e7b28b47b8adcfd9e7d83eeaf0e3f) commit, which updated the support libs to a newer version (not sure why). ------------------------------------------------------------------------ This removal was suggested by the dependency analysis report, see below: Advice for :WordPressLoginFlow Unused dependencies which should be removed: implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0' --- libs/login/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/build.gradle b/libs/login/build.gradle index 46c3ff9c37e..21309a637ec 100644 --- a/libs/login/build.gradle +++ b/libs/login/build.gradle @@ -51,7 +51,6 @@ dependencies { implementation ("com.gravatar:gravatar:$gravatarSdkVersion") implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" - implementation "androidx.vectordrawable:vectordrawable-animated:$androidxVectorDrawableAnimatedVersion" implementation "androidx.constraintlayout:constraintlayout:$androidxConstraintLayoutVersion" implementation "com.google.android.material:material:$materialVersion" From 2058d9743c580e452106ff87b932387cf2dfc930 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Tue, 13 Aug 2024 17:08:37 +0100 Subject: [PATCH 883/888] Show the SMS button when no auth types are provided --- .../org/wordpress/android/login/Login2FaFragment.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index 5fc4ecdbd3b..cda982c77de 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -1,5 +1,7 @@ package org.wordpress.android.login; +import static android.content.Context.CLIPBOARD_SERVICE; + import android.content.ClipboardManager; import android.content.Context; import android.os.Bundle; @@ -53,8 +55,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static android.content.Context.CLIPBOARD_SERVICE; - import dagger.android.support.AndroidSupportInjection; public class Login2FaFragment extends LoginBaseFormFragment implements TextWatcher, @@ -208,7 +208,9 @@ protected void setupContent(ViewGroup rootView) { // restrict the allowed input chars to just numbers m2FaInput.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789")); - boolean isSmsEnabled = mSupportedAuthTypes.contains(SupportedAuthTypes.PUSH); + // If we didn't get a list of supported auth types, then the flow is not using webauthn, + // We should treat it as if SMS is enabled for the user + boolean isSmsEnabled = mSupportedAuthTypes.isEmpty() || mSupportedAuthTypes.contains(SupportedAuthTypes.PUSH); mOtpButton = rootView.findViewById(R.id.login_otp_button); mOtpButton.setVisibility(isSmsEnabled ? View.VISIBLE : View.GONE); mOtpButton.setText(mSentSmsCode ? R.string.login_text_otp_another : R.string.login_text_otp); From 7d85541693a51e66a80120b066b13771da47fa12 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Thu, 15 Aug 2024 10:29:32 +0100 Subject: [PATCH 884/888] Remove unused variable --- .../main/java/org/wordpress/android/login/Login2FaFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java index cda982c77de..f35e4e8c2f9 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/Login2FaFragment.java @@ -132,7 +132,6 @@ public static Login2FaFragment newInstance(String emailAddress, String password, String userId, String webauthnNonce, String authenticatorNonce, String backupNonce, String smsNonce, List authTypes) { - boolean supportsWebauthn = webauthnNonce != null && !webauthnNonce.isEmpty(); Login2FaFragment fragment = new Login2FaFragment(); Bundle args = new Bundle(); args.putString(ARG_EMAIL_ADDRESS, emailAddress); From 44f234dab48ae79a2129e1d76bacb876c5744614 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Mon, 14 Oct 2024 14:23:21 +0100 Subject: [PATCH 885/888] Introduce a new listener function to pass the connect/site-info result --- .../wordpress/android/login/ConnectSiteInfoResult.kt | 11 +++++++++++ .../org/wordpress/android/login/LoginListener.java | 6 +++++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 libs/login/src/main/java/org/wordpress/android/login/ConnectSiteInfoResult.kt diff --git a/libs/login/src/main/java/org/wordpress/android/login/ConnectSiteInfoResult.kt b/libs/login/src/main/java/org/wordpress/android/login/ConnectSiteInfoResult.kt new file mode 100644 index 00000000000..086f5d2d828 --- /dev/null +++ b/libs/login/src/main/java/org/wordpress/android/login/ConnectSiteInfoResult.kt @@ -0,0 +1,11 @@ +package org.wordpress.android.login + +data class ConnectSiteInfoResult @JvmOverloads constructor( + val url: String, + val urlAfterRedirects: String, + val hasJetpack: Boolean, + /** + * Whether the site is suspended on WordPress.com and can't be connected using Jetpack + */ + val isWPComSuspended: Boolean = false, +) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java index 25e85e121ec..9964353730c 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginListener.java @@ -61,7 +61,11 @@ void needs2faSocial(String email, String userId, String nonceAuthenticator, Stri // Login Site Address input callbacks void alreadyLoggedInWpcom(ArrayList oldSitesIds); void gotWpcomSiteInfo(String siteAddress); - void gotConnectedSiteInfo(@NonNull String siteAddress, @Nullable String redirectUrl, boolean hasJetpack); + default void gotConnectSiteInfo(@NonNull ConnectSiteInfoResult result) { + gotConnectedSiteInfo(result.getUrl(), result.getUrlAfterRedirects(), result.getHasJetpack()); + } + + default void gotConnectedSiteInfo(@NonNull String siteAddress, @Nullable String redirectUrl, boolean hasJetpack) { } void gotXmlRpcEndpoint(String inputSiteAddress, String endpointAddress); void handleSslCertificateError(MemorizingTrustManager memorizingTrustManager, SelfSignedSSLCallback callback); void helpSiteAddress(String url); From f32d9926748c2f246ec5b725e4a3f3259bedbc60 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Mon, 14 Oct 2024 14:23:57 +0100 Subject: [PATCH 886/888] Update site address logic to handle suspended websites for Woo login --- .../login/LoginSiteAddressFragment.java | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index 8d99ea6b837..c4c8171109f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -32,6 +32,7 @@ import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.SiteStore.ConnectSiteInfoPayload; import org.wordpress.android.fluxc.store.SiteStore.OnConnectSiteInfoChecked; +import org.wordpress.android.fluxc.store.SiteStore.SiteErrorType; import org.wordpress.android.login.util.SiteUtils; import org.wordpress.android.login.widgets.WPLoginInputRow; import org.wordpress.android.login.widgets.WPLoginInputRow.OnEditorCommitListener; @@ -340,11 +341,13 @@ public void handleDiscoverySuccess(@NonNull String endpointAddress) { String inputSiteAddress = mRequestedSiteAddress; endProgress(); if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { - mLoginListener.gotConnectedSiteInfo( - mConnectSiteInfoUrl, - mConnectSiteInfoUrlRedirect, - mConnectSiteInfoCalculatedHasJetpack - ); + mLoginListener.gotConnectSiteInfo( + new ConnectSiteInfoResult( + mConnectSiteInfoUrl, + mConnectSiteInfoUrlRedirect, + mConnectSiteInfoCalculatedHasJetpack + ) + ); } else { mLoginListener.gotXmlRpcEndpoint(inputSiteAddress, endpointAddress); } @@ -397,13 +400,26 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { event.error.type.name(), event.error.message); - AppLog.e(T.API, "onFetchedConnectSiteInfo has error: " + event.error.message); - if (NetworkUtils.isNetworkAvailable(requireContext())) { - showError(R.string.invalid_site_url_message); + if (event.error.type == SiteErrorType.WPCOM_SITE_SUSPENDED + && mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { + // the site is WPCom suspended, we should treat it as non-Jetpack site + mConnectSiteInfoCalculatedHasJetpack = false; + mLoginListener.gotConnectSiteInfo( + new ConnectSiteInfoResult( + mRequestedSiteAddress, + mRequestedSiteAddress, + mConnectSiteInfoCalculatedHasJetpack, + true + ) + ); } else { - showError(R.string.error_generic_network); + AppLog.e(T.API, "onFetchedConnectSiteInfo has error: " + event.error.message); + if (NetworkUtils.isNetworkAvailable(requireContext())) { + showError(R.string.invalid_site_url_message); + } else { + showError(R.string.error_generic_network); + } } - endProgressIfNeeded(); } else { boolean hasJetpack = calculateHasJetpack(event.info); @@ -433,10 +449,12 @@ private void handleConnectSiteInfoForWoo(ConnectSiteInfoPayload siteInfo) { mLoginListener.handleSiteAddressError(siteInfo); } else { endProgressIfNeeded(); - mLoginListener.gotConnectedSiteInfo( - mConnectSiteInfoUrl, - mConnectSiteInfoUrlRedirect, - mConnectSiteInfoCalculatedHasJetpack + mLoginListener.gotConnectSiteInfo( + new ConnectSiteInfoResult( + mConnectSiteInfoUrl, + mConnectSiteInfoUrlRedirect, + mConnectSiteInfoCalculatedHasJetpack + ) ); } } From 548dbe6255b925ef47ceb125b04afcb6c4bb2f6b Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Mon, 14 Oct 2024 14:24:25 +0100 Subject: [PATCH 887/888] Code cleanup In Woo, XMLRPC discovery is not used anymore, so the code removed here wasn't used --- .../android/login/LoginSiteAddressFragment.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index c4c8171109f..582c33ceeca 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -340,17 +340,7 @@ public void handleDiscoverySuccess(@NonNull String endpointAddress) { // hold the URL in a variable to use below otherwise it gets cleared up by endProgress String inputSiteAddress = mRequestedSiteAddress; endProgress(); - if (mLoginListener.getLoginMode() == LoginMode.WOO_LOGIN_MODE) { - mLoginListener.gotConnectSiteInfo( - new ConnectSiteInfoResult( - mConnectSiteInfoUrl, - mConnectSiteInfoUrlRedirect, - mConnectSiteInfoCalculatedHasJetpack - ) - ); - } else { - mLoginListener.gotXmlRpcEndpoint(inputSiteAddress, endpointAddress); - } + mLoginListener.gotXmlRpcEndpoint(inputSiteAddress, endpointAddress); } private void askForHttpAuthCredentials(@NonNull final String url, int messageId) { From fa45edda8798f0ae042b9478af445362af7457b0 Mon Sep 17 00:00:00 2001 From: Hicham Boushaba Date: Mon, 14 Oct 2024 14:45:31 +0100 Subject: [PATCH 888/888] Make urlAfterRedirects nullable --- .../java/org/wordpress/android/login/ConnectSiteInfoResult.kt | 2 +- .../org/wordpress/android/login/LoginSiteAddressFragment.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/login/src/main/java/org/wordpress/android/login/ConnectSiteInfoResult.kt b/libs/login/src/main/java/org/wordpress/android/login/ConnectSiteInfoResult.kt index 086f5d2d828..a0ab4a7c0eb 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/ConnectSiteInfoResult.kt +++ b/libs/login/src/main/java/org/wordpress/android/login/ConnectSiteInfoResult.kt @@ -2,7 +2,7 @@ package org.wordpress.android.login data class ConnectSiteInfoResult @JvmOverloads constructor( val url: String, - val urlAfterRedirects: String, + val urlAfterRedirects: String?, val hasJetpack: Boolean, /** * Whether the site is suspended on WordPress.com and can't be connected using Jetpack diff --git a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java index 582c33ceeca..764c5e4159f 100644 --- a/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java +++ b/libs/login/src/main/java/org/wordpress/android/login/LoginSiteAddressFragment.java @@ -397,7 +397,7 @@ public void onFetchedConnectSiteInfo(OnConnectSiteInfoChecked event) { mLoginListener.gotConnectSiteInfo( new ConnectSiteInfoResult( mRequestedSiteAddress, - mRequestedSiteAddress, + null, mConnectSiteInfoCalculatedHasJetpack, true )