-
Notifications
You must be signed in to change notification settings - Fork 1
/
input_password.dart
125 lines (104 loc) · 3.49 KB
/
input_password.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import "dart:async";
import "package:flutter/material.dart";
import "package:flutter_gen/gen_l10n/app_localizations.dart";
class InputPassword extends StatefulWidget {
/// Controller of the input password
final TextEditingController controller;
final VoidCallback? onChange;
final VoidCallback? onEditingComplete;
final bool isRequired;
final bool autoFocus;
final bool enabled;
final TextInputAction textInputAction;
/// Controller of the main password input,
/// meaning that this input is used to confirm the first one.
final TextEditingController? passwordToConfirmController;
const InputPassword({
required this.controller,
this.isRequired = true,
this.autoFocus = false,
this.enabled = true,
this.onChange,
this.onEditingComplete,
this.textInputAction = TextInputAction.done,
this.passwordToConfirmController,
super.key,
});
@override
State<InputPassword> createState() => _InputPasswordState();
}
class _InputPasswordState extends State<InputPassword> {
final GlobalKey<FormFieldState> _formFieldKey =
GlobalKey<FormFieldState>(debugLabel: "password_input_widget");
// Timer applied before the validation is triggered
Timer? timer;
// Indicate if the password is hidden or not.
bool isPasswordObscured = true;
@override
void initState() {
super.initState();
isPasswordObscured = true;
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
void _onChange(String? _) {
timer?.cancel();
// Trigger a new timer that will validate on inactivity
timer = Timer(const Duration(milliseconds: 300), () {
_formFieldKey.currentState!.validate();
widget.onChange?.call();
});
}
String? _validate(String? value, AppLocalizations l10n) {
if (widget.isRequired) {
if (value == null || value.isEmpty) {
return widget.passwordToConfirmController == null
? l10n.input_password_msg_missing_password
: l10n.input_password_msg_missing_password_confirmation;
} else if (widget.passwordToConfirmController != null &&
widget.passwordToConfirmController?.text != widget.controller.text) {
return l10n.input_password_configuration_mismatch;
}
}
return null;
}
void _toggleVisibility() {
setState(() {
isPasswordObscured = !isPasswordObscured;
});
}
@override
Widget build(BuildContext context) {
final AppLocalizations l10n = AppLocalizations.of(context);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 7),
child: TextFormField(
key: _formFieldKey,
controller: widget.controller,
autofocus: widget.autoFocus,
enabled: widget.enabled,
autofillHints: const [AutofillHints.password],
textInputAction: widget.textInputAction,
onChanged: _onChange,
onEditingComplete: widget.onEditingComplete,
validator: (String? value) => _validate(value, l10n),
obscureText: isPasswordObscured,
decoration: InputDecoration(
hintText: widget.passwordToConfirmController != null
? l10n.input_password_confirmation_placeholder
: l10n.input_password_placeholder,
suffixIcon: IconButton(
icon: Icon(isPasswordObscured
? Icons.visibility_rounded
: Icons.visibility_off_rounded),
onPressed: _toggleVisibility,
),
alignLabelWithHint: false,
),
),
);
}
}