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

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

Powered by Google App Engine
This is Rietveld 408576698