Skip to main content

inset_services/
autofill.rs

1//! Flutter counterpart: `services/autofill.dart`.
2//!
3//! `AutofillConfiguration` lives in `inset-embedder` (re-exported from
4//! `text_input.rs`) because `View` names `TextInputConfiguration`.
5
6use inset_foundation::{App, Handle, HandleId};
7
8use crate::text_input::{
9    AnyTextInputClient, TextEditingValue, TextInput, TextInputConfiguration, TextInputConnection,
10};
11
12/// A collection of commonly used autofill hint strings on different platforms.
13///
14/// Each hint is pre-defined on at least one supported platform. See their
15/// documentation for their availability on each platform, and the platform
16/// values each autofill hint corresponds to.
17pub struct AutofillHints;
18
19impl AutofillHints {
20    /// The input field expects an address locality (city/town).
21    ///
22    /// This hint will be translated to the below values on different platforms:
23    ///
24    /// * Android: [AUTOFILL_HINT_POSTAL_ADDRESS_LOCALITY](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_POSTAL_ADDRESS_LOCALITY).
25    /// * iOS: [addressCity](https://developer.apple.com/documentation/uikit/uitextcontenttype).
26    /// * Otherwise, the hint string will be used as-is.
27    pub const ADDRESS_CITY: &str = "addressCity";
28
29    /// The input field expects a city name combined with a state name.
30    ///
31    /// This hint will be translated to the below values on different platforms:
32    ///
33    /// * iOS: [addressCityAndState](https://developer.apple.com/documentation/uikit/uitextcontenttype).
34    /// * Otherwise, the hint string will be used as-is.
35    pub const ADDRESS_CITY_AND_STATE: &str = "addressCityAndState";
36
37    /// The input field expects a region/state.
38    ///
39    /// This hint will be translated to the below values on different platforms:
40    ///
41    /// * Android: [AUTOFILL_HINT_POSTAL_ADDRESS_REGION](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_POSTAL_ADDRESS_REGION).
42    /// * iOS: [addressState](https://developer.apple.com/documentation/uikit/uitextcontenttype).
43    /// * Otherwise, the hint string will be used as-is.
44    pub const ADDRESS_STATE: &str = "addressState";
45
46    /// The input field expects a person's full birth date.
47    ///
48    /// This hint will be translated to the below values on different platforms:
49    ///
50    /// * Android: [AUTOFILL_HINT_BIRTH_DATE_FULL](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_BIRTH_DATE_FULL).
51    /// * web: ["bday"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
52    /// * Otherwise, the hint string will be used as-is.
53    pub const BIRTHDAY: &str = "birthday";
54
55    /// The input field expects a person's birth day(of the month).
56    ///
57    /// This hint will be translated to the below values on different platforms:
58    ///
59    /// * Android: [AUTOFILL_HINT_BIRTH_DATE_DAY](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_BIRTH_DATE_DAY).
60    /// * web: ["bday-day"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
61    /// * Otherwise, the hint string will be used as-is.
62    pub const BIRTHDAY_DAY: &str = "birthdayDay";
63
64    /// The input field expects a person's birth month.
65    ///
66    /// This hint will be translated to the below values on different platforms:
67    ///
68    /// * Android: [AUTOFILL_HINT_BIRTH_DATE_MONTH](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_BIRTH_DATE_MONTH).
69    /// * web: ["bday-month"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
70    /// * Otherwise, the hint string will be used as-is.
71    pub const BIRTHDAY_MONTH: &str = "birthdayMonth";
72
73    /// The input field expects a person's birth year.
74    ///
75    /// This hint will be translated to the below values on different platforms:
76    ///
77    /// * Android: [AUTOFILL_HINT_BIRTH_DATE_YEAR](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_BIRTH_DATE_YEAR).
78    /// * web: ["bday-year"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
79    /// * Otherwise, the hint string will be used as-is.
80    pub const BIRTHDAY_YEAR: &str = "birthdayYear";
81
82    /// The input field expects an
83    /// [ISO 3166-1-alpha-2](https://www.iso.org/standard/63545.html) country code.
84    ///
85    /// This hint will be translated to the below values on different platforms:
86    ///
87    /// * web: ["country"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
88    /// * Otherwise, the hint string will be used as-is.
89    pub const COUNTRY_CODE: &str = "countryCode";
90
91    /// The input field expects a country name.
92    ///
93    /// This hint will be translated to the below values on different platforms:
94    ///
95    /// * Android: [AUTOFILL_HINT_POSTAL_ADDRESS_COUNTRY](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_POSTAL_ADDRESS_COUNTRY).
96    /// * iOS: [countryName](https://developer.apple.com/documentation/uikit/uitextcontenttype).
97    /// * web: ["country-name"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
98    /// * Otherwise, the hint string will be used as-is.
99    pub const COUNTRY_NAME: &str = "countryName";
100
101    /// The input field expects a credit card expiration date.
102    ///
103    /// This hint will be translated to the below values on different platforms:
104    ///
105    /// * Android: [AUTOFILL_HINT_CREDIT_CARD_NUMBER](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_CREDIT_CARD_NUMBER).
106    /// * web: ["cc-exp"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
107    /// * Otherwise, the hint string will be used as-is.
108    pub const CREDIT_CARD_EXPIRATION_DATE: &str = "creditCardExpirationDate";
109
110    /// The input field expects a credit card expiration day.
111    ///
112    /// This hint will be translated to the below values on different platforms:
113    ///
114    /// * Android: [AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY).
115    /// * Otherwise, the hint string will be used as-is.
116    pub const CREDIT_CARD_EXPIRATION_DAY: &str = "creditCardExpirationDay";
117
118    /// The input field expects a credit card expiration month.
119    ///
120    /// This hint will be translated to the below values on different platforms:
121    ///
122    /// * Android: [AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH).
123    /// * web: ["cc-exp-month"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
124    /// * Otherwise, the hint string will be used as-is.
125    pub const CREDIT_CARD_EXPIRATION_MONTH: &str = "creditCardExpirationMonth";
126
127    /// The input field expects a credit card expiration year.
128    ///
129    /// This hint will be translated to the below values on different platforms:
130    ///
131    /// * Android: [AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR).
132    /// * web: ["cc-exp-year"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
133    /// * Otherwise, the hint string will be used as-is.
134    pub const CREDIT_CARD_EXPIRATION_YEAR: &str = "creditCardExpirationYear";
135
136    /// The input field expects the holder's last/family name as given on a credit
137    /// card.
138    ///
139    /// This hint will be translated to the below values on different platforms:
140    ///
141    /// * web: ["cc-family-name"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
142    /// * Otherwise, the hint string will be used as-is.
143    pub const CREDIT_CARD_FAMILY_NAME: &str = "creditCardFamilyName";
144
145    /// The input field expects the holder's first/given name as given on a credit
146    /// card.
147    ///
148    /// This hint will be translated to the below values on different platforms:
149    ///
150    /// * web: ["cc-given-name"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
151    /// * Otherwise, the hint string will be used as-is.
152    pub const CREDIT_CARD_GIVEN_NAME: &str = "creditCardGivenName";
153
154    /// The input field expects the holder's middle name as given on a credit
155    /// card.
156    ///
157    /// This hint will be translated to the below values on different platforms:
158    ///
159    /// * web: ["cc-additional-name"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
160    /// * Otherwise, the hint string will be used as-is.
161    pub const CREDIT_CARD_MIDDLE_NAME: &str = "creditCardMiddleName";
162
163    /// The input field expects the holder's full name as given on a credit card.
164    ///
165    /// This hint will be translated to the below values on different platforms:
166    ///
167    /// * web: ["cc-name"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
168    /// * Otherwise, the hint string will be used as-is.
169    pub const CREDIT_CARD_NAME: &str = "creditCardName";
170
171    /// The input field expects a credit card number.
172    ///
173    /// This hint will be translated to the below values on different platforms:
174    ///
175    /// * Android: [AUTOFILL_HINT_CREDIT_CARD_NUMBER](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_CREDIT_CARD_NUMBER).
176    /// * iOS: [creditCardNumber](https://developer.apple.com/documentation/uikit/uitextcontenttype).
177    /// * web: ["cc-number"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
178    /// * Otherwise, the hint string will be used as-is.
179    pub const CREDIT_CARD_NUMBER: &str = "creditCardNumber";
180
181    /// The input field expects a credit card security code.
182    ///
183    /// This hint will be translated to the below values on different platforms:
184    ///
185    /// * Android: [AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE).
186    /// * web: ["cc-csc"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
187    /// * Otherwise, the hint string will be used as-is.
188    pub const CREDIT_CARD_SECURITY_CODE: &str = "creditCardSecurityCode";
189
190    /// The input field expects the type of a credit card, for example "Visa".
191    ///
192    /// This hint will be translated to the below values on different platforms:
193    ///
194    /// * web: ["cc-type"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
195    /// * Otherwise, the hint string will be used as-is.
196    pub const CREDIT_CARD_TYPE: &str = "creditCardType";
197
198    /// The input field expects an email address.
199    ///
200    /// This hint will be translated to the below values on different platforms:
201    ///
202    /// * Android: [AUTOFILL_HINT_EMAIL_ADDRESS](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_EMAIL_ADDRESS).
203    /// * iOS: [emailAddress](https://developer.apple.com/documentation/uikit/uitextcontenttype).
204    /// * web: ["email"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
205    /// * Otherwise, the hint string will be used as-is.
206    pub const EMAIL: &str = "email";
207
208    /// The input field expects a person's last/family name.
209    ///
210    /// This hint will be translated to the below values on different platforms:
211    ///
212    /// * Android: [AUTOFILL_HINT_PERSON_NAME_FAMILY](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PERSON_NAME_FAMILY).
213    /// * iOS: [familyName](https://developer.apple.com/documentation/uikit/uitextcontenttype).
214    /// * web: ["family-name"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
215    /// * Otherwise, the hint string will be used as-is.
216    pub const FAMILY_NAME: &str = "familyName";
217
218    /// The input field expects a street address that fully identifies a location.
219    ///
220    /// This hint will be translated to the below values on different platforms:
221    ///
222    /// * Android: [AUTOFILL_HINT_POSTAL_ADDRESS_STREET_ADDRESS](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_POSTAL_ADDRESS_STREET_ADDRESS).
223    /// * iOS: [fullStreetAddress](https://developer.apple.com/documentation/uikit/uitextcontenttype).
224    /// * web: ["street-address"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
225    /// * Otherwise, the hint string will be used as-is.
226    pub const FULL_STREET_ADDRESS: &str = "fullStreetAddress";
227
228    /// The input field expects a gender.
229    ///
230    /// This hint will be translated to the below values on different platforms:
231    ///
232    /// * Android: [AUTOFILL_HINT_GENDER](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_GENDER).
233    /// * web: ["sex"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
234    /// * Otherwise, the hint string will be used as-is.
235    pub const GENDER: &str = "gender";
236
237    /// The input field expects a person's first/given name.
238    ///
239    /// This hint will be translated to the below values on different platforms:
240    ///
241    /// * Android: [AUTOFILL_HINT_PERSON_NAME_GIVEN](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PERSON_NAME_GIVEN).
242    /// * iOS: [givenName](https://developer.apple.com/documentation/uikit/uitextcontenttype).
243    /// * web: ["given-name"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
244    /// * Otherwise, the hint string will be used as-is.
245    pub const GIVEN_NAME: &str = "givenName";
246
247    /// The input field expects a URL representing an instant messaging protocol
248    /// endpoint.
249    ///
250    /// This hint will be translated to the below values on different platforms:
251    ///
252    /// * web: ["impp"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
253    /// * Otherwise, the hint string will be used as-is.
254    pub const IMPP: &str = "impp";
255
256    /// The input field expects a job title.
257    ///
258    /// This hint will be translated to the below values on different platforms:
259    ///
260    /// * iOS: [jobTitle](https://developer.apple.com/documentation/uikit/uitextcontenttype).
261    /// * web: ["organization-title"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
262    /// * Otherwise, the hint string will be used as-is.
263    pub const JOB_TITLE: &str = "jobTitle";
264
265    /// The input field expects the preferred language of the user.
266    ///
267    /// This hint will be translated to the below values on different platforms:
268    ///
269    /// * web: ["language"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
270    /// * Otherwise, the hint string will be used as-is.
271    pub const LANGUAGE: &str = "language";
272
273    /// The input field expects a location, such as a point of interest, an
274    /// address,or another way to identify a location.
275    ///
276    /// This hint will be translated to the below values on different platforms:
277    ///
278    /// * iOS: [location](https://developer.apple.com/documentation/uikit/uitextcontenttype).
279    /// * Otherwise, the hint string will be used as-is.
280    pub const LOCATION: &str = "location";
281
282    /// The input field expects a person's middle initial.
283    ///
284    /// This hint will be translated to the below values on different platforms:
285    ///
286    /// * Android: [AUTOFILL_HINT_PERSON_NAME_MIDDLE_INITIAL](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PERSON_NAME_MIDDLE_INITIAL).
287    /// * Otherwise, the hint string will be used as-is.
288    pub const MIDDLE_INITIAL: &str = "middleInitial";
289
290    /// The input field expects a person's middle name.
291    ///
292    /// This hint will be translated to the below values on different platforms:
293    ///
294    /// * Android: [AUTOFILL_HINT_PERSON_NAME_MIDDLE](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PERSON_NAME_MIDDLE).
295    /// * iOS: [middleName](https://developer.apple.com/documentation/uikit/uitextcontenttype).
296    /// * web: ["additional-name"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
297    /// * Otherwise, the hint string will be used as-is.
298    pub const MIDDLE_NAME: &str = "middleName";
299
300    /// The input field expects a person's full name.
301    ///
302    /// This hint will be translated to the below values on different platforms:
303    ///
304    /// * Android: [AUTOFILL_HINT_PERSON_NAME](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PERSON_NAME).
305    /// * iOS: [name](https://developer.apple.com/documentation/uikit/uitextcontenttype).
306    /// * web: ["name"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
307    /// * Otherwise, the hint string will be used as-is.
308    pub const NAME: &str = "name";
309
310    /// The input field expects a person's name prefix or title, such as "Dr.".
311    ///
312    /// This hint will be translated to the below values on different platforms:
313    ///
314    /// * Android: [AUTOFILL_HINT_PERSON_NAME_PREFIX](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PERSON_NAME_PREFIX).
315    /// * iOS: [namePrefix](https://developer.apple.com/documentation/uikit/uitextcontenttype).
316    /// * web: ["honorific-prefix"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
317    /// * Otherwise, the hint string will be used as-is.
318    pub const NAME_PREFIX: &str = "namePrefix";
319
320    /// The input field expects a person's name suffix, such as "Jr.".
321    ///
322    /// This hint will be translated to the below values on different platforms:
323    ///
324    /// * Android: [AUTOFILL_HINT_PERSON_NAME_SUFFIX](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PERSON_NAME_SUFFIX).
325    /// * iOS: [nameSuffix](https://developer.apple.com/documentation/uikit/uitextcontenttype).
326    /// * web: ["honorific-suffix"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
327    /// * Otherwise, the hint string will be used as-is.
328    pub const NAME_SUFFIX: &str = "nameSuffix";
329
330    /// The input field expects a newly created password for save/update.
331    ///
332    /// This hint will be translated to the below values on different platforms:
333    ///
334    /// * Android: [AUTOFILL_HINT_NEW_PASSWORD](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_NEW_PASSWORD).
335    /// * iOS: [newPassword](https://developer.apple.com/documentation/uikit/uitextcontenttype).
336    /// * web: ["new-password"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
337    /// * Otherwise, the hint string will be used as-is.
338    pub const NEW_PASSWORD: &str = "newPassword";
339
340    /// The input field expects a newly created username for save/update.
341    ///
342    /// This hint will be translated to the below values on different platforms:
343    ///
344    /// * Android: [AUTOFILL_HINT_NEW_USERNAME](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_NEW_USERNAME).
345    /// * Otherwise, the hint string will be used as-is.
346    pub const NEW_USERNAME: &str = "newUsername";
347
348    /// The input field expects a nickname.
349    ///
350    /// This hint will be translated to the below values on different platforms:
351    ///
352    /// * iOS: [nickname](https://developer.apple.com/documentation/uikit/uitextcontenttype).
353    /// * web: ["nickname"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
354    /// * Otherwise, the hint string will be used as-is.
355    pub const NICKNAME: &str = "nickname";
356
357    /// The input field expects a SMS one-time code.
358    ///
359    /// This hint will be translated to the below values on different platforms:
360    ///
361    /// * Android: [AUTOFILL_HINT_SMS_OTP](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_SMS_OTP).
362    /// * iOS: [oneTimeCode](https://developer.apple.com/documentation/uikit/uitextcontenttype).
363    /// * web: ["one-time-code"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
364    /// * Otherwise, the hint string will be used as-is.
365    pub const ONE_TIME_CODE: &str = "oneTimeCode";
366
367    /// The input field expects an email one-time code.
368    ///
369    /// This hint will be translated to the below values on different platforms:
370    ///
371    /// * Android: [AUTOFILL_HINT_EMAIL_OTP](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_EMAIL_OTP).
372    /// * Otherwise, the hint string will be used as-is.
373    pub const EMAIL_OTP_CODE: &str = "emailOTPCode";
374
375    /// The input field expects an organization name corresponding to the person,
376    /// address, or contact information in the other fields associated with this
377    /// field.
378    ///
379    /// This hint will be translated to the below values on different platforms:
380    ///
381    /// * iOS: [organizationName](https://developer.apple.com/documentation/uikit/uitextcontenttype).
382    /// * web: ["organization"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
383    /// * Otherwise, the hint string will be used as-is.
384    pub const ORGANIZATION_NAME: &str = "organizationName";
385
386    /// The input field expects a password.
387    ///
388    /// This hint will be translated to the below values on different platforms:
389    ///
390    /// * Android: [AUTOFILL_HINT_PASSWORD](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PASSWORD).
391    /// * iOS: [password](https://developer.apple.com/documentation/uikit/uitextcontenttype).
392    /// * web: ["current-password"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
393    /// * Otherwise, the hint string will be used as-is.
394    pub const PASSWORD: &str = "password";
395
396    /// The input field expects a photograph, icon, or other image corresponding
397    /// to the company, person, address, or contact information in the other
398    /// fields associated with this field.
399    ///
400    /// This hint will be translated to the below values on different platforms:
401    ///
402    /// * web: ["photo"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
403    /// * Otherwise, the hint string will be used as-is.
404    pub const PHOTO: &str = "photo";
405
406    /// The input field expects a postal address.
407    ///
408    /// This hint will be translated to the below values on different platforms:
409    ///
410    /// * Android: [AUTOFILL_HINT_POSTAL_ADDRESS](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_POSTAL_ADDRESS).
411    /// * Otherwise, the hint string will be used as-is.
412    pub const POSTAL_ADDRESS: &str = "postalAddress";
413
414    /// The input field expects an auxiliary address details.
415    ///
416    /// This hint will be translated to the below values on different platforms:
417    ///
418    /// * Android: [AUTOFILL_HINT_POSTAL_ADDRESS_EXTENDED_ADDRESS](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_POSTAL_ADDRESS_EXTENDED_ADDRESS).
419    /// * Otherwise, the hint string will be used as-is.
420    pub const POSTAL_ADDRESS_EXTENDED: &str = "postalAddressExtended";
421
422    /// The input field expects an extended ZIP/POSTAL code.
423    ///
424    /// This hint will be translated to the below values on different platforms:
425    ///
426    /// * Android: [AUTOFILL_HINT_POSTAL_ADDRESS_EXTENDED_POSTAL_CODE](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_POSTAL_ADDRESS_EXTENDED_POSTAL_CODE).
427    /// * Otherwise, the hint string will be used as-is.
428    pub const POSTAL_ADDRESS_EXTENDED_POSTAL_CODE: &str = "postalAddressExtendedPostalCode";
429
430    /// The input field expects a postal code.
431    ///
432    /// This hint will be translated to the below values on different platforms:
433    ///
434    /// * Android: [AUTOFILL_HINT_POSTAL_CODE](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_POSTAL_CODE).
435    /// * iOS: [postalCode](https://developer.apple.com/documentation/uikit/uitextcontenttype).
436    /// * web: ["postal-code"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
437    /// * Otherwise, the hint string will be used as-is.
438    pub const POSTAL_CODE: &str = "postalCode";
439
440    /// The first administrative level in the address. This is typically the
441    /// province in which the address is located. In the United States, this would
442    /// be the state. In Switzerland, the canton. In the United Kingdom, the post
443    /// town.
444    ///
445    /// This hint will be translated to the below values on different platforms:
446    ///
447    /// * web: ["address-level1"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
448    /// * Otherwise, the hint string will be used as-is.
449    pub const STREET_ADDRESS_LEVEL1: &str = "streetAddressLevel1";
450
451    /// The second administrative level, in addresses with at least two of them.
452    /// In countries with two administrative levels, this would typically be the
453    /// city, town, village, or other locality in which the address is located.
454    ///
455    /// This hint will be translated to the below values on different platforms:
456    ///
457    /// * web: ["address-level2"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
458    /// * Otherwise, the hint string will be used as-is.
459    pub const STREET_ADDRESS_LEVEL2: &str = "streetAddressLevel2";
460
461    /// The third administrative level, in addresses with at least three
462    /// administrative levels.
463    ///
464    /// This hint will be translated to the below values on different platforms:
465    ///
466    /// * web: ["address-level3"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
467    /// * Otherwise, the hint string will be used as-is.
468    pub const STREET_ADDRESS_LEVEL3: &str = "streetAddressLevel3";
469
470    /// The finest-grained administrative level, in addresses which have four
471    /// levels.
472    ///
473    /// This hint will be translated to the below values on different platforms:
474    ///
475    /// * web: ["address-level4"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
476    /// * Otherwise, the hint string will be used as-is.
477    pub const STREET_ADDRESS_LEVEL4: &str = "streetAddressLevel4";
478
479    /// The input field expects the first line of a street address.
480    ///
481    /// This hint will be translated to the below values on different platforms:
482    ///
483    /// * iOS: [streetAddressLine1](https://developer.apple.com/documentation/uikit/uitextcontenttype).
484    /// * web: ["address-line1"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
485    /// * Otherwise, the hint string will be used as-is.
486    pub const STREET_ADDRESS_LINE1: &str = "streetAddressLine1";
487
488    /// The input field expects the second line of a street address.
489    ///
490    /// This hint will be translated to the below values on different platforms:
491    ///
492    /// * iOS: [streetAddressLine2](https://developer.apple.com/documentation/uikit/uitextcontenttype).
493    ///   As of iOS 14.2 this hint does not trigger autofill.
494    /// * web: ["address-line2"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
495    /// * Otherwise, the hint string will be used as-is.
496    pub const STREET_ADDRESS_LINE2: &str = "streetAddressLine2";
497
498    /// The input field expects the third line of a street address.
499    ///
500    /// This hint will be translated to the below values on different platforms:
501    ///
502    /// * web: ["address-line3"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
503    /// * Otherwise, the hint string will be used as-is.
504    pub const STREET_ADDRESS_LINE3: &str = "streetAddressLine3";
505
506    /// The input field expects a sublocality.
507    ///
508    /// This hint will be translated to the below values on different platforms:
509    ///
510    /// * iOS: [sublocality](https://developer.apple.com/documentation/uikit/uitextcontenttype).
511    /// * Otherwise, the hint string will be used as-is.
512    pub const SUBLOCALITY: &str = "sublocality";
513
514    /// The input field expects a telephone number.
515    ///
516    /// This hint will be translated to the below values on different platforms:
517    ///
518    /// * Android: [AUTOFILL_HINT_PHONE_NUMBER](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PHONE_NUMBER).
519    /// * iOS: [telephoneNumber](https://developer.apple.com/documentation/uikit/uitextcontenttype).
520    /// * web: ["tel"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
521    /// * Otherwise, the hint string will be used as-is.
522    pub const TELEPHONE_NUMBER: &str = "telephoneNumber";
523
524    /// The input field expects a phone number's area code, with a country
525    /// -internal prefix applied if applicable.
526    ///
527    /// This hint will be translated to the below values on different platforms:
528    ///
529    /// * web: ["tel-area-code"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
530    /// * Otherwise, the hint string will be used as-is.
531    pub const TELEPHONE_NUMBER_AREA_CODE: &str = "telephoneNumberAreaCode";
532
533    /// The input field expects a phone number's country code.
534    ///
535    /// This hint will be translated to the below values on different platforms:
536    ///
537    /// * Android: [AUTOFILL_HINT_PHONE_COUNTRY_CODE](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PHONE_COUNTRY_CODE).
538    /// * web: ["tel-country-code"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
539    /// * Otherwise, the hint string will be used as-is.
540    pub const TELEPHONE_NUMBER_COUNTRY_CODE: &str = "telephoneNumberCountryCode";
541
542    /// The input field expects the current device's phone number, usually for
543    /// Sign Up / OTP flows.
544    ///
545    /// This hint will be translated to the below values on different platforms:
546    ///
547    /// * Android: [AUTOFILL_HINT_PHONE_NUMBER_DEVICE](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PHONE_NUMBER_DEVICE).
548    /// * Otherwise, the hint string will be used as-is.
549    pub const TELEPHONE_NUMBER_DEVICE: &str = "telephoneNumberDevice";
550
551    /// The input field expects a phone number's internal extension code.
552    ///
553    /// This hint will be translated to the below values on different platforms:
554    ///
555    /// * web: ["tel-extension"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
556    /// * Otherwise, the hint string will be used as-is.
557    pub const TELEPHONE_NUMBER_EXTENSION: &str = "telephoneNumberExtension";
558
559    /// The input field expects a phone number without the country code and area
560    /// code components.
561    ///
562    /// This hint will be translated to the below values on different platforms:
563    ///
564    /// * web: ["tel-local"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
565    /// * Otherwise, the hint string will be used as-is.
566    pub const TELEPHONE_NUMBER_LOCAL: &str = "telephoneNumberLocal";
567
568    /// The input field expects the first part of the component of the telephone
569    /// number that follows the area code, when that component is split into two
570    /// components.
571    ///
572    /// This hint will be translated to the below values on different platforms:
573    ///
574    /// * web: ["tel-local-prefix"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
575    /// * Otherwise, the hint string will be used as-is.
576    pub const TELEPHONE_NUMBER_LOCAL_PREFIX: &str = "telephoneNumberLocalPrefix";
577
578    /// The input field expects the second part of the component of the telephone
579    /// number that follows the area code, when that component is split into two
580    /// components.
581    ///
582    /// This hint will be translated to the below values on different platforms:
583    ///
584    /// * web: ["tel-local-suffix"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
585    /// * Otherwise, the hint string will be used as-is.
586    pub const TELEPHONE_NUMBER_LOCAL_SUFFIX: &str = "telephoneNumberLocalSuffix";
587
588    /// The input field expects a phone number without country code.
589    ///
590    /// This hint will be translated to the below values on different platforms:
591    ///
592    /// * Android: [AUTOFILL_HINT_PHONE_NATIONAL](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_PHONE_NATIONAL).
593    /// * web: ["tel-national"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
594    /// * Otherwise, the hint string will be used as-is.
595    pub const TELEPHONE_NUMBER_NATIONAL: &str = "telephoneNumberNational";
596
597    /// The amount that the user would like for the transaction (e.g. when
598    /// entering a bid or sale price).
599    ///
600    /// This hint will be translated to the below values on different platforms:
601    ///
602    /// * web: ["transaction-amount"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
603    /// * Otherwise, the hint string will be used as-is.
604    pub const TRANSACTION_AMOUNT: &str = "transactionAmount";
605
606    /// The currency that the user would prefer the transaction to use, in [ISO
607    /// 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html).
608    ///
609    /// This hint will be translated to the below values on different platforms:
610    ///
611    /// * web: ["transaction-currency"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
612    /// * Otherwise, the hint string will be used as-is.
613    pub const TRANSACTION_CURRENCY: &str = "transactionCurrency";
614
615    /// The input field expects a URL.
616    ///
617    /// This hint will be translated to the below values on different platforms:
618    ///
619    /// * iOS: [URL](https://developer.apple.com/documentation/uikit/uitextcontenttype).
620    /// * web: ["url"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
621    /// * Otherwise, the hint string will be used as-is.
622    pub const URL: &str = "url";
623
624    /// The input field expects a username or an account name.
625    ///
626    /// This hint will be translated to the below values on different platforms:
627    ///
628    /// * Android: [AUTOFILL_HINT_USERNAME](https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_USERNAME).
629    /// * iOS: [username](https://developer.apple.com/documentation/uikit/uitextcontenttype).
630    /// * web: ["username"](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute).
631    /// * Otherwise, the hint string will be used as-is.
632    pub const USERNAME: &str = "username";
633}
634
635/// An object that represents an autofillable input field in the autofill workflow.
636///
637/// An [`AutofillClient`] provides autofill-related information of the input field
638/// it represents to the platform, and consumes autofill inputs from the platform.
639pub trait AutofillClient: Sized + 'static {
640    /// The unique identifier of this [`AutofillClient`].
641    ///
642    /// The identifier must not be changed.
643    fn autofill_id(self: Handle<Self>, app: &App) -> String;
644
645    /// The [`TextInputConfiguration`] that describes this [`AutofillClient`].
646    ///
647    /// In order to participate in autofill, its
648    /// [`TextInputConfiguration::autofill_configuration`] must not be
649    /// [`AutofillConfiguration::DISABLED`](crate::AutofillConfiguration::DISABLED).
650    fn text_input_configuration(self: Handle<Self>, app: &App) -> TextInputConfiguration;
651
652    /// Requests this [`AutofillClient`] update its [`TextEditingValue`] to the given
653    /// value.
654    fn autofill(self: Handle<Self>, app: &mut App, new_editing_value: TextEditingValue);
655
656    /// This client as the erased [`AnyAutofillClient`].
657    fn as_autofill_client(self: Handle<Self>) -> AnyAutofillClient {
658        AnyAutofillClient {
659            id: self.id(),
660            vtable: const { &AutofillClientVTable::of::<Self>() },
661        }
662    }
663}
664
665struct AutofillClientVTable {
666    autofill_id: fn(&App, HandleId) -> String,
667    text_input_configuration: fn(&App, HandleId) -> TextInputConfiguration,
668    autofill: fn(&mut App, HandleId, TextEditingValue),
669}
670
671fn resolve<T: 'static>(id: HandleId) -> Handle<T> {
672    Handle::from_id(id)
673}
674
675impl AutofillClientVTable {
676    const fn of<C: AutofillClient>() -> AutofillClientVTable {
677        AutofillClientVTable {
678            autofill_id: |app, id| C::autofill_id(resolve(id), app),
679            text_input_configuration: |app, id| C::text_input_configuration(resolve(id), app),
680            autofill: |app, id, value| C::autofill(resolve(id), app, value),
681        }
682    }
683}
684
685/// Erased [`AutofillClient`]: one identity and a static vtable.
686#[derive(Clone, Copy)]
687pub struct AnyAutofillClient {
688    id: HandleId,
689    vtable: &'static AutofillClientVTable,
690}
691
692impl AnyAutofillClient {
693    pub fn autofill_id(self, app: &App) -> String {
694        (self.vtable.autofill_id)(app, self.id)
695    }
696
697    pub fn text_input_configuration(self, app: &App) -> TextInputConfiguration {
698        (self.vtable.text_input_configuration)(app, self.id)
699    }
700
701    pub fn autofill(self, app: &mut App, new_editing_value: TextEditingValue) {
702        (self.vtable.autofill)(app, self.id, new_editing_value);
703    }
704}
705
706impl PartialEq for AnyAutofillClient {
707    fn eq(&self, other: &AnyAutofillClient) -> bool {
708        self.id == other.id
709    }
710}
711
712impl Eq for AnyAutofillClient {}
713
714/// An ordered group within which [`AutofillClient`]s are logically connected.
715///
716/// [`AutofillClient`]s within the same [`AutofillScope`] are isolated from other
717/// input fields during autofill. That is, when an autofillable `TextInputClient`
718/// gains focus, only the [`AutofillClient`]s within the same [`AutofillScope`] will
719/// be visible to the autofill service, in the same order as they appear in
720/// [`AutofillScope::autofill_clients`].
721///
722/// [`AutofillScope`] also allows `TextInput` to redirect autofill values from the
723/// platform to the [`AutofillClient`] with the given identifier, by calling
724/// [`AutofillScope::get_autofill_client`].
725///
726/// An [`AutofillClient`] that's not tied to any [`AutofillScope`] will only
727/// participate in autofill if the autofill is directly triggered by its own
728/// `TextInputClient`.
729pub trait AutofillScope: Sized + 'static {
730    /// Gets the [`AutofillClient`] associated with the given `autofill_id`, in
731    /// this [`AutofillScope`].
732    ///
733    /// Returns [`None`] if there's no matching [`AutofillClient`].
734    fn get_autofill_client(
735        self: Handle<Self>,
736        app: &App,
737        autofill_id: &str,
738    ) -> Option<AnyAutofillClient>;
739
740    /// The collection of [`AutofillClient`]s currently tied to this [`AutofillScope`].
741    ///
742    /// Every [`AutofillClient`] in this list must have autofill enabled (i.e. its
743    /// [`AutofillClient::text_input_configuration`] must have a non-disabled
744    /// [`crate::AutofillConfiguration`].)
745    fn autofill_clients(self: Handle<Self>, app: &App) -> Vec<AnyAutofillClient>;
746
747    /// Allows a `TextInputClient` to attach to this scope. This method should be
748    /// called in lieu of [`TextInput::attach`], when the `TextInputClient` wishes to
749    /// participate in autofill.
750    ///
751    /// Flutter `AutofillScopeMixin.attach`.
752    fn attach(
753        self: Handle<Self>,
754        app: &mut App,
755        trigger: AnyTextInputClient,
756        configuration: TextInputConfiguration,
757    ) -> Handle<TextInputConnection> {
758        debug_assert!(
759            !self.autofill_clients(app).iter().any(|client| {
760                !client
761                    .text_input_configuration(app)
762                    .autofill_configuration
763                    .enabled
764            }),
765            "Every client in AutofillScope.autofillClients must enable autofill"
766        );
767        TextInput::attach(app, trigger, configuration)
768    }
769}
770
771/// A partial implementation of [`AutofillScope`].
772///
773/// The mixin provides a default implementation for [`AutofillScope::attach`].
774pub trait AutofillScopeMixin: AutofillScope {}
775
776impl<T: AutofillScope> AutofillScopeMixin for T {}
777
778#[cfg(test)]
779mod tests {
780    use inset_foundation::AppCell;
781
782    use super::*;
783    use crate::text_input::TextInputClient;
784
785    #[test]
786    fn hint_strings_match_dart() {
787        assert_eq!(AutofillHints::EMAIL, "email");
788        assert_eq!(AutofillHints::ONE_TIME_CODE, "oneTimeCode");
789        assert_eq!(AutofillHints::EMAIL_OTP_CODE, "emailOTPCode");
790    }
791
792    #[derive(Default)]
793    struct RecordingField {
794        autofill_id: String,
795        value: TextEditingValue,
796        filled: Option<TextEditingValue>,
797    }
798
799    impl AutofillClient for RecordingField {
800        fn autofill_id(self: Handle<Self>, app: &App) -> String {
801            app.get(self).autofill_id.clone()
802        }
803
804        fn text_input_configuration(self: Handle<Self>, app: &App) -> TextInputConfiguration {
805            TextInputConfiguration::builder()
806                .autofill_configuration(crate::AutofillConfiguration::new(
807                    app.get(self).autofill_id.clone(),
808                    vec![AutofillHints::EMAIL.to_owned()],
809                    app.get(self).value.clone(),
810                ))
811                .build()
812        }
813
814        fn autofill(self: Handle<Self>, app: &mut App, new_editing_value: TextEditingValue) {
815            app.get_mut(self).filled = Some(new_editing_value);
816        }
817    }
818
819    impl TextInputClient for RecordingField {
820        fn current_text_editing_value(self: Handle<Self>, app: &App) -> Option<TextEditingValue> {
821            Some(app.get(self).value.clone())
822        }
823
824        fn update_editing_value(self: Handle<Self>, app: &mut App, value: TextEditingValue) {
825            app.get_mut(self).value = value;
826        }
827
828        fn perform_action(self: Handle<Self>, _app: &mut App, _action: crate::TextInputAction) {}
829
830        fn connection_closed(self: Handle<Self>, _app: &mut App) {}
831    }
832
833    struct RecordingScope {
834        clients: Vec<AnyAutofillClient>,
835    }
836
837    impl AutofillScope for RecordingScope {
838        fn get_autofill_client(
839            self: Handle<Self>,
840            app: &App,
841            autofill_id: &str,
842        ) -> Option<AnyAutofillClient> {
843            self.autofill_clients(app)
844                .into_iter()
845                .find(|client| client.autofill_id(app) == autofill_id)
846        }
847
848        fn autofill_clients(self: Handle<Self>, app: &App) -> Vec<AnyAutofillClient> {
849            app.get(self).clients.clone()
850        }
851    }
852
853    #[test]
854    fn scope_attach_uses_text_input_attach() {
855        let cell = AppCell::new();
856        let mut app = cell.borrow_mut();
857        let field = app.create(RecordingField {
858            autofill_id: "email".into(),
859            ..RecordingField::default()
860        });
861        let scope = app.create(RecordingScope {
862            clients: vec![field.as_autofill_client()],
863        });
864        let configuration = field.text_input_configuration(&app);
865        let connection = scope.attach(&mut app, field.as_text_input_client(), configuration);
866        assert!(connection.attached(&mut app));
867        assert_eq!(
868            scope
869                .get_autofill_client(&app, "email")
870                .map(|c| c.autofill_id(&app)),
871            Some("email".into())
872        );
873        field
874            .as_autofill_client()
875            .autofill(&mut app, TextEditingValue::new().text("user@example.com"));
876        assert_eq!(
877            app.get(field).filled.as_ref().map(|v| v.text.as_str()),
878            Some("user@example.com")
879        );
880    }
881}