Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java

Issue 2081533002: Edit contacts UI for PaymentRequest (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@contactDetails
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
index e4984546129ee9ba4209bfd06db6886d13701ee6..47aefa8ff9cc0a6ef9693fcc0d679dd6421b07ef 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -16,18 +16,34 @@ import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.ColorDrawable;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Handler;
import android.support.annotation.IntDef;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
-import android.text.TextUtils.TruncateAt;
+import android.telephony.PhoneNumberFormattingTextWatcher;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.text.TextWatcher;
import android.view.Gravity;
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -160,6 +176,22 @@ public class PaymentRequestUI implements DialogInterface.OnDismissListener, View
void onPaymentRequestReadyToPay(PaymentRequestUI ui);
/**
+ * Called when edit dialog is showing.
gone 2016/06/21 06:04:39 the Edit dialog? Add the in more places?
please use gerrit instead 2016/06/22 02:12:30 Done.
+ */
+ void onPaymentRequestReadyToEdit(PaymentRequestUI ui);
+
+ /**
+ * Called when editor validation completes with error. This can happen, for example, when
+ * user enters an invalid email address.
+ */
+ void onPaymentRequestEditorValidationError(PaymentRequestUI ui);
+
+ /**
+ * Called when editor is dismissed.
+ */
+ void onPaymentRequestEditorDismissed(PaymentRequestUI ui);
+
+ /**
* Called when the result UI is showing.
*/
void onPaymentRequestResultReady(PaymentRequestUI ui);
@@ -170,6 +202,9 @@ public class PaymentRequestUI implements DialogInterface.OnDismissListener, View
void onPaymentRequestDismiss();
}
+ /** The indicator for input fields that are required. */
+ private static final String REQUIRED_FIELD_INDICATOR = "*";
+
/** Length of the animation to either show the UI or expand it to full height. */
private static final int DIALOG_ENTER_ANIMATION_MS = 225;
@@ -184,6 +219,8 @@ public class PaymentRequestUI implements DialogInterface.OnDismissListener, View
private final boolean mRequestContactDetails;
private final Dialog mDialog;
+ private final Dialog mEditDialog;
+ private final Handler mHandler = new Handler();
private final ViewGroup mFullContainer;
private final ViewGroup mRequestView;
private final PaymentResultUIManager mResultView;
@@ -194,6 +231,8 @@ public class PaymentRequestUI implements DialogInterface.OnDismissListener, View
private Button mEditButton;
private Button mPayButton;
private View mCloseButton;
+ private AutoCompleteTextView mPhoneInput;
+ private PhoneNumberFormattingTextWatcher mPhoneFormatter;
private LineItemBreakdownSection mOrderSummarySection;
private ExtraTextSection mShippingSummarySection;
@@ -262,6 +301,8 @@ public class PaymentRequestUI implements DialogInterface.OnDismissListener, View
bottomSheetParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
mFullContainer.addView(mRequestView, bottomSheetParams);
+ mEditDialog = new AlwaysDismissedDialog(activity, R.style.DialogWhenLarge);
+
// Set up the dialog.
mDialog = new AlwaysDismissedDialog(activity, R.style.DialogWhenLarge);
mDialog.setOnDismissListener(this);
@@ -297,7 +338,7 @@ public class PaymentRequestUI implements DialogInterface.OnDismissListener, View
R.string.payments_select_shipping_address_prompt)
: selectedShippingAddress, selectedShippingName);
mShippingSummarySection.setSummaryProperties(
- TruncateAt.MIDDLE, true, null, true);
+ TextUtils.TruncateAt.MIDDLE, true, null, true);
// Indicate the shipping option below the address.
mShippingSummarySection.setExtraText(selectedShippingOptionLabel == null
@@ -547,6 +588,187 @@ public class PaymentRequestUI implements DialogInterface.OnDismissListener, View
}
/**
+ * Displays the editor user interface for the given model.
gone 2016/06/21 06:04:39 Everything new you've added that is editor related
please use gerrit instead 2016/06/22 02:12:31 Done.
+ *
+ * @param editorModel The description of the editor user interface to display.
+ */
+ public void showEditor(final EditorModel editorModel) {
+ final LinearLayout editor = new LinearLayout(mContext);
+ editor.setOrientation(LinearLayout.VERTICAL);
+ TextView title = new TextView(mContext);
+ title.setText(editorModel.getTitle());
+ editor.addView(title);
+
+ final Button done = new Button(mContext);
gone 2016/06/21 06:04:39 Rearrange this code so that the button initializin
please use gerrit instead 2016/06/22 02:12:30 Done.
+ for (int i = 0; i < editorModel.getFields().size(); i++) {
+ final AutoCompleteTextView input = new AutoCompleteTextView(mContext);
+ final EditorFieldModel fieldModel = editorModel.getFields().get(i);
+ input.setTag(fieldModel);
+ input.setHint(fieldModel.getLabel() + REQUIRED_FIELD_INDICATOR);
+ input.setText(fieldModel.getValue());
+ if (fieldModel.getSuggestions() != null && !fieldModel.getSuggestions().isEmpty()) {
+ input.setAdapter(new ArrayAdapter<CharSequence>(mContext,
+ android.R.layout.simple_spinner_dropdown_item,
+ fieldModel.getSuggestions()));
+ input.setThreshold(0);
+ }
gone 2016/06/21 06:04:39 newlines between the blocks
please use gerrit instead 2016/06/22 02:12:30 Done.
+ if (fieldModel.getInputTypeHint() == EditorFieldModel.INPUT_TYPE_HINT_PHONE) {
+ input.setId(R.id.payments_edit_phone_input);
+ input.setInputType(InputType.TYPE_CLASS_PHONE);
+ if (mPhoneFormatter == null) {
+ mPhoneInput = input;
+ new PhoneFormatterTask().execute();
+ } else {
+ input.addTextChangedListener(mPhoneFormatter);
+ }
+ } else if (fieldModel.getInputTypeHint() == EditorFieldModel.INPUT_TYPE_HINT_EMAIL) {
+ input.setId(R.id.payments_edit_email_input);
+ input.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ }
+ input.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ fieldModel.setValue(s.toString());
+ input.getBackground().mutate().setColorFilter(null);
+ input.setError(null);
+ }
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ });
+ input.setOnEditorActionListener(new TextView.OnEditorActionListener() {
gone 2016/06/21 06:04:39 This listener looks to be the same for all element
please use gerrit instead 2016/06/22 02:12:30 Done.
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ done.performClick();
+ return true;
+ } else if (actionId == EditorInfo.IME_ACTION_NEXT) {
+ View next = input.focusSearch(View.FOCUS_FORWARD);
+ if (next != null && next instanceof AutoCompleteTextView) {
+ next.requestFocus();
+ return true;
+ }
+ }
+ return false;
+ }
+ });
+ editor.addView(input);
+ }
+
+ TextView explanation = new TextView(mContext);
+ explanation.setText(mContext.getString(R.string.payments_required_field_message));
+ editor.addView(explanation);
+
+ Button cancel = new Button(mContext);
+ cancel.setId(R.id.payments_edit_cancel_button);
+ cancel.setText(mContext.getString(R.string.cancel));
+ cancel.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ editorModel.cancel();
+ mEditDialog.dismiss();
+ }
+ });
+ editor.addView(cancel);
+
+ done.setId(R.id.payments_edit_done_button);
+ done.setText(mContext.getString(R.string.done));
+ done.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ final List<AutoCompleteTextView> invalidViews = getInvalidViews(editor);
+ if (invalidViews.isEmpty()) {
+ editorModel.done();
+ mEditDialog.dismiss();
+ } else {
+ if (!invalidViews.contains(mEditDialog.getCurrentFocus())) {
+ focusInputFieldAndShowSoftKeyboard(invalidViews.get(0));
+ }
+ ColorFilter errorMessageColorFilter = new PorterDuffColorFilter(
+ ApiCompatibilityUtils.getColor(
+ mContext.getResources(), R.color.input_underline_error_color),
+ PorterDuff.Mode.SRC_IN);
+ for (int i = 0; i < invalidViews.size(); i++) {
+ AutoCompleteTextView invalid = invalidViews.get(i);
+ invalid.setError(((EditorFieldModel) invalid.getTag()).getErrorMessage());
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ invalid.getBackground().mutate().setColorFilter(
+ errorMessageColorFilter);
+ }
+ }
+ if (sObserverForTest != null) {
+ sObserverForTest.onPaymentRequestEditorValidationError(
+ PaymentRequestUI.this);
+ }
+ }
+ }
+ });
+ editor.addView(done);
+
+ mEditDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ mPhoneInput = null;
+ editorModel.cancel();
+ if (sObserverForTest != null) {
+ sObserverForTest.onPaymentRequestEditorDismissed(PaymentRequestUI.this);
+ }
+ }
+ });
+ mEditDialog.setContentView(editor);
+ mEditDialog.show();
+
+ final List<AutoCompleteTextView> invalidViews = getInvalidViews(editor);
+ if (!invalidViews.isEmpty()) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ focusInputFieldAndShowSoftKeyboard(invalidViews.get(0));
gone 2016/06/21 06:04:39 You really shouldn't be forcing a keyboard to show
please use gerrit instead 2016/06/22 02:12:30 This is what we do in CVV prompt. https://cs.chro
gone 2016/06/22 05:24:13 Acknowledged.
+ }
+ });
+ }
+ }
+
+ /**
+ * Avoids disk reads when building a phone formatter.
+ */
+ private class PhoneFormatterTask
gone 2016/06/21 06:04:39 Geez, do we actually get StrictMode violations her
please use gerrit instead 2016/06/22 02:12:30 Yes.
+ extends AsyncTask<Void, Void, PhoneNumberFormattingTextWatcher> {
+ @Override
+ protected PhoneNumberFormattingTextWatcher doInBackground(Void... unused) {
+ return new PhoneNumberFormattingTextWatcher();
+ }
+
+ @Override
+ protected void onPostExecute(PhoneNumberFormattingTextWatcher result) {
+ mPhoneFormatter = result;
+ if (mPhoneInput != null) mPhoneInput.addTextChangedListener(mPhoneFormatter);
+ }
+ }
+
+ private static List<AutoCompleteTextView> getInvalidViews(ViewGroup container) {
gone 2016/06/21 06:04:39 getViewsWithInvalidInformation "invalid" and "inv
please use gerrit instead 2016/06/22 02:12:30 Done.
+ List<AutoCompleteTextView> invalidViews = new ArrayList<>();
+ for (int i = 0; i < container.getChildCount(); i++) {
+ View view = container.getChildAt(i);
+ if (!(view instanceof AutoCompleteTextView)) continue;
+ AutoCompleteTextView textView = (AutoCompleteTextView) view;
+ if (!((EditorFieldModel) textView.getTag()).isValid()) invalidViews.add(textView);
+ }
+ return invalidViews;
+ }
+
+ private void focusInputFieldAndShowSoftKeyboard(View view) {
+ view.requestFocus();
+ InputMethodManager imm =
+ (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
+ view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ if (sObserverForTest != null) sObserverForTest.onPaymentRequestReadyToEdit(this);
+ }
+
+ /**
* Called when user clicks anything in the dialog.
*/
@Override
@@ -967,10 +1189,20 @@ public class PaymentRequestUI implements DialogInterface.OnDismissListener, View
}
@VisibleForTesting
+ public Dialog getEditDialogForTest() {
+ return mEditDialog;
+ }
+
+ @VisibleForTesting
public ViewGroup getShippingAddressSectionForTest() {
return mShippingAddressSection;
}
+ @VisibleForTesting
+ public ViewGroup getContactDetailsSectionForTest() {
+ return mContactDetailsSection;
+ }
+
private void notifyReadyForInput() {
if (sObserverForTest != null && isAcceptingUserInput()) {
sObserverForTest.onPaymentRequestReadyForInput(this);

Powered by Google App Engine
This is Rietveld 408576698