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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java

Issue 2680143002: Use dropdown list for admin areas in pr form. (Closed)
Patch Set: The one with some clean ups, suggested by Math. Created 3 years, 8 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.payments; 5 package org.chromium.chrome.browser.payments;
6 6
7 import android.os.Handler; 7 import android.os.Handler;
8 import android.util.Pair; 8 import android.util.Pair;
9 9
10 import org.chromium.base.Callback; 10 import org.chromium.base.Callback;
11 import org.chromium.chrome.R; 11 import org.chromium.chrome.R;
12 import org.chromium.chrome.browser.autofill.PersonalDataManager; 12 import org.chromium.chrome.browser.autofill.PersonalDataManager;
13 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; 13 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
14 import org.chromium.chrome.browser.autofill.PersonalDataManager.GetSubKeysReques tDelegate;
14 import org.chromium.chrome.browser.autofill.PhoneNumberUtil; 15 import org.chromium.chrome.browser.autofill.PhoneNumberUtil;
15 import org.chromium.chrome.browser.payments.ui.EditorFieldModel; 16 import org.chromium.chrome.browser.payments.ui.EditorFieldModel;
16 import org.chromium.chrome.browser.payments.ui.EditorFieldModel.EditorFieldValid ator; 17 import org.chromium.chrome.browser.payments.ui.EditorFieldModel.EditorFieldValid ator;
17 import org.chromium.chrome.browser.payments.ui.EditorModel; 18 import org.chromium.chrome.browser.payments.ui.EditorModel;
18 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge; 19 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge;
19 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.Ad dressField; 20 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.Ad dressField;
20 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.Ad dressUiComponent; 21 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.Ad dressUiComponent;
21 22
22 import java.util.HashMap; 23 import java.util.HashMap;
23 import java.util.HashSet; 24 import java.util.HashSet;
24 import java.util.List; 25 import java.util.List;
25 import java.util.Locale; 26 import java.util.Locale;
26 import java.util.Map; 27 import java.util.Map;
27 import java.util.Set; 28 import java.util.Set;
28 29
29 import javax.annotation.Nullable; 30 import javax.annotation.Nullable;
30 31
31 /** 32 /**
32 * An address editor. Can be used for either shipping or billing address editing . 33 * An address editor. Can be used for either shipping or billing address editing .
33 */ 34 */
34 public class AddressEditor extends EditorBase<AutofillAddress> { 35 public class AddressEditor
36 extends EditorBase<AutofillAddress> implements GetSubKeysRequestDelegate {
35 private final Handler mHandler = new Handler(); 37 private final Handler mHandler = new Handler();
36 private final Map<Integer, EditorFieldModel> mAddressFields = new HashMap<>( ); 38 private final Map<Integer, EditorFieldModel> mAddressFields = new HashMap<>( );
37 private final Set<CharSequence> mPhoneNumbers = new HashSet<>(); 39 private final Set<CharSequence> mPhoneNumbers = new HashSet<>();
38 @Nullable private AutofillProfileBridge mAutofillProfileBridge; 40 @Nullable
39 @Nullable private EditorFieldModel mCountryField; 41 private AutofillProfileBridge mAutofillProfileBridge;
40 @Nullable private EditorFieldModel mPhoneField; 42 @Nullable
41 @Nullable private EditorFieldValidator mPhoneValidator; 43 private EditorFieldModel mCountryField;
42 @Nullable private List<AddressUiComponent> mAddressUiComponents; 44 @Nullable
43 45 private EditorFieldModel mPhoneField;
46 @Nullable
47 private EditorFieldValidator mPhoneValidator;
48 @Nullable
49 private List<AddressUiComponent> mAddressUiComponents;
50 private boolean mAdminAreasLoaded;
51 private String mRecentlySelectedCountry;
52 private Runnable mCountryChangeCallBack;
Mathieu 2017/03/28 14:43:32 nit: mCountryChangeCallback
Parastoo 2017/03/29 19:33:55 Done.
53 private AutofillProfile mProfile;
54 private EditorModel mEditor;
44 /** 55 /**
45 * Adds the given phone number to the autocomplete set, if it's valid. 56 * Adds the given phone number to the autocomplete set, if it's valid.
46 * 57 *
47 * @param phoneNumber The phone number to possibly add. 58 * @param phoneNumber The phone number to possibly add.
48 */ 59 */
49 public void addPhoneNumberIfValid(@Nullable CharSequence phoneNumber) { 60 public void addPhoneNumberIfValid(@Nullable CharSequence phoneNumber) {
50 if (getPhoneValidator().isValid(phoneNumber)) mPhoneNumbers.add(phoneNum ber); 61 if (getPhoneValidator().isValid(phoneNumber)) mPhoneNumbers.add(phoneNum ber);
51 } 62 }
52 63
53 /** 64 /**
(...skipping 11 matching lines...) Expand all
65 public void edit( 76 public void edit(
66 @Nullable final AutofillAddress toEdit, final Callback<AutofillAddre ss> callback) { 77 @Nullable final AutofillAddress toEdit, final Callback<AutofillAddre ss> callback) {
67 super.edit(toEdit, callback); 78 super.edit(toEdit, callback);
68 79
69 if (mAutofillProfileBridge == null) mAutofillProfileBridge = new Autofil lProfileBridge(); 80 if (mAutofillProfileBridge == null) mAutofillProfileBridge = new Autofil lProfileBridge();
70 81
71 // If |toEdit| is null, we're creating a new autofill profile with the c ountry code of the 82 // If |toEdit| is null, we're creating a new autofill profile with the c ountry code of the
72 // default locale on this device. 83 // default locale on this device.
73 boolean isNewAddress = toEdit == null; 84 boolean isNewAddress = toEdit == null;
74 85
75 // Ensure that |address| and |profile| are always not null. 86 // Ensure that |address| and |mProfile| are always not null.
76 final AutofillAddress address = 87 final AutofillAddress address =
77 isNewAddress ? new AutofillAddress(mContext, new AutofillProfile ()) : toEdit; 88 isNewAddress ? new AutofillAddress(mContext, new AutofillProfile ()) : toEdit;
78 final AutofillProfile profile = address.getProfile(); 89 mProfile = address.getProfile();
79 90
80 // The title of the editor depends on whether we're adding a new address or editing an 91 // The title of the editor depends on whether we're adding a new address or editing an
81 // existing address. 92 // existing address.
82 final EditorModel editor = 93 mEditor =
83 new EditorModel(isNewAddress 94 new EditorModel(isNewAddress ? mContext.getString(R.string.autof ill_create_profile)
84 ? mContext.getString(R.string.autofill_create_profile) 95 : toEdit.getEditTitle());
85 : toEdit.getEditTitle()); 96
97 // When edit is called, a new form is started, so the country on the
98 // drop-down list is not changed. => mRecentlySelectedCountry should be null.
99 mRecentlySelectedCountry = null;
86 100
87 // The country dropdown is always present on the editor. 101 // The country dropdown is always present on the editor.
88 if (mCountryField == null) { 102 if (mCountryField == null) {
89 mCountryField = EditorFieldModel.createDropdown( 103 mCountryField = EditorFieldModel.createDropdown(
90 mContext.getString(R.string.autofill_profile_editor_country) , 104 mContext.getString(R.string.autofill_profile_editor_country) ,
91 AutofillProfileBridge.getSupportedCountries(), 105 AutofillProfileBridge.getSupportedCountries(),
92 null /* hint */); 106 null /* hint */);
93 } 107 }
94 108
95 // Changing the country will update which fields are in the model. The a ctual fields are not 109 // Changing the country will update which fields are in the model. The a ctual fields are not
96 // discarded, so their contents are preserved. 110 // discarded, so their contents are preserved.
97 mCountryField.setDropdownCallback(new Callback<Pair<String, Runnable>>() { 111 mCountryField.setDropdownCallback(new Callback<Pair<String, Runnable>>() {
98 @Override 112 @Override
113 /*
114 * If the selected country on the country dropdown list is changed,
115 * the first element of eventData is the recently selected dropdown key,
116 * the second element is the callback to invoke for when the dropdow n
117 * change has been processed.
118 */
99 public void onResult(Pair<String, Runnable> eventData) { 119 public void onResult(Pair<String, Runnable> eventData) {
100 editor.removeAllFields(); 120 mEditor.removeAllFields();
101 editor.addField(mCountryField); 121 mRecentlySelectedCountry = eventData.first;
102 addAddressTextFieldsToEditor(editor, eventData.first, 122 mCountryChangeCallBack = eventData.second;
103 Locale.getDefault().getLanguage()); 123 loadAdminAreas();
104 editor.addField(mPhoneField);
105
106 // Notify EditorView that the fields in the model have changed. EditorView should
107 // re-read the model and update the UI accordingly.
108 mHandler.post(eventData.second);
109 } 124 }
110 }); 125 });
111 126
112 // Country dropdown is cached, so the selected item needs to be updated for the new profile 127 // Country dropdown is cached, so the selected item needs to be updated for the new profile
113 // that's being edited. This will not fire the dropdown callback. 128 // that's being edited. This will not fire the dropdown callback.
114 mCountryField.setValue(AutofillAddress.getCountryCode(profile)); 129 mCountryField.setValue(AutofillAddress.getCountryCode(mProfile));
115 editor.addField(mCountryField);
116 130
117 // There's a finite number of fields for address editing. Changing the c ountry will re-order 131 // There's a finite number of fields for address editing. Changing the c ountry will re-order
118 // and relabel the fields. The meaning of each field remains the same. 132 // and relabel the fields. The meaning of each field remains the same.
119 if (mAddressFields.isEmpty()) { 133 if (mAddressFields.isEmpty()) {
120 // City, dependent locality, and organization don't have any special formatting hints. 134 // City, dependent locality, and organization don't have any special formatting hints.
121 mAddressFields.put(AddressField.LOCALITY, EditorFieldModel.createTex tInput()); 135 mAddressFields.put(AddressField.LOCALITY, EditorFieldModel.createTex tInput());
122 mAddressFields.put(AddressField.DEPENDENT_LOCALITY, EditorFieldModel .createTextInput()); 136 mAddressFields.put(AddressField.DEPENDENT_LOCALITY, EditorFieldModel .createTextInput());
123 mAddressFields.put(AddressField.ORGANIZATION, EditorFieldModel.creat eTextInput()); 137 mAddressFields.put(AddressField.ORGANIZATION, EditorFieldModel.creat eTextInput());
124 138
125 // State should be formatted in all capitals.
126 mAddressFields.put(AddressField.ADMIN_AREA, EditorFieldModel.createT extInput(
127 EditorFieldModel.INPUT_TYPE_HINT_REGION));
128
129 // Sorting code and postal code (a.k.a. ZIP code) should show both l etters and digits on 139 // Sorting code and postal code (a.k.a. ZIP code) should show both l etters and digits on
130 // the keyboard, if possible. 140 // the keyboard, if possible.
131 mAddressFields.put(AddressField.SORTING_CODE, EditorFieldModel.creat eTextInput( 141 mAddressFields.put(AddressField.SORTING_CODE, EditorFieldModel.creat eTextInput(
132 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC)); 142 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC));
133 mAddressFields.put(AddressField.POSTAL_CODE, EditorFieldModel.create TextInput( 143 mAddressFields.put(AddressField.POSTAL_CODE, EditorFieldModel.create TextInput(
134 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC)); 144 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC));
135 145
136 // Street line field can contain \n to indicate line breaks. 146 // Street line field can contain \n to indicate line breaks.
137 mAddressFields.put(AddressField.STREET_ADDRESS, EditorFieldModel.cre ateTextInput( 147 mAddressFields.put(AddressField.STREET_ADDRESS, EditorFieldModel.cre ateTextInput(
138 EditorFieldModel.INPUT_TYPE_HINT_STREET_LINES)); 148 EditorFieldModel.INPUT_TYPE_HINT_STREET_LINES));
139 149
140 // Android has special formatting rules for names. 150 // Android has special formatting rules for names.
141 mAddressFields.put(AddressField.RECIPIENT, EditorFieldModel.createTe xtInput( 151 mAddressFields.put(AddressField.RECIPIENT, EditorFieldModel.createTe xtInput(
142 EditorFieldModel.INPUT_TYPE_HINT_PERSON_NAME)); 152 EditorFieldModel.INPUT_TYPE_HINT_PERSON_NAME));
143 } 153 }
144 154
145 // Address fields are cached, so their values need to be updated for eve ry new profile
146 // that's being edited.
147 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) {
148 entry.getValue().setValue(AutofillAddress.getProfileField(profile, e ntry.getKey()));
149 }
150
151 // Both country code and language code dictate which fields should be ad ded to the editor.
152 // For example, "US" will not add dependent locality to the editor. A "J P" address will
153 // start with a person's full name or a with a prefecture name, dependin g on whether the
154 // language code is "ja-Latn" or "ja".
155 addAddressTextFieldsToEditor(editor, profile.getCountryCode(), profile.g etLanguageCode());
156 155
157 // Phone number is present and required for all countries. 156 // Phone number is present and required for all countries.
158 if (mPhoneField == null) { 157 if (mPhoneField == null) {
159 mPhoneField = EditorFieldModel.createTextInput(EditorFieldModel.INPU T_TYPE_HINT_PHONE, 158 mPhoneField = EditorFieldModel.createTextInput(EditorFieldModel.INPU T_TYPE_HINT_PHONE,
160 mContext.getString(R.string.autofill_profile_editor_phone_nu mber), 159 mContext.getString(R.string.autofill_profile_editor_phone_nu mber),
161 mPhoneNumbers, getPhoneValidator(), null, 160 mPhoneNumbers, getPhoneValidator(), null,
162 mContext.getString(R.string.payments_field_required_validati on_message), 161 mContext.getString(R.string.payments_field_required_validati on_message),
163 mContext.getString(R.string.payments_phone_invalid_validatio n_message), null); 162 mContext.getString(R.string.payments_phone_invalid_validatio n_message), null);
164 } 163 }
165 164
166 // Phone number field is cached, so its value needs to be updated for ev ery new profile 165 // Phone number field is cached, so its value needs to be updated for ev ery new profile
167 // that's being edited. 166 // that's being edited.
168 mPhoneField.setValue(profile.getPhoneNumber()); 167 mPhoneField.setValue(mProfile.getPhoneNumber());
169 editor.addField(mPhoneField);
170 168
171 // If the user clicks [Cancel], send |toEdit| address back to the caller , which was the 169 // If the user clicks [Cancel], send |toEdit| address back to the caller , which was the
172 // original state (could be null, a complete address, a partial address) . 170 // original state (could be null, a complete address, a partial address) .
173 editor.setCancelCallback(new Runnable() { 171 mEditor.setCancelCallback(new Runnable() {
174 @Override 172 @Override
175 public void run() { 173 public void run() {
174 /* This makes sure that onSubKeysReceived returns early if it's
175 ever called when Cancel has already occurred.*/
176 mAdminAreasLoaded = true;
177 PersonalDataManager.getInstance().cancelPendingGetSubKeys();
176 callback.onResult(toEdit); 178 callback.onResult(toEdit);
177 } 179 }
178 }); 180 });
179 181
180 // If the user clicks [Done], save changes on disk, mark the address "co mplete," and send it 182 // If the user clicks [Done], save changes on disk, mark the address "co mplete," and send it
181 // back to the caller. 183 // back to the caller.
182 editor.setDoneCallback(new Runnable() { 184 mEditor.setDoneCallback(new Runnable() {
183 @Override 185 @Override
184 public void run() { 186 public void run() {
185 commitChanges(profile); 187 mAdminAreasLoaded = true;
186 address.completeAddress(profile); 188 PersonalDataManager.getInstance().cancelPendingGetSubKeys();
189 commitChanges(mProfile);
190 address.completeAddress(mProfile);
187 callback.onResult(address); 191 callback.onResult(address);
188 } 192 }
189 }); 193 });
190 194
191 mEditorView.show(editor); 195 loadAdminAreas();
192 } 196 }
193 197
194 /** Saves the edited profile on disk. */ 198 /** Saves the edited profile on disk. */
195 private void commitChanges(AutofillProfile profile) { 199 private void commitChanges(AutofillProfile profile) {
196 // Country code and phone number are always required and are always coll ected from the 200 // Country code and phone number are always required and are always coll ected from the
197 // editor model. 201 // editor model.
198 profile.setCountryCode(mCountryField.getValue().toString()); 202 profile.setCountryCode(mCountryField.getValue().toString());
199 profile.setPhoneNumber(mPhoneField.getValue().toString()); 203 profile.setPhoneNumber(mPhoneField.getValue().toString());
200 204
201 // Autofill profile bridge normalizes the language code for the autofill profile. 205 // Autofill profile bridge normalizes the language code for the autofill profile.
(...skipping 11 matching lines...) Expand all
213 217
214 // Clear the fields that are hidden from the user interface, so 218 // Clear the fields that are hidden from the user interface, so
215 // AutofillAddress.toPaymentAddress() will send them to the renderer as empty strings. 219 // AutofillAddress.toPaymentAddress() will send them to the renderer as empty strings.
216 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) { 220 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) {
217 if (!visibleFields.contains(entry.getKey())) { 221 if (!visibleFields.contains(entry.getKey())) {
218 setProfileField(profile, entry.getKey(), ""); 222 setProfileField(profile, entry.getKey(), "");
219 } 223 }
220 } 224 }
221 225
222 // Save the edited autofill profile locally. 226 // Save the edited autofill profile locally.
223 profile.setGUID(PersonalDataManager.getInstance().setProfileToLocal(prof ile)); 227 profile.setGUID(PersonalDataManager.getInstance().setProfileToLocal(mPro file));
224 profile.setIsLocal(true); 228 profile.setIsLocal(true);
225 } 229 }
226 230
227 /** Writes the given value into the specified autofill profile field. */ 231 /** Writes the given value into the specified autofill profile field. */
228 private static void setProfileField( 232 private static void setProfileField(
229 AutofillProfile profile, int field, @Nullable CharSequence value) { 233 AutofillProfile profile, int field, @Nullable CharSequence value) {
230 assert profile != null; 234 assert profile != null;
231 switch (field) { 235 switch (field) {
232 case AddressField.COUNTRY: 236 case AddressField.COUNTRY:
233 profile.setCountryCode(ensureNotNull(value)); 237 profile.setCountryCode(ensureNotNull(value));
(...skipping 24 matching lines...) Expand all
258 return; 262 return;
259 } 263 }
260 264
261 assert false; 265 assert false;
262 } 266 }
263 267
264 private static String ensureNotNull(@Nullable CharSequence value) { 268 private static String ensureNotNull(@Nullable CharSequence value) {
265 return value == null ? "" : value.toString(); 269 return value == null ? "" : value.toString();
266 } 270 }
267 271
272 private void setAddressFieldValuesFromCache() {
273 // Address fields are cached, so their values need to be updated for eve ry new profile
274 // that's being edited.
275 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) {
276 entry.getValue().setValue(AutofillAddress.getProfileField(mProfile, entry.getKey()));
277 }
278 }
279
280 /* Callback of the sub keys request that is called when the sub keys are loa ded.
281 Here the sub keys are admin areas (sub keys of the region=country.) */
282 @Override
283 public void onSubKeysReceived(String[] adminAreas) {
284 if (mAdminAreasLoaded) return;
285 mAdminAreasLoaded = true;
286
287 // If can't get admin areas from server or there is no admin area on the
288 // server, then use text field. Otherwise, use drop down list.
289 if (adminAreas == null || adminAreas.length == 0
290 || PersonalDataManager.getInstance().isOnTestingMode()) {
291 mAddressFields.put(AddressField.ADMIN_AREA, EditorFieldModel.createT extInput());
292 } else {
293 mAddressFields.put(AddressField.ADMIN_AREA, EditorFieldModel.createD ropdown());
294 }
295
296 /* Admin Areas need to be fetched in two cases.
297 1. Initial loading of the form.
298 2. When the selected country is changed in the form.
299 mRecentlySelectedCountry is not null <=> the 2nd case */
300 if (mRecentlySelectedCountry != null) {
301 // Both country code and language code dictate which fields should b e added to the
302 // editor.
303 // For example, "US" will not add dependent locality to the editor. A "JP" address will
304 // start with a person's full name or a with a prefecture name, depe nding on whether the
305 // language code is "ja-Latn" or "ja".
306 addAddressFieldsToEditor(mRecentlySelectedCountry,
307 Locale.getDefault().getLanguage(),
308 adminAreas);
309 // Notify EditorView that the fields in the model have changed. Edit orView should
310 // re-read the model and update the UI accordingly.
311 mHandler.post(mCountryChangeCallBack);
312 } else {
313 // This should be called when all required fields are put in mAddres sField.
314 setAddressFieldValuesFromCache();
315 addAddressFieldsToEditor(mProfile.getCountryCode(),
316 mProfile.getLanguageCode(), adminAreas);
317 mEditorView.show(mEditor);
318 }
319 }
320
321 /** Requests the list of admin areas. */
322 public void loadAdminAreas() {
Mathieu 2017/03/28 14:43:32 make private? Rename loadAdminAreasForCountry(Stri
Parastoo 2017/03/29 19:33:55 Done.
323 String countryCode = (mRecentlySelectedCountry != null)
324 ? mRecentlySelectedCountry
325 : mProfile.getCountryCode();
326
327 // Used to check if the callback is called (for time-out).
328 mAdminAreasLoaded = false;
329
330 // In each rule, admin area keys are saved under sub keys of country.
331 PersonalDataManager.getInstance().loadRulesForSubKeys(countryCode);
332 PersonalDataManager.getInstance().getRegionSubKeys(countryCode, this);
333 onAdminAreasLoading();
334 }
335
336 /* In case the the admin areas are not loaded yet, starts a timer to cancel the request. */
337 public void onAdminAreasLoading() {
338 if (!mAdminAreasLoaded) {
339 new Handler().postDelayed(new Runnable() {
340 @Override
341 public void run() {
342 if (!mAdminAreasLoaded) {
343 onSubKeysReceived(null);
344 PersonalDataManager.getInstance().cancelPendingGetSubKey s();
345 }
346 }
347 }, PersonalDataManager.getInstance().getRequestTimeoutMS());
348 }
349 }
350
268 /** 351 /**
269 * Adds text fields to the editor model based on the country and language co de of the profile 352 * Adds fields to the editor model based on the country and language code of
270 * that's being edited. 353 * the profile that's being edited.
271 */ 354 */
272 private void addAddressTextFieldsToEditor( 355 private void addAddressFieldsToEditor(
273 EditorModel container, String countryCode, String languageCode) { 356 String countryCode, String languageCode, String[] adminAreas) {
274 mAddressUiComponents = mAutofillProfileBridge.getAddressUiComponents(cou ntryCode, 357 mAddressUiComponents =
275 languageCode); 358 mAutofillProfileBridge.getAddressUiComponents(countryCode, langu ageCode);
276 359 // In terms of order, country must be the first field.
360 mEditor.addField(mCountryField);
277 for (int i = 0; i < mAddressUiComponents.size(); i++) { 361 for (int i = 0; i < mAddressUiComponents.size(); i++) {
278 AddressUiComponent component = mAddressUiComponents.get(i); 362 AddressUiComponent component = mAddressUiComponents.get(i);
279 363
280 // The country field is a dropdown, so there's no need to add a text field for it.
281 if (component.id == AddressField.COUNTRY) continue;
282
283 EditorFieldModel field = mAddressFields.get(component.id); 364 EditorFieldModel field = mAddressFields.get(component.id);
284 // Labels depend on country, e.g., state is called province in some countries. These are 365 // Labels depend on country, e.g., state is called province in some countries. These are
285 // already localized. 366 // already localized.
286 field.setLabel(component.label); 367 field.setLabel(component.label);
287 field.setIsFullLine(component.isFullLine); 368 field.setIsFullLine(component.isFullLine);
288 369
370 if (component.id == AddressField.ADMIN_AREA && field.isDropdownField ()) {
371 field.setDropdownKeyValues(
372 mAutofillProfileBridge.getAdminAreaDropdownList(adminAre as));
373 }
374
289 // Libaddressinput formats do not always require the full name (RECI PIENT), but 375 // Libaddressinput formats do not always require the full name (RECI PIENT), but
290 // PaymentRequest does. 376 // PaymentRequest does.
291 if (component.isRequired || component.id == AddressField.RECIPIENT) { 377 if (component.isRequired || component.id == AddressField.RECIPIENT) {
292 field.setRequiredErrorMessage(mContext.getString( 378 field.setRequiredErrorMessage(mContext.getString(
293 R.string.payments_field_required_validation_message)); 379 R.string.payments_field_required_validation_message));
294 } else { 380 } else {
295 field.setRequiredErrorMessage(null); 381 field.setRequiredErrorMessage(null);
296 } 382 }
297 383 mEditor.addField(field);
298 container.addField(field);
299 } 384 }
385 // Phone number must be the last field.
386 mEditor.addField(mPhoneField);
300 } 387 }
301 388
302 private EditorFieldValidator getPhoneValidator() { 389 private EditorFieldValidator getPhoneValidator() {
303 if (mPhoneValidator == null) { 390 if (mPhoneValidator == null) {
304 mPhoneValidator = new EditorFieldValidator() { 391 mPhoneValidator = new EditorFieldValidator() {
305 @Override 392 @Override
306 public boolean isValid(@Nullable CharSequence value) { 393 public boolean isValid(@Nullable CharSequence value) {
307 return value != null && PhoneNumberUtil.isValidNumber(value. toString()); 394 return value != null && PhoneNumberUtil.isValidNumber(value. toString());
308 } 395 }
309 396
310 @Override 397 @Override
311 public boolean isLengthMaximum(@Nullable CharSequence value) { 398 public boolean isLengthMaximum(@Nullable CharSequence value) {
312 return false; 399 return false;
313 } 400 }
314 }; 401 };
315 } 402 }
316 return mPhoneValidator; 403 return mPhoneValidator;
317 } 404 }
318 } 405 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698