Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite phone auth with new architecture and finalize progress revamp #1253

Merged
merged 19 commits into from
May 31, 2018
Merged

Rewrite phone auth with new architecture and finalize progress revamp #1253

merged 19 commits into from
May 31, 2018

Conversation

SUPERCILEX
Copy link
Collaborator

This is it! Half a year later and we're almost done! 👏🍾🎉

Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
@samtstern
Copy link
Contributor

Not gonna look at this yet but +604 -1406 !!!!

@samtstern samtstern changed the base branch from version-3.3.1-dev to version-3.4.0-dev April 16, 2018 16:59
@samtstern samtstern changed the base branch from version-3.4.0-dev to version-4.0.0-dev May 4, 2018 17:24
SUPERCILEX added 5 commits May 4, 2018 22:34
…rewrite

# Conflicts:
#	auth/src/main/java/com/firebase/ui/auth/data/remote/TwitterSignInHandler.java
#	auth/src/main/java/com/firebase/ui/auth/ui/phone/VerifyPhoneNumberFragment.java
#	auth/src/test/java/com/firebase/ui/auth/ui/phone/PhoneActivityTest.java
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
@SUPERCILEX SUPERCILEX changed the title [WIP] Rewrite phone auth with new architecture Rewrite phone auth with new architecture May 5, 2018
@SUPERCILEX
Copy link
Collaborator Author

SUPERCILEX commented May 6, 2018

@samtstern Alrighty, this one is ready for review! Gonna take a look a your PR next.

Some notes about this PR:

  • Because of how the verification callbacks are implemented, I couldn't avoid some ugliness. Maybe you'll have some ideas, but the best I could come up with is a shared view model that's bound to the activity. As a side effect, our error states are propagated from the activity down to the correct fragment which seems weird to me. 🤷‍♂️
  • I dunno what you've done in the progress dialog PR since I haven't looked at it yet, but I've taken the liberty of killing the completable progress dialog since it doesn't add value IMO. We could literally add a check with a delay to all of our progress dialogs, but we aren't in a sci-fi movie where you need "Access granted" visuals. 😂🛰
  • I nuked those alert dialogs in favor of inlined errors in the TextInputLayout. 😌

@samtstern
Copy link
Contributor

@SUPERCILEX excited to review this one! But I've come down with a really strong case of I/O fever, so if I get to this at all this week it will be on Friday. Sorry and appreciate the effort / patience!

<string name="fui_error_too_many_attempts">Este número de teléfono se usó demasiadas veces</string>
<string name="fui_error_quota_exceeded">Ocurrió un problema durante la verificación de tu número de teléfono</string>
<string name="fui_error_session_expired">Este código ya no es válido</string>
<string name="fui_sign_in_with_phone_number">Acceder con el número de teléfono</string>
<string name="fui_done">Listo</string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely a highly annoying request, but could we split out the string removals into another PR? That way this one doesn't have 177 files changed and thousands of lines. I don't want an important behavioral change to get lost among all of this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not at all, I thought you might ask so I removed all the strings in one easily rebasable commit. 👍

Copy link
Contributor

@samtstern samtstern left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some brief comments.

@@ -127,6 +129,16 @@ private void redirectSignIn(String provider, String email) {
EmailActivity.createIntent(getApplication(), getArguments(), email),
RequestCodes.EMAIL_FLOW)));
break;
case PhoneAuthProvider.PROVIDER_ID:
Bundle args = new Bundle();
args.putString(ExtraConstants.PHONE, email);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we rename the email arg to identifier or something? Seems strange to see put(PHONE, email)

@@ -70,10 +67,6 @@ public FlowParameters getFlowParams() {
return mParams;
}

public AuthHelper getAuthHelper() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the helper activity doesn't even have a helper! Love seeing this class die haha.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, that was the first class to die when I started the refactor—it killed me when I had to add it back for the staged PRs. 😆

nationalNumber = params.getString(ExtraConstants.NATIONAL_NUMBER);
}

