diff --git a/res/layout/account_setup_credentials_fragment.xml b/res/layout/account_setup_credentials_fragment.xml index d3e2e7c7f..0003ff17c 100644 --- a/res/layout/account_setup_credentials_fragment.xml +++ b/res/layout/account_setup_credentials_fragment.xml @@ -20,6 +20,42 @@ android:layout_weight="1" android:orientation="vertical"> + + + + + + + + + android:imeOptions="actionDone"/> #777777 #cccccc + + #FFA500 + #808080 + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index a8ee98ceb..1f04c0807 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -194,6 +194,11 @@ Requesting authorization Sign in + + + Email address or password are incorrect + + Email address: Email account @@ -207,7 +212,8 @@ OR Sign in with Google - + + Password Password diff --git a/src/com/android/email/activity/setup/AccountCredentials.java b/src/com/android/email/activity/setup/AccountCredentials.java index 9b2b43cd3..41e4d5374 100644 --- a/src/com/android/email/activity/setup/AccountCredentials.java +++ b/src/com/android/email/activity/setup/AccountCredentials.java @@ -36,7 +36,7 @@ public class AccountCredentials extends Activity final String protocol = getIntent().getStringExtra(EXTRA_PROTOCOL); final AccountSetupCredentialsFragment f = - AccountSetupCredentialsFragment.newInstance(emailAddress, protocol); + AccountSetupCredentialsFragment.newInstance(emailAddress, protocol, false); getFragmentManager().beginTransaction() .add(R.id.account_credentials_fragment_container, f, CREDENTIALS_FRAGMENT_TAG) .commit(); diff --git a/src/com/android/email/activity/setup/AccountSetupCredentialsFragment.java b/src/com/android/email/activity/setup/AccountSetupCredentialsFragment.java index 4b4e57292..3a54b45b1 100644 --- a/src/com/android/email/activity/setup/AccountSetupCredentialsFragment.java +++ b/src/com/android/email/activity/setup/AccountSetupCredentialsFragment.java @@ -24,10 +24,12 @@ import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.text.format.DateUtils; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.TextView; @@ -54,6 +56,7 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment private static final String EXTRA_EMAIL = "email"; private static final String EXTRA_PROTOCOL = "protocol"; + private static final String EXTRA_PASSWORD_FAILED = "password_failed"; public static final String EXTRA_PASSWORD = "password"; public static final String EXTRA_OAUTH_PROVIDER = "provider"; @@ -66,6 +69,10 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment private EditText mImapPasswordText; private EditText mRegularPasswordText; private TextWatcher mValidationTextWatcher; + private TextView mPasswordWarningLabel; + private TextView mEmailConfirmationLabel; + private TextView mEmailConfirmation; + private TextView.OnEditorActionListener mEditorActionListener; private String mEmailAddress; private boolean mOfferOAuth; private boolean mOfferCerts; @@ -87,11 +94,12 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment * @return new fragment instance */ public static AccountSetupCredentialsFragment newInstance(final String email, - final String protocol) { + final String protocol, final boolean passwordFailed) { final AccountSetupCredentialsFragment f = new AccountSetupCredentialsFragment(); final Bundle b = new Bundle(2); b.putString(EXTRA_EMAIL, email); b.putString(EXTRA_PROTOCOL, protocol); + b.putBoolean(EXTRA_PASSWORD_FAILED, passwordFailed); f.setArguments(b); return f; } @@ -111,6 +119,29 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment mDeviceIdSection = UiUtilities.getView(view, R.id.device_id_section); mDeviceId = UiUtilities.getView(view, R.id.device_id); mClientCertificateSelector.setHostCallback(this); + mPasswordWarningLabel = UiUtilities.getView(view, R.id.wrong_password_warning_label); + mEmailConfirmationLabel = UiUtilities.getView(view, R.id.email_confirmation_label); + mEmailConfirmation = UiUtilities.getView(view, R.id.email_confirmation); + + mEditorActionListener = new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView view, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + final Callback callback = (Callback) getActivity(); + if (callback != null) { + final Bundle results = new Bundle(1); + results.putString(EXTRA_PASSWORD, getPassword()); + mResults = results; + callback.onCredentialsComplete(results); + } + return true; + } else { + return false; + } + } + }; + mImapPasswordText.setOnEditorActionListener(mEditorActionListener); + mRegularPasswordText.setOnEditorActionListener(mEditorActionListener); // After any text edits, call validateFields() which enables or disables the Next button mValidationTextWatcher = new TextWatcher() { @@ -166,6 +197,8 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment } mDeviceId.setText(deviceId); } + final boolean passwordFailed = getArguments().getBoolean(EXTRA_PASSWORD_FAILED, false); + setPasswordFailed(passwordFailed); validatePassword(); } @@ -174,14 +207,29 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment super.onDestroy(); if (mImapPasswordText != null) { mImapPasswordText.removeTextChangedListener(mValidationTextWatcher); + mImapPasswordText.setOnEditorActionListener(null); mImapPasswordText = null; } if (mRegularPasswordText != null) { mRegularPasswordText.removeTextChangedListener(mValidationTextWatcher); + mRegularPasswordText.setOnEditorActionListener(null); mRegularPasswordText = null; } } + public void setPasswordFailed(final boolean failed) { + if (failed) { + mPasswordWarningLabel.setVisibility(View.VISIBLE); + mEmailConfirmationLabel.setVisibility(View.VISIBLE); + mEmailConfirmation.setVisibility(View.VISIBLE); + mEmailConfirmation.setText(mEmailAddress); + } else { + mPasswordWarningLabel.setVisibility(View.GONE); + mEmailConfirmationLabel.setVisibility(View.GONE); + mEmailConfirmation.setVisibility(View.GONE); + } + } + public void validatePassword() { final Callback callback = (Callback) getActivity(); if (callback != null) { diff --git a/src/com/android/email/activity/setup/AccountSetupFinal.java b/src/com/android/email/activity/setup/AccountSetupFinal.java index 20249aa43..dd215c8f8 100644 --- a/src/com/android/email/activity/setup/AccountSetupFinal.java +++ b/src/com/android/email/activity/setup/AccountSetupFinal.java @@ -23,6 +23,7 @@ import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.app.Fragment; +import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.LoaderManager; import android.app.ProgressDialog; @@ -108,8 +109,10 @@ public class AccountSetupFinal extends AccountSetupActivity "AccountSetupFinal.authErr"; private static final String SAVESTATE_KEY_IS_PRE_CONFIGURED = "AccountSetupFinal.preconfig"; private static final String SAVESTATE_KEY_SKIP_AUTO_DISCOVER = "AccountSetupFinal.noAuto"; + private static final String SAVESTATE_KEY_PASSWORD_FAILED = "AccountSetupFinal.passwordFailed"; private static final String CONTENT_FRAGMENT_TAG = "AccountSetupContentFragment"; + private static final String CREDENTIALS_BACKSTACK_TAG = "AccountSetupCredentialsFragment"; // Collecting initial email and password private static final int STATE_BASICS = 0; @@ -154,6 +157,7 @@ public class AccountSetupFinal extends AccountSetupActivity private boolean mPreConfiguredFailed = false; private VendorPolicyLoader.Provider mProvider; + private boolean mPasswordFailed; // UI elements @VisibleForTesting @@ -210,6 +214,7 @@ public class AccountSetupFinal extends AccountSetupActivity mIsPreConfiguredProvider = savedInstanceState.getBoolean(SAVESTATE_KEY_IS_PRE_CONFIGURED); mSkipAutoDiscover = savedInstanceState.getBoolean(SAVESTATE_KEY_SKIP_AUTO_DISCOVER); + mPasswordFailed = savedInstanceState.getBoolean(SAVESTATE_KEY_PASSWORD_FAILED); // I don't know why this view state doesn't get restored updateHeadline(); } else { @@ -249,6 +254,7 @@ public class AccountSetupFinal extends AccountSetupActivity } updateHeadline(); updateContentFragment(false /* addToBackstack */); + mPasswordFailed = false; } UiUtilities.getView(this, R.id.previous).setOnClickListener(this); @@ -398,6 +404,7 @@ public class AccountSetupFinal extends AccountSetupActivity outState.putBoolean(SAVESTATE_KEY_REPORT_AUTHENTICATOR_ERROR, mReportAccountAuthenticatorError); outState.putBoolean(SAVESTATE_KEY_IS_PRE_CONFIGURED, mIsPreConfiguredProvider); + outState.putBoolean(SAVESTATE_KEY_PASSWORD_FAILED, mPasswordFailed); } /** @@ -439,13 +446,17 @@ public class AccountSetupFinal extends AccountSetupActivity */ private void updateContentFragment(boolean addToBackstack) { final AccountSetupFragment f; + String backstackTag = null; + switch (mState) { case STATE_BASICS: f = AccountSetupBasicsFragment.newInstance(); break; case STATE_CREDENTIALS: f = AccountSetupCredentialsFragment.newInstance(mSetupData.getEmail(), - mSetupData.getAccount().getOrCreateHostAuthRecv(this).mProtocol); + mSetupData.getAccount().getOrCreateHostAuthRecv(this).mProtocol, + mPasswordFailed); + backstackTag = CREDENTIALS_BACKSTACK_TAG; break; case STATE_TYPE: f = AccountSetupTypeFragment.newInstance(); @@ -469,7 +480,7 @@ public class AccountSetupFinal extends AccountSetupActivity final FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.setup_fragment_container, f, CONTENT_FRAGMENT_TAG); if (addToBackstack) { - ft.addToBackStack(null); + ft.addToBackStack(backstackTag); } ft.commit(); } @@ -488,6 +499,9 @@ public class AccountSetupFinal extends AccountSetupActivity */ private void resetStateFromCurrentFragment() { AccountSetupFragment f = getContentFragment(); + if (mState == STATE_CREDENTIALS) { + mPasswordFailed = false; + } mState = f.getState(); updateHeadline(); } @@ -505,6 +519,7 @@ public class AccountSetupFinal extends AccountSetupActivity switch (mState) { case STATE_BASICS: onBasicsComplete(); + // TODO: Move protocol choice before password entry if (shouldDivertToManual()) { // Alternate entry to the debug options screen (for devices without a physical // keyboard): @@ -544,9 +559,13 @@ public class AccountSetupFinal extends AccountSetupActivity break; case STATE_CHECKING_PRECONFIGURED: if (mPreConfiguredFailed) { - mState = STATE_MANUAL_INCOMING; - updateHeadline(); - updateContentFragment(true /* addToBackstack */); + // Get rid of the previous instance of the AccountSetupCredentialsFragment. + FragmentManager fm = getFragmentManager(); + fm.popBackStackImmediate(CREDENTIALS_BACKSTACK_TAG, 0); + final AccountSetupCredentialsFragment f = (AccountSetupCredentialsFragment) + getContentFragment(); + f.setPasswordFailed(mPasswordFailed); + resetStateFromCurrentFragment(); } else { mState = STATE_OPTIONS; updateHeadline(); @@ -896,6 +915,7 @@ public class AccountSetupFinal extends AccountSetupActivity @Override public void onCheckSettingsError(int reason, String message) { + mPasswordFailed = true; dismissCheckSettingsFragment(); final DialogFragment f = CheckSettingsErrorDialogFragment.newInstance(reason, message); @@ -916,7 +936,7 @@ public class AccountSetupFinal extends AccountSetupActivity @Override public void onCheckSettingsErrorDialogEditSettings() { - // If we're checking pre-configured, set a flag that we failed and navigate fowards to + // If we're checking pre-configured, set a flag that we failed and navigate forwards to // incoming settings if (mState == STATE_CHECKING_PRECONFIGURED || mState == STATE_AUTO_DISCOVER) { mPreConfiguredFailed = true; @@ -928,6 +948,8 @@ public class AccountSetupFinal extends AccountSetupActivity @Override public void onCheckSettingsComplete() { + mPreConfiguredFailed = false; + mPasswordFailed = false; dismissCheckSettingsFragment(); proceed(); }