From 2fec55498c0cebe8f283af6fad35067d8250d944 Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Wed, 2 May 2018 17:04:09 -0700 Subject: [PATCH 1/9] Start removing progress dialogs Change-Id: Ie8e5a0c5dd0105b1b9d79ef385836286cfe6375f --- .../com/firebase/ui/auth/KickoffActivity.java | 4 +- .../ui/auth/ui/HelperActivityBase.java | 17 ++++- .../ui/auth/ui/InvisibleActivityBase.java | 75 +++++++++++++++++++ .../ui/auth/ui/ProgressDialogHolder.java | 6 +- .../credentials/CredentialSaveActivity.java | 4 +- .../ui/auth/viewmodel/ResourceObserver.java | 5 +- .../main/res/layout/fui_activity_kickoff.xml | 21 ++++++ auth/src/main/res/values/styles.xml | 4 +- 8 files changed, 121 insertions(+), 15 deletions(-) create mode 100644 auth/src/main/java/com/firebase/ui/auth/ui/InvisibleActivityBase.java create mode 100644 auth/src/main/res/layout/fui_activity_kickoff.xml diff --git a/auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java b/auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java index d91a22dc0..a32c2a9ba 100644 --- a/auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java @@ -12,14 +12,14 @@ import com.firebase.ui.auth.data.model.FlowParameters; import com.firebase.ui.auth.data.model.UserCancellationException; import com.firebase.ui.auth.data.remote.SignInKickstarter; -import com.firebase.ui.auth.ui.HelperActivityBase; +import com.firebase.ui.auth.ui.InvisibleActivityBase; import com.firebase.ui.auth.viewmodel.ResourceObserver; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class KickoffActivity extends HelperActivityBase { +public class KickoffActivity extends InvisibleActivityBase { private SignInKickstarter mKickstarter; public static Intent createIntent(Context context, FlowParameters flowParams) { diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java b/auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java index 28ef4949f..31a0ecc0a 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java @@ -7,6 +7,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RestrictTo; +import android.support.annotation.StringRes; import android.support.v7.app.AppCompatActivity; import com.firebase.ui.auth.IdpResponse; @@ -74,10 +75,6 @@ public AuthHelper getAuthHelper() { return mAuthHelper; } - public ProgressDialogHolder getDialogHolder() { - return mProgressDialogHolder; - } - public void finish(int resultCode, @Nullable Intent intent) { setResult(resultCode, intent); finish(); @@ -97,4 +94,16 @@ public void startSaveCredentials( this, getFlowParams(), credential, response); startActivityForResult(intent, RequestCodes.CRED_SAVE_FLOW); } + + public void showProgress(@StringRes int message) { + getDialogHolder().showLoadingDialog(message); + } + + public void hideProgress() { + getDialogHolder().dismissDialog(); + } + + protected ProgressDialogHolder getDialogHolder() { + return mProgressDialogHolder; + } } diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/InvisibleActivityBase.java b/auth/src/main/java/com/firebase/ui/auth/ui/InvisibleActivityBase.java new file mode 100644 index 000000000..31a14648b --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/ui/InvisibleActivityBase.java @@ -0,0 +1,75 @@ +package com.firebase.ui.auth.ui; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.Nullable; +import android.support.annotation.RestrictTo; +import android.view.View; +import android.widget.ProgressBar; + +import com.firebase.ui.auth.R; + + +/** + * Base classes for activities that are just simple overlays. + */ +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) +public class InvisibleActivityBase extends HelperActivityBase { + + private static final long MIN_SPINNER_MS = 1000; + + private Handler mHandler = new Handler(); + private ProgressBar mProgressBar; + private long mLastShownTime = 0; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.fui_activity_kickoff); + + // TODO: Set the color based on passed in theme + mProgressBar = findViewById(R.id.progress_spinner); + } + + @Override + public void showProgress(int message) { + if (mProgressBar.getVisibility() == View.VISIBLE) { + mHandler.removeCallbacksAndMessages(null); + return; + } + + mLastShownTime = System.currentTimeMillis(); + mProgressBar.setVisibility(View.VISIBLE); + } + + @Override + public void hideProgress() { + doAfterTimeout(new Runnable() { + @Override + public void run() { + mLastShownTime = 0; + mProgressBar.setVisibility(View.INVISIBLE); + } + }); + } + + @Override + public void finish(int resultCode, @Nullable Intent intent) { + setResult(resultCode, intent); + doAfterTimeout(new Runnable() { + @Override + public void run() { + finish(); + } + }); + } + + private void doAfterTimeout(Runnable runnable) { + long currentTime = System.currentTimeMillis(); + long diff = currentTime - mLastShownTime; + long remaining = Math.max(MIN_SPINNER_MS - diff, 0); + + mHandler.postDelayed(runnable, remaining); + } +} diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/ProgressDialogHolder.java b/auth/src/main/java/com/firebase/ui/auth/ui/ProgressDialogHolder.java index 1b6ff9d8e..c4d7d4e83 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/ProgressDialogHolder.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/ProgressDialogHolder.java @@ -18,7 +18,6 @@ public ProgressDialogHolder(Context context) { private void showLoadingDialog(String message) { dismissDialog(); - if (mProgressDialog == null) { mProgressDialog = new ProgressDialog(mContext); mProgressDialog.setIndeterminate(true); @@ -34,10 +33,11 @@ public void showLoadingDialog(@StringRes int stringResource) { } public void dismissDialog() { - if (mProgressDialog != null) { + if (isProgressDialogShowing()) { mProgressDialog.dismiss(); - mProgressDialog = null; } + + mProgressDialog = null; } public boolean isProgressDialogShowing() { diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java index 2a359c44a..286e142d3 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java @@ -12,7 +12,7 @@ import com.firebase.ui.auth.R; import com.firebase.ui.auth.data.model.FlowParameters; import com.firebase.ui.auth.data.model.Resource; -import com.firebase.ui.auth.ui.HelperActivityBase; +import com.firebase.ui.auth.ui.InvisibleActivityBase; import com.firebase.ui.auth.util.ExtraConstants; import com.firebase.ui.auth.viewmodel.ResourceObserver; import com.firebase.ui.auth.viewmodel.smartlock.SmartLockHandler; @@ -21,7 +21,7 @@ /** * Invisible Activity used for saving credentials to SmartLock. */ -public class CredentialSaveActivity extends HelperActivityBase { +public class CredentialSaveActivity extends InvisibleActivityBase { private static final String TAG = "CredentialSaveActivity"; private SmartLockHandler mHandler; diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/ResourceObserver.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/ResourceObserver.java index ce438002c..d84f4c675 100644 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/ResourceObserver.java +++ b/auth/src/main/java/com/firebase/ui/auth/viewmodel/ResourceObserver.java @@ -4,6 +4,7 @@ import android.support.annotation.NonNull; import android.support.annotation.RestrictTo; import android.support.annotation.StringRes; +import android.util.Log; import com.firebase.ui.auth.data.model.Resource; import com.firebase.ui.auth.data.model.State; @@ -34,10 +35,10 @@ private ResourceObserver(HelperActivityBase activity, FragmentBase fragment, int @Override public final void onChanged(Resource resource) { if (resource.getState() == State.LOADING) { - mActivity.getDialogHolder().showLoadingDialog(mLoadingMessage); + mActivity.showProgress(mLoadingMessage); return; } - mActivity.getDialogHolder().dismissDialog(); + mActivity.hideProgress(); if (resource.isUsed()) { return; } diff --git a/auth/src/main/res/layout/fui_activity_kickoff.xml b/auth/src/main/res/layout/fui_activity_kickoff.xml new file mode 100644 index 000000000..796a4b424 --- /dev/null +++ b/auth/src/main/res/layout/fui_activity_kickoff.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/auth/src/main/res/values/styles.xml b/auth/src/main/res/values/styles.xml index ae3b546b1..e5867d9e9 100644 --- a/auth/src/main/res/values/styles.xml +++ b/auth/src/main/res/values/styles.xml @@ -12,11 +12,11 @@ + + From 4b363d4bb9d989fefb4616415007ef78918aa224 Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Thu, 3 May 2018 11:39:12 -0700 Subject: [PATCH 3/9] Finish the check and register email flows Change-Id: I95e08b3f2150387918ddf6a7455eda54a71f8296 --- .../com/firebase/ui/auth/ui/FragmentBase.java | 12 +- .../ui/auth/ui/HelperActivityBase.java | 4 +- .../com/firebase/ui/auth/ui/ProgressView.java | 16 +++ .../ui/auth/ui/email/CheckEmailFragment.java | 22 +++- .../auth/ui/email/RegisterEmailFragment.java | 22 +++- .../ui/auth/viewmodel/ResourceObserver.java | 23 +++- .../res/layout/fui_check_email_layout.xml | 55 +++++--- .../res/layout/fui_register_email_layout.xml | 123 ++++++++++-------- 8 files changed, 191 insertions(+), 86 deletions(-) create mode 100644 auth/src/main/java/com/firebase/ui/auth/ui/ProgressView.java diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/FragmentBase.java b/auth/src/main/java/com/firebase/ui/auth/ui/FragmentBase.java index 208ca31fc..3247b66df 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/FragmentBase.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/FragmentBase.java @@ -11,7 +11,7 @@ import com.google.firebase.auth.FirebaseUser; @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class FragmentBase extends Fragment { +public class FragmentBase extends Fragment implements ProgressView { private HelperActivityBase mActivity; private ProgressDialogHolder mProgressDialogHolder; @@ -44,4 +44,14 @@ public void startSaveCredentials( @Nullable String password) { mActivity.startSaveCredentials(firebaseUser, response, password); } + + @Override + public void showProgress(int message) { + mActivity.showProgress(message); + } + + @Override + public void hideProgress() { + mActivity.hideProgress(); + } } diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java b/auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java index 31a0ecc0a..f87a0153e 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java @@ -25,7 +25,7 @@ @SuppressWarnings("Registered") @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class HelperActivityBase extends AppCompatActivity { +public class HelperActivityBase extends AppCompatActivity implements ProgressView { private FlowParameters mParams; private AuthHelper mAuthHelper; @@ -95,10 +95,12 @@ public void startSaveCredentials( startActivityForResult(intent, RequestCodes.CRED_SAVE_FLOW); } + @Override public void showProgress(@StringRes int message) { getDialogHolder().showLoadingDialog(message); } + @Override public void hideProgress() { getDialogHolder().dismissDialog(); } diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/ProgressView.java b/auth/src/main/java/com/firebase/ui/auth/ui/ProgressView.java new file mode 100644 index 000000000..ba5dd96ae --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/ui/ProgressView.java @@ -0,0 +1,16 @@ +package com.firebase.ui.auth.ui; + +import android.support.annotation.RestrictTo; +import android.support.annotation.StringRes; + +/** + * View (Activity or Fragment, normally) that can respond to progress events. + */ +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) +public interface ProgressView { + + void showProgress(@StringRes int message); + + void hideProgress(); + +} diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/CheckEmailFragment.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/CheckEmailFragment.java index 42de36f32..766a3bf89 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/email/CheckEmailFragment.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/CheckEmailFragment.java @@ -12,7 +12,9 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.EditText; +import android.widget.ProgressBar; import com.firebase.ui.auth.R; import com.firebase.ui.auth.data.model.User; @@ -59,6 +61,9 @@ interface CheckEmailListener { private CheckEmailHandler mHandler; + private Button mNextButton; + private ProgressBar mProgressBar; + private EditText mEmailEditText; private TextInputLayout mEmailLayout; @@ -82,6 +87,9 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + mNextButton = view.findViewById(R.id.button_next); + mProgressBar = view.findViewById(R.id.top_progress_bar); + // Email field and validator mEmailLayout = view.findViewById(R.id.email_layout); mEmailEditText = view.findViewById(R.id.email); @@ -95,7 +103,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat mEmailEditText.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO); } - view.findViewById(R.id.button_next).setOnClickListener(this); + mNextButton.setOnClickListener(this); } @Override @@ -175,4 +183,16 @@ private void validateAndProceed() { mHandler.fetchProvider(email); } } + + @Override + public void showProgress(int message) { + mNextButton.setEnabled(false); + mProgressBar.setVisibility(View.VISIBLE); + } + + @Override + public void hideProgress() { + mNextButton.setEnabled(true); + mProgressBar.setVisibility(View.INVISIBLE); + } } diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailFragment.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailFragment.java index ffbeeb38b..897689ff2 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailFragment.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailFragment.java @@ -11,7 +11,9 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.EditText; +import android.widget.ProgressBar; import android.widget.TextView; import com.firebase.ui.auth.AuthUI; @@ -44,6 +46,9 @@ public class RegisterEmailFragment extends FragmentBase implements private EmailProviderResponseHandler mHandler; + private Button mNextButton; + private ProgressBar mProgressBar; + private EditText mEmailEditText; private EditText mNameEditText; private EditText mPasswordEditText; @@ -110,6 +115,9 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + mNextButton = view.findViewById(R.id.button_create); + mProgressBar = view.findViewById(R.id.top_progress_bar); + mEmailEditText = view.findViewById(R.id.email); mNameEditText = view.findViewById(R.id.name); mPasswordEditText = view.findViewById(R.id.password); @@ -135,7 +143,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat mEmailEditText.setOnFocusChangeListener(this); mNameEditText.setOnFocusChangeListener(this); mPasswordEditText.setOnFocusChangeListener(this); - view.findViewById(R.id.button_create).setOnClickListener(this); + mNextButton.setOnClickListener(this); // Only show the name field if required nameInput.setVisibility(requireName ? View.VISIBLE : View.GONE); @@ -223,6 +231,18 @@ public void onDonePressed() { validateAndRegisterUser(); } + @Override + public void showProgress(int message) { + mNextButton.setEnabled(false); + mProgressBar.setVisibility(View.VISIBLE); + } + + @Override + public void hideProgress() { + mNextButton.setEnabled(true); + mProgressBar.setVisibility(View.INVISIBLE); + } + private void validateAndRegisterUser() { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/ResourceObserver.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/ResourceObserver.java index d84f4c675..11fdc1d12 100644 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/ResourceObserver.java +++ b/auth/src/main/java/com/firebase/ui/auth/viewmodel/ResourceObserver.java @@ -4,41 +4,52 @@ import android.support.annotation.NonNull; import android.support.annotation.RestrictTo; import android.support.annotation.StringRes; -import android.util.Log; import com.firebase.ui.auth.data.model.Resource; import com.firebase.ui.auth.data.model.State; import com.firebase.ui.auth.ui.FragmentBase; import com.firebase.ui.auth.ui.HelperActivityBase; +import com.firebase.ui.auth.ui.ProgressView; import com.firebase.ui.auth.util.ui.FlowUtils; @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public abstract class ResourceObserver implements Observer> { + + private final ProgressView mProgressView; private final HelperActivityBase mActivity; private final FragmentBase mFragment; private final int mLoadingMessage; protected ResourceObserver(@NonNull HelperActivityBase activity, @StringRes int message) { - this(activity, null, message); + this(activity, null, activity, message); } protected ResourceObserver(@NonNull FragmentBase fragment, @StringRes int message) { - this((HelperActivityBase) fragment.getActivity(), fragment, message); + this(null, fragment, fragment, message); } - private ResourceObserver(HelperActivityBase activity, FragmentBase fragment, int message) { + private ResourceObserver(HelperActivityBase activity, + FragmentBase fragment, + ProgressView progressView, + int message) { mActivity = activity; mFragment = fragment; + + if (mActivity == null && mFragment == null) { + throw new IllegalStateException("ResourceObserver must be attached to an Activity or a Fragment"); + } + + mProgressView = progressView; mLoadingMessage = message; } @Override public final void onChanged(Resource resource) { if (resource.getState() == State.LOADING) { - mActivity.showProgress(mLoadingMessage); + mProgressView.showProgress(mLoadingMessage); return; } - mActivity.hideProgress(); + mProgressView.hideProgress(); if (resource.isUsed()) { return; } diff --git a/auth/src/main/res/layout/fui_check_email_layout.xml b/auth/src/main/res/layout/fui_check_email_layout.xml index 90e1c431f..691cbd1be 100644 --- a/auth/src/main/res/layout/fui_check_email_layout.xml +++ b/auth/src/main/res/layout/fui_check_email_layout.xml @@ -7,31 +7,44 @@ android:layout_height="match_parent"> - + + - - - - - -