Chromium Code Reviews| Index: ui/android/java/src/org/chromium/ui/autofill/CardUnmaskPrompt.java |
| diff --git a/ui/android/java/src/org/chromium/ui/autofill/CardUnmaskPrompt.java b/ui/android/java/src/org/chromium/ui/autofill/CardUnmaskPrompt.java |
| index b2fd58da40fe2639bb8d4f4502cee8832c7737d1..500bb5501a758adf283dd901e80b07be7dde3072 100644 |
| --- a/ui/android/java/src/org/chromium/ui/autofill/CardUnmaskPrompt.java |
| +++ b/ui/android/java/src/org/chromium/ui/autofill/CardUnmaskPrompt.java |
| @@ -13,19 +13,25 @@ import android.text.TextWatcher; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.inputmethod.InputMethodManager; |
| +import android.widget.ArrayAdapter; |
| import android.widget.Button; |
| import android.widget.EditText; |
| import android.widget.ProgressBar; |
| +import android.widget.Spinner; |
| import android.widget.TextView; |
| import org.chromium.ui.R; |
| +import java.text.NumberFormat; |
| +import java.util.Calendar; |
| + |
| /** |
| * A prompt that bugs users to enter their CVC when unmasking a Wallet instrument (credit card). |
| */ |
| public class CardUnmaskPrompt implements DialogInterface.OnDismissListener, TextWatcher { |
| private CardUnmaskPromptDelegate mDelegate; |
| private AlertDialog mDialog; |
| + private boolean mShouldRequestExpirationDate; |
| /** |
| * An interface to handle the interaction with an CardUnmaskPrompt object. |
| @@ -46,17 +52,19 @@ public class CardUnmaskPrompt implements DialogInterface.OnDismissListener, Text |
| * @param userResponse The value the user entered (a CVC), or an empty string if the |
| * user canceled. |
| */ |
| - void onUserInput(String userResponse); |
| + void onUserInput(String cvc, String month, String year); |
| } |
| - public CardUnmaskPrompt( |
| - Context context, CardUnmaskPromptDelegate delegate, String title, String instructions) { |
| + public CardUnmaskPrompt(Context context, CardUnmaskPromptDelegate delegate, String title, |
| + String instructions, int iconId, boolean shouldRequestExpirationDate) { |
| mDelegate = delegate; |
| LayoutInflater inflater = LayoutInflater.from(context); |
| View v = inflater.inflate(R.layout.autofill_card_unmask_prompt, null); |
| ((TextView) v.findViewById(R.id.instructions)).setText(instructions); |
| + // TODO(estade): do something with iconId. |
| + |
| mDialog = new AlertDialog.Builder(context) |
| .setTitle(title) |
| .setView(v) |
| @@ -64,11 +72,15 @@ public class CardUnmaskPrompt implements DialogInterface.OnDismissListener, Text |
| .setPositiveButton(R.string.card_unmask_confirm_button, null) |
| .setOnDismissListener(this) |
| .create(); |
| + |
| + mShouldRequestExpirationDate = shouldRequestExpirationDate; |
| } |
| public void show() { |
| mDialog.show(); |
| + if (mShouldRequestExpirationDate) initializeExpirationDateSpinners(); |
| + |
| // Override the View.OnClickListener so that pressing the positive button doesn't dismiss |
| // the dialog. |
| Button verifyButton = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); |
| @@ -76,16 +88,18 @@ public class CardUnmaskPrompt implements DialogInterface.OnDismissListener, Text |
| verifyButton.setOnClickListener(new View.OnClickListener() { |
| @Override |
| public void onClick(View view) { |
| - mDelegate.onUserInput(cardUnmaskInput().getText().toString()); |
| + mDelegate.onUserInput(getCardUnmaskInput().getText().toString(), |
| + (String) getMonthSpinner().getSelectedItem(), |
| + (String) getYearSpinner().getSelectedItem()); |
| } |
| }); |
| - final EditText input = cardUnmaskInput(); |
| + final EditText input = getCardUnmaskInput(); |
| input.addTextChangedListener(this); |
| input.post(new Runnable() { |
| @Override |
| public void run() { |
| - showKeyboardForUnmaskInput(); |
| + setInitialFocus(); |
| } |
| }); |
| } |
| @@ -95,7 +109,10 @@ public class CardUnmaskPrompt implements DialogInterface.OnDismissListener, Text |
| } |
| public void disableAndWaitForVerification() { |
| - cardUnmaskInput().setEnabled(false); |
| + getCardUnmaskInput().setEnabled(false); |
| + getMonthSpinner().setEnabled(false); |
| + getYearSpinner().setEnabled(false); |
| + |
| mDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); |
| getVerificationProgressBar().setVisibility(View.VISIBLE); |
| @@ -108,9 +125,10 @@ public class CardUnmaskPrompt implements DialogInterface.OnDismissListener, Text |
| TextView message = getVerificationView(); |
| message.setText("Verification failed. Please try again."); |
| message.setVisibility(View.VISIBLE); |
| - EditText input = cardUnmaskInput(); |
| - input.setEnabled(true); |
| - showKeyboardForUnmaskInput(); |
| + getCardUnmaskInput().setEnabled(true); |
| + getMonthSpinner().setEnabled(true); |
| + getYearSpinner().setEnabled(true); |
| + setInitialFocus(); |
| // TODO(estade): UI decision - should we clear the input? |
|
newt (away)
2015/01/29 04:42:28
IMO, no. I'd leave the input so the user can see a
Evan Stade
2015/01/30 02:13:23
this is mostly a note to myself to check with ains
newt (away)
2015/01/30 16:29:00
I'm aware. Just providing another opinion in case
|
| } else { |
| mDialog.findViewById(R.id.verification_success).setVisibility(View.VISIBLE); |
| @@ -130,8 +148,7 @@ public class CardUnmaskPrompt implements DialogInterface.OnDismissListener, Text |
| @Override |
| public void afterTextChanged(Editable s) { |
| - boolean valid = mDelegate.checkUserInputValidity(cardUnmaskInput().getText().toString()); |
| - mDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(valid); |
| + mDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(inputsAreValid()); |
| } |
| @Override |
| @@ -140,13 +157,51 @@ public class CardUnmaskPrompt implements DialogInterface.OnDismissListener, Text |
| @Override |
| public void onTextChanged(CharSequence s, int start, int before, int count) {} |
| - private void showKeyboardForUnmaskInput() { |
| + private void initializeExpirationDateSpinners() { |
| + ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>( |
|
newt (away)
2015/01/29 04:42:28
Reusing this variable makes the code a bit harder
Evan Stade
2015/01/30 02:13:23
Done.
|
| + mDialog.getContext(), android.R.layout.simple_spinner_item); |
| + |
| + // TODO(estade): i18n, or remove this entry, or something. |
| + adapter.add("MM"); |
|
newt (away)
2015/01/29 04:42:28
You could follow the UI design used in the autofil
Evan Stade
2015/01/30 02:13:24
I don't think that fits nicely into the mocks that
|
| + NumberFormat nf = NumberFormat.getInstance(); |
| + nf.setMinimumIntegerDigits(2); |
| + for (int month = 1; month <= 12; month++) { |
| + adapter.add(nf.format(month)); |
| + } |
| + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); |
| + getMonthSpinner().setAdapter(adapter); |
| + |
| + adapter = new ArrayAdapter<CharSequence>( |
| + mDialog.getContext(), android.R.layout.simple_spinner_item); |
| + adapter.add("YYYY"); |
| + Calendar calendar = Calendar.getInstance(); |
| + int initialYear = calendar.get(Calendar.YEAR); |
| + for (int year = initialYear; year < initialYear + 10; year++) { |
| + adapter.add(Integer.toString(year)); |
| + } |
| + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); |
| + getYearSpinner().setAdapter(adapter); |
| + |
| + getMonthSpinner().setVisibility(View.VISIBLE); |
| + getYearSpinner().setVisibility(View.VISIBLE); |
| + } |
| + |
| + private void setInitialFocus() { |
| + if (mShouldRequestExpirationDate) return; |
| + |
| InputMethodManager imm = (InputMethodManager) mDialog.getContext().getSystemService( |
| Context.INPUT_METHOD_SERVICE); |
| - imm.showSoftInput(cardUnmaskInput(), InputMethodManager.SHOW_IMPLICIT); |
| + imm.showSoftInput(getCardUnmaskInput(), InputMethodManager.SHOW_IMPLICIT); |
| + } |
| + |
| + private boolean inputsAreValid() { |
|
newt (away)
2015/01/29 04:42:28
I'd call this "areInputsValid()". The current name
Evan Stade
2015/01/30 02:13:24
Done.
|
| + return mDelegate.checkUserInputValidity(getCardUnmaskInput().getText().toString()) |
|
newt (away)
2015/01/29 04:42:28
Maybe easier to read:
if (mShouldRequestExpir
Evan Stade
2015/01/30 02:13:24
not a huge fan of nested ifs in place of &&, but I
|
| + && (!mShouldRequestExpirationDate |
| + || (getMonthSpinner().getSelectedItemPosition() != 0 |
| + && getYearSpinner().getSelectedItemPosition() != 0)); |
| } |
| - private EditText cardUnmaskInput() { |
| + private EditText getCardUnmaskInput() { |
| return (EditText) mDialog.findViewById(R.id.card_unmask_input); |
|
newt (away)
2015/01/29 04:42:28
A more typical pattern is have a member variable f
Evan Stade
2015/01/30 02:13:23
Done.
|
| } |
| @@ -157,4 +212,12 @@ public class CardUnmaskPrompt implements DialogInterface.OnDismissListener, Text |
| private TextView getVerificationView() { |
| return (TextView) mDialog.findViewById(R.id.verification_message); |
| } |
| + |
| + private Spinner getMonthSpinner() { |
| + return (Spinner) mDialog.findViewById(R.id.expiration_month); |
| + } |
| + |
| + private Spinner getYearSpinner() { |
| + return (Spinner) mDialog.findViewById(R.id.expiration_year); |
| + } |
| } |