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

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

Powered by Google App Engine
This is Rietveld 408576698