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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
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 android.widget.ProgressBar;

import com.firebase.ui.auth.R;


Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: extra new line

/**
* 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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ooof, this seems like a long time. How about 500ms or even 750?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to 750. You'd be surprised how "flickery" 500 feels.


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_invisible);

// Create an indeterminate, circular progress bar in the app's theme
mProgressBar = new ProgressBar(new ContextThemeWrapper(this, getFlowParams().themeId));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't we use the material library version to get sexiness pre-L? (And consistent behavior in general.)

mProgressBar.setIndeterminate(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.

Why are we using INVISIBLE (here and elsewhere)? That means we're going to be doing extra layout and measure passes...


// 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.INVISIBLE);
}
});
}

@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.

}
});
}

private void doAfterTimeout(Runnable runnable) {
long currentTime = System.currentTimeMillis();
long diff = currentTime - mLastShownTime;
long remaining = Math.max(MIN_SPINNER_MS - diff, 0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we maybe add a comment saying we want at least 0 and the diff can be really big? I was confused as to why we needed max at first.


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 com.firebase.ui.auth.R;
import com.firebase.ui.auth.data.model.User;
Expand Down Expand Up @@ -59,6 +61,9 @@ interface CheckEmailListener {

private CheckEmailHandler mHandler;

private Button mNextButton;
private ProgressBar mProgressBar;

private EditText mEmailEditText;
private TextInputLayout mEmailLayout;

Expand All @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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);
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 @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
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