@@ -133,177 +133,180 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
133133 @override
134134 Widget build (BuildContext context) {
135135 final localization = widget.localization;
136- return Form (
137- key: _formKey,
138- child: Column (
139- crossAxisAlignment: CrossAxisAlignment .stretch,
140- children: [
141- TextFormField (
142- keyboardType: TextInputType .emailAddress,
143- autofillHints: const [AutofillHints .email],
144- validator: (value) {
145- if (value == null ||
146- value.isEmpty ||
147- ! EmailValidator .validate (_emailController.text)) {
148- return localization.validEmailError;
149- }
150- return null ;
151- },
152- decoration: InputDecoration (
153- prefixIcon: const Icon (Icons .email),
154- label: Text (localization.enterEmail),
155- ),
156- controller: _emailController,
157- ),
158- if (! _forgotPassword) ...[
159- spacer (16 ),
136+ return AutofillGroup (
137+ child: Form (
138+ key: _formKey,
139+ child: Column (
140+ crossAxisAlignment: CrossAxisAlignment .stretch,
141+ children: [
160142 TextFormField (
161- autofillHints: _isSigningIn
162- ? [AutofillHints .password]
163- : [AutofillHints .newPassword],
143+ keyboardType: TextInputType .emailAddress,
144+ autofillHints: const [AutofillHints .email],
164145 validator: (value) {
165- if (value == null || value.isEmpty || value.length < 6 ) {
166- return localization.passwordLengthError;
146+ if (value == null ||
147+ value.isEmpty ||
148+ ! EmailValidator .validate (_emailController.text)) {
149+ return localization.validEmailError;
167150 }
168151 return null ;
169152 },
170153 decoration: InputDecoration (
171- prefixIcon: const Icon (Icons .lock ),
172- label: Text (localization.enterPassword ),
154+ prefixIcon: const Icon (Icons .email ),
155+ label: Text (localization.enterEmail ),
173156 ),
174- obscureText: true ,
175- controller: _passwordController,
157+ controller: _emailController,
176158 ),
177- spacer (16 ),
178- if (widget.metadataFields != null && ! _isSigningIn)
179- ...widget.metadataFields!
180- .map ((metadataField) => [
181- TextFormField (
182- controller: _metadataControllers[metadataField],
183- decoration: InputDecoration (
184- label: Text (metadataField.label),
185- prefixIcon: metadataField.prefixIcon,
159+ if (! _forgotPassword) ...[
160+ spacer (16 ),
161+ TextFormField (
162+ autofillHints: _isSigningIn
163+ ? [AutofillHints .password]
164+ : [AutofillHints .newPassword],
165+ validator: (value) {
166+ if (value == null || value.isEmpty || value.length < 6 ) {
167+ return localization.passwordLengthError;
168+ }
169+ return null ;
170+ },
171+ decoration: InputDecoration (
172+ prefixIcon: const Icon (Icons .lock),
173+ label: Text (localization.enterPassword),
174+ ),
175+ obscureText: true ,
176+ controller: _passwordController,
177+ ),
178+ spacer (16 ),
179+ if (widget.metadataFields != null && ! _isSigningIn)
180+ ...widget.metadataFields!
181+ .map ((metadataField) => [
182+ TextFormField (
183+ controller: _metadataControllers[metadataField],
184+ decoration: InputDecoration (
185+ label: Text (metadataField.label),
186+ prefixIcon: metadataField.prefixIcon,
187+ ),
188+ validator: metadataField.validator,
186189 ),
187- validator: metadataField.validator,
190+ spacer (16 ),
191+ ])
192+ .expand ((element) => element),
193+ ElevatedButton (
194+ child: (_isLoading)
195+ ? SizedBox (
196+ height: 16 ,
197+ width: 16 ,
198+ child: CircularProgressIndicator (
199+ color: Theme .of (context).colorScheme.onPrimary,
200+ strokeWidth: 1.5 ,
188201 ),
189- spacer (16 ),
190- ])
191- .expand ((element) => element),
192- ElevatedButton (
193- child: (_isLoading)
194- ? SizedBox (
195- height: 16 ,
196- width: 16 ,
197- child: CircularProgressIndicator (
198- color: Theme .of (context).colorScheme.onPrimary,
199- strokeWidth: 1.5 ,
200- ),
201- )
202- : Text (
203- _isSigningIn ? localization.signIn : localization.signUp),
204- onPressed: () async {
205- if (! _formKey.currentState! .validate ()) {
206- return ;
207- }
208- setState (() {
209- _isLoading = true ;
210- });
211- try {
212- if (_isSigningIn) {
213- final response = await supabase.auth.signInWithPassword (
214- email: _emailController.text.trim (),
215- password: _passwordController.text.trim (),
216- );
217- widget.onSignInComplete.call (response);
218- } else {
219- final response = await supabase.auth.signUp (
220- email: _emailController.text.trim (),
221- password: _passwordController.text.trim (),
222- emailRedirectTo: widget.redirectTo,
223- data: _resolveData (),
224- );
225- widget.onSignUpComplete.call (response);
226- }
227- } on AuthException catch (error) {
228- if (widget.onError == null && context.mounted) {
229- context.showErrorSnackBar (error.message);
230- } else {
231- widget.onError? .call (error);
232- }
233- } catch (error) {
234- if (widget.onError == null && context.mounted) {
235- context.showErrorSnackBar (
236- '${localization .unexpectedError }: $error ' );
237- } else {
238- widget.onError? .call (error);
202+ )
203+ : Text (_isSigningIn
204+ ? localization.signIn
205+ : localization.signUp),
206+ onPressed: () async {
207+ if (! _formKey.currentState! .validate ()) {
208+ return ;
239209 }
240- }
241- if (mounted) {
242210 setState (() {
243- _isLoading = false ;
211+ _isLoading = true ;
244212 });
245- }
246- },
247- ),
248- spacer (16 ),
249- if (_isSigningIn) ...[
213+ try {
214+ if (_isSigningIn) {
215+ final response = await supabase.auth.signInWithPassword (
216+ email: _emailController.text.trim (),
217+ password: _passwordController.text.trim (),
218+ );
219+ widget.onSignInComplete.call (response);
220+ } else {
221+ final response = await supabase.auth.signUp (
222+ email: _emailController.text.trim (),
223+ password: _passwordController.text.trim (),
224+ emailRedirectTo: widget.redirectTo,
225+ data: _resolveData (),
226+ );
227+ widget.onSignUpComplete.call (response);
228+ }
229+ } on AuthException catch (error) {
230+ if (widget.onError == null && context.mounted) {
231+ context.showErrorSnackBar (error.message);
232+ } else {
233+ widget.onError? .call (error);
234+ }
235+ } catch (error) {
236+ if (widget.onError == null && context.mounted) {
237+ context.showErrorSnackBar (
238+ '${localization .unexpectedError }: $error ' );
239+ } else {
240+ widget.onError? .call (error);
241+ }
242+ }
243+ if (mounted) {
244+ setState (() {
245+ _isLoading = false ;
246+ });
247+ }
248+ },
249+ ),
250+ spacer (16 ),
251+ if (_isSigningIn) ...[
252+ TextButton (
253+ onPressed: () {
254+ setState (() {
255+ _forgotPassword = true ;
256+ });
257+ },
258+ child: Text (localization.forgotPassword),
259+ ),
260+ ],
250261 TextButton (
262+ key: const ValueKey ('toggleSignInButton' ),
251263 onPressed: () {
252264 setState (() {
253- _forgotPassword = true ;
265+ _forgotPassword = false ;
266+ _isSigningIn = ! _isSigningIn;
254267 });
255268 },
256- child: Text (localization.forgotPassword),
269+ child: Text (_isSigningIn
270+ ? localization.dontHaveAccount
271+ : localization.haveAccount),
257272 ),
258273 ],
259- TextButton (
260- key: const ValueKey ('toggleSignInButton' ),
261- onPressed: () {
262- setState (() {
263- _forgotPassword = false ;
264- _isSigningIn = ! _isSigningIn;
265- });
266- },
267- child: Text (_isSigningIn
268- ? localization.dontHaveAccount
269- : localization.haveAccount),
270- ),
271- ],
272- if (_isSigningIn && _forgotPassword) ...[
273- spacer (16 ),
274- ElevatedButton (
275- onPressed: () async {
276- try {
277- if (! _formKey.currentState! .validate ()) {
278- return ;
274+ if (_isSigningIn && _forgotPassword) ...[
275+ spacer (16 ),
276+ ElevatedButton (
277+ onPressed: () async {
278+ try {
279+ if (! _formKey.currentState! .validate ()) {
280+ return ;
281+ }
282+ setState (() {
283+ _isLoading = true ;
284+ });
285+
286+ final email = _emailController.text.trim ();
287+ await supabase.auth.resetPasswordForEmail (email);
288+ widget.onPasswordResetEmailSent? .call ();
289+ } on AuthException catch (error) {
290+ widget.onError? .call (error);
291+ } catch (error) {
292+ widget.onError? .call (error);
279293 }
294+ },
295+ child: Text (localization.sendPasswordReset),
296+ ),
297+ spacer (16 ),
298+ TextButton (
299+ onPressed: () {
280300 setState (() {
281- _isLoading = true ;
301+ _forgotPassword = false ;
282302 });
283-
284- final email = _emailController.text.trim ();
285- await supabase.auth.resetPasswordForEmail (email);
286- widget.onPasswordResetEmailSent? .call ();
287- } on AuthException catch (error) {
288- widget.onError? .call (error);
289- } catch (error) {
290- widget.onError? .call (error);
291- }
292- },
293- child: Text (localization.sendPasswordReset),
294- ),
303+ },
304+ child: Text (localization.backToSignIn),
305+ ),
306+ ],
295307 spacer (16 ),
296- TextButton (
297- onPressed: () {
298- setState (() {
299- _forgotPassword = false ;
300- });
301- },
302- child: Text (localization.backToSignIn),
303- ),
304308 ],
305- spacer (16 ),
306- ],
309+ ),
307310 ),
308311 );
309312 }
0 commit comments