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

Remove progress dialogs #1280

Merged
merged 12 commits into from
May 17, 2018
3 changes: 3 additions & 0 deletions auth/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ dependencies {
implementation "com.android.support:customtabs:$supportLibraryVersion"
compileOnly("com.twitter.sdk.android:twitter-core:3.1.1@aar") { transitive = true }

// Material progress bar for loading indicators
implementation 'me.zhanghai.android.materialprogressbar:library:1.4.2'

testImplementation 'junit:junit:4.12'
//noinspection GradleDynamicVersion
testImplementation 'org.mockito:mockito-core:2.15.+'
Expand Down
7 changes: 3 additions & 4 deletions auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -31,8 +31,7 @@ protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mKickstarter = ViewModelProviders.of(this).get(SignInKickstarter.class);
mKickstarter.init(getFlowParams());
mKickstarter.getOperation().observe(this, new ResourceObserver<IdpResponse>(
this, R.string.fui_progress_dialog_loading) {
mKickstarter.getOperation().observe(this, new ResourceObserver<IdpResponse>(this) {
@Override
protected void onSuccess(@NonNull IdpResponse response) {
finish(RESULT_OK, response.toIntent());
Expand Down
12 changes: 11 additions & 1 deletion auth/src/main/java/com/firebase/ui/auth/ui/FragmentBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

So we haven't gotten rid of all of progress dialogs yet?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think once you're done with Phone auth we can really kill the whole ProgressDialogHolder thing.


Expand Down Expand Up @@ -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();
}
}
21 changes: 16 additions & 5 deletions auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -24,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;
Expand Down Expand Up @@ -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();
Expand All @@ -97,4 +94,18 @@ public void startSaveCredentials(
this, getFlowParams(), credential, response);
startActivityForResult(intent, RequestCodes.CRED_SAVE_FLOW);
}

@Override
public void showProgress(@StringRes int message) {
getDialogHolder().showLoadingDialog(message);
}

@Override
public void hideProgress() {
getDialogHolder().dismissDialog();
}

protected ProgressDialogHolder getDialogHolder() {
return mProgressDialogHolder;
}
}
104 changes: 104 additions & 0 deletions auth/src/main/java/com/firebase/ui/auth/ui/InvisibleActivityBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
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.ContextThemeWrapper;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.firebase.ui.auth.R;

import me.zhanghai.android.materialprogressbar.MaterialProgressBar;

/**
* Base classes for activities that are just simple overlays.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class InvisibleActivityBase extends HelperActivityBase {

// Minimum time that the spinner will stay on screen, once it is shown.
private static final long MIN_SPINNER_MS = 750;

private Handler mHandler = new Handler();
private MaterialProgressBar mProgressBar;

// Last time that the progress bar was actually shown
private long mLastShownTime = 0;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fui_activity_invisible);

// Create an indeterminate, circular progress bar in the app's theme
mProgressBar = new MaterialProgressBar(new ContextThemeWrapper(this, getFlowParams().themeId));
mProgressBar.setIndeterminate(true);
mProgressBar.setVisibility(View.GONE);

// Set bar to float in the center
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;

// Add to the container
FrameLayout container = findViewById(R.id.invisible_frame);
container.addView(mProgressBar, params);
}

@Override
public void showProgress(int message) {
if (mProgressBar.getVisibility() == View.VISIBLE) {
mHandler.removeCallbacksAndMessages(null);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Glad to see you know that trick too! I've been burned so many times using removeCallbacks without the messages bit. 🤦‍♂️😆

return;
}

mLastShownTime = System.currentTimeMillis();
mProgressBar.setVisibility(View.VISIBLE);
Copy link
Collaborator

Choose a reason for hiding this comment

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

So I'm wondering, what if we also had a really small (like 300ms) delay to show progress? Would that make the app feel faster?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So do you mean possibly avoid showing it at all for things that take under 300ms? Sounds like a great idea to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually since we are launching into a different activity here (which affects a lot of things underlying) it's better to show immediately.

}

@Override
public void hideProgress() {
doAfterTimeout(new Runnable() {
@Override
public void run() {
mLastShownTime = 0;
mProgressBar.setVisibility(View.GONE);
}
});
}

@Override
public void finish(int resultCode, @Nullable Intent intent) {
setResult(resultCode, intent);
doAfterTimeout(new Runnable() {
@Override
public void run() {
finish();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you explain your reasoning for waiting to finish? Since there's no text to read or anything like that, I feel like we should finish instantly. Or did that feel janky?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a comment. Basically sometimes we call finish() instead of hideProgress() so this is for that case.

}
});
}

/**
* For certain actions (like finishing or hiding the progress dialog) we want to make sure
* that we have shown the progress state for at least MIN_SPINNER_MS to prevent flickering.
*
* This method performs some action after the window has passed, or immediately if we have
* already waited longer than that.
*/
private void doAfterTimeout(Runnable runnable) {
long currentTime = System.currentTimeMillis();
long diff = currentTime - mLastShownTime;

// 'diff' is how long it's been since we showed the spinner, so in the
// case where diff is greater than our minimum spinner duration then our
// remaining wait time is 0.
long remaining = Math.max(MIN_SPINNER_MS - diff, 0);

mHandler.postDelayed(runnable, remaining);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public ProgressDialogHolder(Context context) {

private void showLoadingDialog(String message) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

So we really can't kill this class yet? 😭

Copy link
Contributor Author

@samtstern samtstern May 16, 2018

Choose a reason for hiding this comment

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

Right now it just acts as a "fallback" implementation. If you were to add a new activity or fragment and not override the progress methods to do something special, it would use a dialog.

Once phone auth is updated we can remove the base implementation, I think.

dismissDialog();

if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(mContext);
mProgressDialog.setIndeterminate(true);
Expand All @@ -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() {
Expand Down
16 changes: 16 additions & 0 deletions auth/src/main/java/com/firebase/ui/auth/ui/ProgressView.java
Original file line number Diff line number Diff line change
@@ -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();

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
import android.util.Log;

import com.firebase.ui.auth.IdpResponse;
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;
Expand All @@ -21,7 +20,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;
Expand All @@ -47,8 +46,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
mHandler.init(getFlowParams());
mHandler.setResponse(response);

mHandler.getOperation().observe(this, new ResourceObserver<IdpResponse>(
this, R.string.fui_progress_dialog_loading) {
mHandler.getOperation().observe(this, new ResourceObserver<IdpResponse>(this) {
@Override
protected void onSuccess(@NonNull IdpResponse response) {
finish(RESULT_OK, response.toIntent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 android.widget.TextView;

import com.firebase.ui.auth.R;
Expand Down Expand Up @@ -62,6 +64,9 @@ interface CheckEmailListener {

private CheckEmailHandler mHandler;

private Button mNextButton;
private ProgressBar mProgressBar;

private EditText mEmailEditText;
private TextInputLayout mEmailLayout;

Expand All @@ -85,6 +90,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);
Expand All @@ -98,7 +106,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);

TextView termsText = view.findViewById(R.id.email_tos_and_pp_text);
TextView footerText = view.findViewById(R.id.email_footer_tos_and_pp_text);
Expand Down Expand Up @@ -193,4 +201,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);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -112,6 +117,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);
Expand All @@ -137,7 +145,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);
Expand Down Expand Up @@ -226,6 +234,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);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here

}

private void validateAndRegisterUser() {
String email = mEmailEditText.getText().toString();
String password = mPasswordEditText.getText().toString();
Expand Down
Loading