if (!TextUtils.isEmpty(countryIso) && !TextUtils.isEmpty(nationalNumber)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This block is pretty much the heart of the decision making here so I think a comment or two would be good, especially for the final elseif block.

mPhoneEditText.setSelection(number.getPhoneNumber().length());
}
if (PhoneNumber.isCountryValid(number)) {
setCountryCode(number);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If isCountryValid is true but isValid is false then it looks like we'll call onNext() with a situation that will cause getPseudoValidPhoneNumber() to return null and then put an error on screen.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, you're right.

mPhoneNumber = savedInstanceState.getString(KEY_VERIFICATION_PHONE);
final PhoneProviderResponseHandler handler =
ViewModelProviders.of(this).get(PhoneProviderResponseHandler.class);
handler.init(getFlowParams());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: name this something more specific than handler? When it's used inside of verificationHandler it gets a bit confusing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed verificationHandler to phoneVerifier.

protected void onSuccess(@NonNull PhoneAuthCredential credential) {
handler.startSignIn(credential, new IdpResponse.Builder(
new User.Builder(PhoneAuthProvider.PROVIDER_ID, null)
.setPhoneNumber(getPhoneNumber())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok looking at the two methods where we do fragment detection, getErrorView() and getPhoneNumber(), that's where we both agree we could improve.

Here I see that we use getPhoneNumber() in the verification handler to kick off the other handler.

What's the original reason why this flow benefits from being a multi-Fragment activity rather than a series of activities? Would that help cut down on the patterns we don't like?

Copy link
Collaborator Author

@SUPERCILEX SUPERCILEX May 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You actually just gave me a different idea here: I made the phone number pass through the verification view model—not sure why I didn't think of that before. 🤦‍♂️ It still doesn't address the error view thing though, but that's not as bad as the phone number bit IMO.

As for activities, I'm not sure how they would be solving our problem... they would make it harder to talk between them since we'd be relying on a bunch of bundles. Whad'ya think of bfb3b22? It's certainly an improvement over the current PhoneActivity! 😆

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks better to me!

SUPERCILEX added 4 commits May 7, 2018 20:37
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
}

private void start(PhoneNumber number) {
if (PhoneNumber.isValid(number)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: nornmally I think this pattern is clearer:

if (bad condition) {
  //  ...
  return;
}

// Good condition....

Less indentation and survives future editing better.


import com.firebase.ui.auth.R;

public final class CompletableProgressDialog extends DialogFragment {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am all for killing this dialog, but we should preserve the UX that it was meant to provide. This special "checkmark progress dialog" thing came from UX studies that the former Digits team did.

In the situation where the phone number is auto-verified or the SMS is auto-retrieved, it can be opaque to the user why they were signed in without any action.

So we need to handle each of those two cases in the UI specifically.

}

private void onCodeSent() {
completeLoadingDialog(getString(R.string.fui_code_sent));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is part of the same comment from above, making sure that even when things happen really quickly the user has a chance to notice each step of phone auth.

new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onVerificationCompleted(@NonNull PhoneAuthCredential credential) {
setResult(Resource.forSuccess(Pair.create(number, credential)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the case where retrieval happened without any user interaction. Any ideas for how we can send a special signal to the UI and what it should look like?

/**
* Activity to control the entire phone verification flow. Plays host to {@link
* VerifyPhoneNumberFragment} and {@link SubmitConfirmationCodeFragment}
* CheckPhoneNumberFragment} and {@link SubmitConfirmationCodeFragment}
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class PhoneActivity extends AppCompatBase {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this text-free dialog that flickers into and out of existence at the start of the flow?
https://drive.google.com/file/d/1DifkJhYY8iPVGW2AWgTnc0muPyFPWsPf/view

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That one isn't my fault, it's the Smart Lock dialog. 🤷‍♂️ Not much we can do there.

mSubmitConfirmationButton = view.findViewById(R.id.submit_confirmation_code);

getActivity().setTitle(getString(R.string.fui_verify_your_phone_title));
mCountdown.run();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be mHandler.postRunnable(mCountDown()) instead?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@samtstern
Copy link
Contributor

samtstern commented May 17, 2018

@SUPERCILEX do you think you can address the UX concerns and all other remaining issues in time for 4.0.0 (deadline for code complete 5/22 right now) or would you like to punt this to a 4.0.1 release?

Also if there are any translations needed for this and you're shooting for 4.0.0 we should get the strings finalized and send them off ASAP.

@SUPERCILEX
Copy link
Collaborator Author

@samtstern yeah, probably not going to get this done in time so 4.0.1 it is. (Unless I beat the tos translations and you have time to review—again, not likely. 😂)

@samtstern samtstern added this to the 4.0.1 milestone May 18, 2018
@SUPERCILEX SUPERCILEX changed the base branch from version-4.0.0-dev to version-4.1.0-dev May 29, 2018 00:00
# Conflicts:
#	auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java
#	auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java
#	auth/src/main/java/com/firebase/ui/auth/ui/phone/CompletableProgressDialog.java
#	auth/src/main/java/com/firebase/ui/auth/ui/phone/PhoneActivity.java
#	auth/src/main/java/com/firebase/ui/auth/ui/phone/SubmitConfirmationCodeFragment.java
#	auth/src/main/java/com/firebase/ui/auth/ui/phone/VerifyPhoneNumberFragment.java
#	auth/src/main/java/com/firebase/ui/auth/util/ui/PreambleHandler.java
#	auth/src/main/res/layout/fui_phone_progress_dialog.xml
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
protected void onSuccess(@NonNull PhoneVerification verification) {
if (verification.isAutoVerified()) {
Toast.makeText(
PhoneActivity.this, R.string.fui_verified, Toast.LENGTH_LONG).show();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this address your auto verified concerns?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about a Snackbar? Or are we using Toast since it will last across the UI transition?

Copy link
Contributor

@samtstern samtstern May 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh also I just went through and tried this, I think we should extend the fui_verified message to be something like "Phone number automatically verified"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm using a Toast since the UI will disappear too fast. And good point about the string, I'll rename it to fui_auto_verified too to minimize translation confusion.

@SUPERCILEX SUPERCILEX changed the title Rewrite phone auth with new architecture Rewrite phone auth with new architecture and finalize progress revamp May 29, 2018
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Copy link
Contributor

@samtstern samtstern left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks mostly good!

Btw not sure if you saw this but it's now pretty easy to test all the different branches of this flow:
https://firebase.google.com/docs/auth/android/phone-auth#integration-testing

@@ -97,15 +74,13 @@ public void startSaveCredentials(

@Override
public void showProgress(@StringRes int message) {
getDialogHolder().showLoadingDialog(message);
throw new UnsupportedOperationException(
"Either a fragment or activity must handle progress updates.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just make these two methods abstract then if we want to force the subclass to implement them?

I think what you're trying to do is not allow events to bubble up from fragments but maybe then we should remove the default behavior from the fragment?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, I thought we still had some fragments that forwarded progress updates to the activity, but I guess the was in the ProgressDialog world. Everything is abstract now. 👍

countryIso,
String.valueOf(PhoneNumberUtils.getCountryCode(countryIso))));
} else if (getFlowParams().enableHints) {
FlowUtils.unhandled(this, new PendingIntentRequiredException(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a strange patter: we're faking a PendingIntentRequiredException just to launch the hint picker. Should we instead bubble up some event that will allow this to be fired from the ViewModel as normal?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'm even using mHandler.getApplication() for the context so I must have forgotten this bit sometime while refactoring. 😊

protected void onSuccess(@NonNull PhoneVerification verification) {
if (verification.isAutoVerified()) {
Toast.makeText(
PhoneActivity.this, R.string.fui_verified, Toast.LENGTH_LONG).show();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about a Snackbar? Or are we using Toast since it will last across the UI transition?

@Override
protected void onFailure(@NonNull Exception e) {
if (e instanceof PhoneNumberVerificationRequiredException) {
// Ignore if resending verification code
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add some more explanation for how this comment relates to the code below?

}
@Override
public void showProgress(int message) {
FragmentBase fragment = (CheckPhoneNumberFragment)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we DRY up the first few lines from showProgress and hideProgress into some getActiveFragment method or something?

Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
@samtstern
Copy link
Contributor

samtstern commented May 30, 2018

@SUPERCILEX nice! This looks good to me once the conflicts are gone.

I think for 4.0.1 we can try and fit in this one, plus #1324. Then release and focus on 4.1.0.

…rewrite

# Conflicts:
#	auth/src/main/java/com/firebase/ui/auth/util/ui/PreambleHandler.java
@SUPERCILEX
Copy link
Collaborator Author

@samtstern SGTM, though I had already merged from 4.1 dev. Do you want me to try and rebase those changes out to target 4.0.1?

@samtstern
Copy link
Contributor

samtstern commented May 31, 2018 via email

@samtstern samtstern modified the milestones: 4.0.1, 4.1.0 May 31, 2018
@samtstern samtstern merged commit afe6c2d into firebase:version-4.1.0-dev May 31, 2018
@samtstern
Copy link
Contributor

@SUPERCILEX boom! Your second big kahuna is now complete!

@SUPERCILEX SUPERCILEX deleted the phone-rewrite branch May 31, 2018 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants