1
1
import 'package:flutter/material.dart' ;
2
- import 'package:flutter/services.dart' ;
3
2
import 'package:flutter_bloc/flutter_bloc.dart' ;
4
3
import 'package:flutter_news_app_mobile_client_full_source_code/app/bloc/app_bloc.dart' ;
5
4
import 'package:flutter_news_app_mobile_client_full_source_code/app/config/config.dart' ;
6
5
import 'package:flutter_news_app_mobile_client_full_source_code/authentication/bloc/authentication_bloc.dart' ;
7
6
import 'package:flutter_news_app_mobile_client_full_source_code/l10n/l10n.dart' ;
7
+ import 'package:pinput/pinput.dart' ;
8
8
import 'package:ui_kit/ui_kit.dart' ;
9
9
10
10
/// {@template email_code_verification_page}
@@ -130,10 +130,12 @@ class _EmailCodeVerificationFormState
130
130
extends State <_EmailCodeVerificationForm > {
131
131
final _formKey = GlobalKey <FormState >();
132
132
final _codeController = TextEditingController ();
133
+ final _focusNode = FocusNode ();
133
134
134
135
@override
135
136
void dispose () {
136
137
_codeController.dispose ();
138
+ _focusNode.dispose ();
137
139
super .dispose ();
138
140
}
139
141
@@ -152,39 +154,48 @@ class _EmailCodeVerificationFormState
152
154
Widget build (BuildContext context) {
153
155
final l10n = AppLocalizationsX (context).l10n;
154
156
final textTheme = Theme .of (context).textTheme;
157
+ final colorScheme = Theme .of (context).colorScheme;
158
+
159
+ final defaultPinTheme = PinTheme (
160
+ width: 56 ,
161
+ height: 60 ,
162
+ textStyle: textTheme.headlineSmall,
163
+ decoration: BoxDecoration (
164
+ color: colorScheme.surface,
165
+ borderRadius: BorderRadius .circular (8 ),
166
+ border: Border .all (color: colorScheme.onSurface.withOpacity (0.12 )),
167
+ ),
168
+ );
155
169
156
170
return Form (
157
171
key: _formKey,
158
172
child: Column (
159
173
mainAxisSize: MainAxisSize .min,
160
174
children: [
161
- Padding (
162
- // No horizontal padding needed if column is stretched
163
- // padding: const EdgeInsets.symmetric(horizontal: AppSpacing.md),
164
- padding: EdgeInsets .zero,
165
- child: TextFormField (
166
- controller: _codeController,
167
- decoration: InputDecoration (
168
- labelText: l10n.emailCodeVerificationHint,
169
- // border: const OutlineInputBorder(),
170
- counterText: '' ,
175
+ Pinput (
176
+ length: 6 ,
177
+ controller: _codeController,
178
+ focusNode: _focusNode,
179
+ defaultPinTheme: defaultPinTheme,
180
+ onCompleted: (pin) => _submitForm (),
181
+ validator: (value) {
182
+ if (value == null || value.isEmpty) {
183
+ return l10n.emailCodeValidationEmptyError;
184
+ }
185
+ if (value.length != 6 ) {
186
+ return l10n.emailCodeValidationLengthError;
187
+ }
188
+ return null ;
189
+ },
190
+ focusedPinTheme: defaultPinTheme.copyWith (
191
+ decoration: defaultPinTheme.decoration! .copyWith (
192
+ border: Border .all (color: colorScheme.primary),
193
+ ),
194
+ ),
195
+ errorPinTheme: defaultPinTheme.copyWith (
196
+ decoration: defaultPinTheme.decoration! .copyWith (
197
+ border: Border .all (color: colorScheme.error),
171
198
),
172
- keyboardType: TextInputType .number,
173
- inputFormatters: [FilteringTextInputFormatter .digitsOnly],
174
- maxLength: 6 ,
175
- textAlign: TextAlign .center,
176
- style: textTheme.headlineSmall,
177
- enabled: ! widget.isLoading,
178
- validator: (value) {
179
- if (value == null || value.isEmpty) {
180
- return l10n.emailCodeValidationEmptyError;
181
- }
182
- if (value.length != 6 ) {
183
- return l10n.emailCodeValidationLengthError;
184
- }
185
- return null ;
186
- },
187
- onFieldSubmitted: widget.isLoading ? null : (_) => _submitForm (),
188
199
),
189
200
),
190
201
const SizedBox (height: AppSpacing .xxl),
0 commit comments