Skip to content

Commit 234b34f

Browse files
LorenzohidalgoJordan-Nelson
authored andcommitted
feat(authenticator): Add AutoFill Capabilities (#2306)
* added autofillHints for AuthenticatorUsernameField * added autofillhints + autofillgroup + finishAutofillContext * added access to autofillHints from textfield * added missing AutofillGroup * updated README * removed redundant override for `birthday` AutoFill * autofillHints override for ConfirmSignInFormField * autofillHints override for VerifyUserTextField * AutoFillHints Platform Support * table order fix * added autofillHints Override for SignupFormField * added autofillHint Override ConfirmSignInFormField * autofillHints Override for ConfirmSignUpFormField * autofillHints Override for VerifyUserFormField * autofillHints Override for SignInFormField * autofillHints Override for ResetPasswordFormField * overrideAutofillHints to autofillHints change * readme typo + missing PhoneField autofillHints * removed AutofillGroup * chore: update phone number username hints * chore: remove superflous comments --------- Co-authored-by: Jordan Nelson <[email protected]>
1 parent c149fbe commit 234b34f

14 files changed

+386
-0
lines changed

packages/amplify_authenticator/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,34 @@ class LoggedInScreen extends StatelessWidget {
8787
}
8888
}
8989
```
90+
91+
## Setting up & Troubleshooting AutoFill
92+
93+
`Authenticator` provides built-in `AutoFill` features for the generated `Forms`. Some additional configurations could be necessary to provide the best user experience and ensure your app fully supports password autofill.
94+
95+
Please refer to the [official documentation](https://api.flutter.dev/flutter/material/TextField/autofillHints.html) for the configuration steps and how to troubleshoot this feature.
96+
97+
### AutoFillHints Platform Support
98+
99+
The following `AutoFillHints` have been implemented for the `Authenticator` package.
100+
101+
| AutoFillHint | iOS | Android | Web |
102+
| ------------ | :-: | :-----: | :-: |
103+
| birthday | ❌ | ✅ | ✅ |
104+
| countryName | ✅ | ✅ | ✅ |
105+
| email | ✅ | ✅ | ✅ |
106+
| familyName | ✅ | ✅ | ✅ |
107+
| fullStreetAddress | ✅ | ✅ | ✅ |
108+
| gender | ❌ | ✅ | ✅ |
109+
| givenName | ✅ | ✅ | ✅ |
110+
| middleName | ✅ | ✅ | ✅ |
111+
| name | ✅ | ✅ | ✅ |
112+
| newPassword | ✅ | ✅ | ✅ |
113+
| newUsername | ❌ | ✅ | ❌ |
114+
| nickname | ✅ | ❌ | ✅ |
115+
| oneTimeCode | ✅ | ✅ | ✅ |
116+
| password | ✅ | ✅ | ✅ |
117+
| telephoneNumber | ✅ | ✅ | ✅ |
118+
| username | ✅ | ✅ | ✅ |
119+
120+
Supported Hints are automatically translated to their platform-specific equivalent. Otherwise, the hint string will be used as-is.

packages/amplify_authenticator/lib/src/mixins/authenticator_date_field.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ mixin AuthenticatorDateField<FieldType,
8484
),
8585
keyboardType: TextInputType.datetime,
8686
controller: _controller,
87+
autofillHints: autofillHints,
8788
);
8889
}
8990
}

packages/amplify_authenticator/lib/src/mixins/authenticator_phone_field.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ mixin AuthenticatorPhoneFieldMixin<FieldType,
129129
_searchVal = searchVal;
130130
});
131131
},
132+
autofillHints: const [
133+
AutofillHints.countryName,
134+
],
132135
),
133136
),
134137
const SizedBox(height: 10),

packages/amplify_authenticator/lib/src/mixins/authenticator_text_field.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ mixin AuthenticatorTextField<FieldType,
5757
keyboardType: keyboardType,
5858
obscureText: obscureText,
5959
textAlignVertical: TextAlignVertical.center,
60+
autofillHints: autofillHints,
6061
);
6162
},
6263
);

packages/amplify_authenticator/lib/src/mixins/authenticator_username_field.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ mixin AuthenticatorUsernameField<FieldType,
236236
enabled: enabled,
237237
errorMaxLines: errorMaxLines,
238238
initialValue: state.username,
239+
autofillHints: autofillHints,
239240
);
240241
}
241242
return TextFormField(
@@ -258,6 +259,7 @@ mixin AuthenticatorUsernameField<FieldType,
258259
),
259260
keyboardType: keyboardType,
260261
obscureText: false,
262+
autofillHints: autofillHints,
261263
);
262264
}
263265
}

packages/amplify_authenticator/lib/src/state/authenticator_state.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import 'package:amplify_authenticator/src/models/username_input.dart';
2121
import 'package:amplify_authenticator/src/state/auth_state.dart';
2222
import 'package:amplify_authenticator/src/utils/country_code.dart';
2323
import 'package:flutter/material.dart';
24+
import 'package:flutter/services.dart';
2425

2526
@visibleForTesting
2627
typedef BlocEventPredicate = bool Function(AuthState state);
@@ -305,7 +306,11 @@ class AuthenticatorState extends ChangeNotifier {
305306
if (!_formKey.currentState!.validate()) {
306307
return;
307308
}
309+
308310
_setIsBusy(true);
311+
312+
TextInput.finishAutofillContext(shouldSave: true);
313+
309314
var confirm = AuthConfirmSignInData(
310315
confirmationValue: _confirmationCode.trim(),
311316
attributes: authAttributes,
@@ -322,7 +327,11 @@ class AuthenticatorState extends ChangeNotifier {
322327
if (!_formKey.currentState!.validate()) {
323328
return;
324329
}
330+
325331
_setIsBusy(true);
332+
333+
TextInput.finishAutofillContext(shouldSave: true);
334+
326335
var confirm = AuthConfirmSignInData(
327336
confirmationValue: _confirmationCode.trim(),
328337
attributes: authAttributes,
@@ -338,7 +347,11 @@ class AuthenticatorState extends ChangeNotifier {
338347
if (!_formKey.currentState!.validate()) {
339348
return;
340349
}
350+
341351
_setIsBusy(true);
352+
353+
TextInput.finishAutofillContext(shouldSave: true);
354+
342355
var confirm = AuthConfirmSignInData(
343356
confirmationValue: _newPassword.trim(),
344357
attributes: authAttributes,
@@ -354,7 +367,11 @@ class AuthenticatorState extends ChangeNotifier {
354367
if (!_formKey.currentState!.validate()) {
355368
return;
356369
}
370+
357371
_setIsBusy(true);
372+
373+
TextInput.finishAutofillContext(shouldSave: true);
374+
358375
final confirmation = AuthConfirmSignUpData(
359376
code: _confirmationCode.trim(),
360377
username: _username.trim(),
@@ -371,7 +388,11 @@ class AuthenticatorState extends ChangeNotifier {
371388
if (!_formKey.currentState!.validate()) {
372389
return;
373390
}
391+
374392
_setIsBusy(true);
393+
394+
TextInput.finishAutofillContext(shouldSave: true);
395+
375396
AuthSignInData signIn = AuthUsernamePasswordSignInData(
376397
username: _username.trim(),
377398
password: _password.trim(),
@@ -403,7 +424,11 @@ class AuthenticatorState extends ChangeNotifier {
403424
if (!_formKey.currentState!.validate()) {
404425
return;
405426
}
427+
406428
_setIsBusy(true);
429+
430+
TextInput.finishAutofillContext(shouldSave: true);
431+
407432
final resetPasswordData = AuthResetPasswordData(username: _username.trim());
408433
_authBloc.add(AuthResetPassword(resetPasswordData));
409434
await nextBlocEvent(
@@ -418,7 +443,11 @@ class AuthenticatorState extends ChangeNotifier {
418443
if (!_formKey.currentState!.validate()) {
419444
return;
420445
}
446+
421447
_setIsBusy(true);
448+
449+
TextInput.finishAutofillContext(shouldSave: true);
450+
422451
AuthConfirmResetPasswordData confirmResetPasswordData =
423452
AuthConfirmResetPasswordData(
424453
username: _username.trim(),
@@ -439,6 +468,8 @@ class AuthenticatorState extends ChangeNotifier {
439468
}
440469
_setIsBusy(true);
441470

471+
TextInput.finishAutofillContext(shouldSave: true);
472+
442473
final signUp = AuthSignUpData(
443474
username: _username.trim(),
444475
password: _password.trim(),
@@ -462,6 +493,9 @@ class AuthenticatorState extends ChangeNotifier {
462493
return;
463494
}
464495
_setIsBusy(true);
496+
497+
TextInput.finishAutofillContext(shouldSave: true);
498+
465499
AuthConfirmVerifyUserData authConfirmVerifyUserData =
466500
AuthConfirmVerifyUserData(
467501
userAttributeKey: userAttributeKey,
@@ -479,7 +513,11 @@ class AuthenticatorState extends ChangeNotifier {
479513
if (!_formKey.currentState!.validate()) {
480514
return;
481515
}
516+
482517
_setIsBusy(true);
518+
519+
TextInput.finishAutofillContext(shouldSave: true);
520+
483521
AuthVerifyUserData authVerifyUserData = AuthVerifyUserData(
484522
userAttributeKey: attributeKeyToVerify,
485523
);

packages/amplify_authenticator/lib/src/widgets/form_field.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ abstract class AuthenticatorFormField<FieldType, FieldValue,
6868
this.hintText,
6969
FormFieldValidator<FieldValue>? validator,
7070
this.requiredOverride,
71+
this.autofillHints,
7172
}) : validatorOverride = validator,
7273
super(key: key);
7374

@@ -96,6 +97,9 @@ abstract class AuthenticatorFormField<FieldType, FieldValue,
9697
/// User override of default [required] value.
9798
final bool? requiredOverride;
9899

100+
/// Autocomplete hints to override the default value
101+
final Iterable<String>? autofillHints;
102+
99103
/// Whether the field is required in the form.
100104
///
101105
/// Defaults to `false`.
@@ -121,6 +125,7 @@ abstract class AuthenticatorFormField<FieldType, FieldValue,
121125
properties
122126
.add(DiagnosticsProperty<bool?>('requiredOverride', requiredOverride));
123127
properties.add(EnumProperty<UsernameType?>('usernameType', usernameType));
128+
properties.add(IterableProperty<String>('autofillHints', autofillHints));
124129
}
125130
}
126131

@@ -211,6 +216,9 @@ abstract class AuthenticatorFormFieldState<FieldType, FieldValue,
211216
/// Widget to show above the label.
212217
Widget? get surlabel => null;
213218

219+
// Autocomplete hints
220+
Iterable<String>? get autofillHints => widget.autofillHints;
221+
214222
@nonVirtual
215223
@override
216224
Widget build(BuildContext context) {
@@ -255,5 +263,6 @@ abstract class AuthenticatorFormFieldState<FieldType, FieldValue,
255263
properties.add(StringProperty('labelText', labelText));
256264
properties.add(DiagnosticsProperty<double?>('marginBottom', marginBottom));
257265
properties.add(DoubleProperty('labelGap', labelGap));
266+
properties.add(IterableProperty<String>('autofillHints', autofillHints));
258267
}
259268
}

0 commit comments

Comments
 (0)