@@ -17,98 +17,156 @@ class AuthenticationPage extends StatelessWidget {
17
17
}
18
18
}
19
19
20
- class _AuthenticationView extends StatelessWidget {
21
- _AuthenticationView ();
20
+ class _AuthenticationView extends StatefulWidget {
21
+ @override
22
+ __AuthenticationViewState createState () => __AuthenticationViewState ();
23
+ }
22
24
25
+ class __AuthenticationViewState extends State <_AuthenticationView > {
23
26
final _emailController = TextEditingController ();
24
- final _passwordController = TextEditingController ();
27
+ // Removed password controller
28
+
29
+ @override
30
+ void dispose () {
31
+ _emailController.dispose ();
32
+ // Removed password controller disposal
33
+ super .dispose ();
34
+ }
25
35
26
36
@override
27
37
Widget build (BuildContext context) {
38
+ // Use BlocConsumer to listen for state changes for side effects (SnackBar)
28
39
return Scaffold (
29
40
body: SafeArea (
30
- child: BlocBuilder <AuthenticationBloc , AuthenticationState >(
31
- builder: (context, state) {
32
- if (state is AuthenticationLoading ) {
33
- return const Center (child: CircularProgressIndicator ());
34
- }
41
+ child: BlocConsumer <AuthenticationBloc , AuthenticationState >(
42
+ listener: (context, state) {
35
43
if (state is AuthenticationFailure ) {
36
- WidgetsBinding .instance.addPostFrameCallback ((_) {
37
- ScaffoldMessenger .of (context).showSnackBar (
38
- SnackBar (content: Text (state.errorMessage)),
44
+ ScaffoldMessenger .of (context)
45
+ ..hideCurrentSnackBar ()
46
+ ..showSnackBar (
47
+ SnackBar (
48
+ content: Text (state.errorMessage),
49
+ backgroundColor: Theme .of (context).colorScheme.error,
50
+ ),
51
+ );
52
+ } else if (state is AuthenticationLinkSentSuccess ) {
53
+ ScaffoldMessenger .of (context)
54
+ ..hideCurrentSnackBar ()
55
+ ..showSnackBar (
56
+ const SnackBar (
57
+ content: Text ('Check your email for the sign-in link.' ),
58
+ ),
39
59
);
40
- });
60
+ // Optionally clear email field or navigate
41
61
}
62
+ },
63
+ builder: (context, state) {
64
+ // Determine if loading indicator should be shown
65
+ final isLoading = state is AuthenticationLoading ||
66
+ state is AuthenticationLinkSending ;
67
+
42
68
return Padding (
43
- padding: const EdgeInsets .all (16 ),
44
- child: SingleChildScrollView (
45
- child: Column (
46
- mainAxisAlignment: MainAxisAlignment .center,
47
- children: [
48
- const Text (
49
- 'Sign In' ,
50
- style:
51
- TextStyle (fontSize: 24 , fontWeight: FontWeight .bold),
52
- ),
53
- const SizedBox (height: 32 ),
54
- TextFormField (
55
- controller: _emailController,
56
- decoration: const InputDecoration (
57
- labelText: 'Email' ,
58
- border: OutlineInputBorder (),
69
+ padding: const EdgeInsets .all (16 ), // Use AppSpacing later
70
+ child: Center (
71
+ // Center content vertically
72
+ child: SingleChildScrollView (
73
+ // Allow scrolling if needed
74
+ child: Column (
75
+ // Use CrossAxisAlignment.stretch for full-width buttons
76
+ crossAxisAlignment: CrossAxisAlignment .stretch,
77
+ children: [
78
+ Text (
79
+ 'Sign In / Register' , // Updated title
80
+ style: Theme .of (context)
81
+ .textTheme
82
+ .headlineMedium, // Use theme typography
83
+ textAlign: TextAlign .center,
84
+ ),
85
+ const SizedBox (height: 32 ), // Use AppSpacing later
86
+ TextFormField (
87
+ controller: _emailController,
88
+ decoration: const InputDecoration (
89
+ labelText: 'Email' , // Needs localization
90
+ border: OutlineInputBorder (),
91
+ ),
92
+ keyboardType: TextInputType .emailAddress,
93
+ autocorrect: false ,
94
+ textInputAction:
95
+ TextInputAction .done, // Improve keyboard action
96
+ enabled: ! isLoading, // Disable field when loading
59
97
),
60
- keyboardType: TextInputType .emailAddress,
61
- ),
62
- const SizedBox (height: 16 ),
63
- TextFormField (
64
- controller: _passwordController,
65
- decoration: const InputDecoration (
66
- labelText: 'Password' ,
67
- border: OutlineInputBorder (),
98
+ // Removed Password Field
99
+ const SizedBox (height: 32 ), // Use AppSpacing later
100
+ // Show loading indicator within the button if sending link
101
+ ElevatedButton (
102
+ onPressed: isLoading // Disable button when loading
103
+ ? null
104
+ : () {
105
+ context.read <AuthenticationBloc >().add (
106
+ AuthenticationSendSignInLinkRequested (
107
+ email: _emailController.text
108
+ .trim (), // Trim whitespace
109
+ ),
110
+ );
111
+ },
112
+ child: state is AuthenticationLinkSending
113
+ ? const SizedBox (
114
+ // Consistent height loading indicator
115
+ height: 24 ,
116
+ width: 24 ,
117
+ child:
118
+ CircularProgressIndicator (strokeWidth: 2 ),
119
+ )
120
+ : const Text (
121
+ 'Send Sign-In Link' ), // Needs localization
68
122
),
69
- obscureText: true ,
70
- ),
71
- const SizedBox (height: 32 ),
72
- ElevatedButton (
73
- onPressed: () {
74
- context.read <AuthenticationBloc >().add (
75
- AuthenticationEmailSignInRequested (
76
- email: _emailController.text,
77
- password: _passwordController.text,
78
- ),
79
- );
80
- },
81
- child: const Text ('Sign In with Email' ),
82
- ),
83
- const SizedBox (height: 16 ),
84
- ElevatedButton (
85
- onPressed: () {
86
- context
87
- .read <AuthenticationBloc >()
88
- .add (const AuthenticationGoogleSignInRequested ());
89
- },
90
- style: ElevatedButton .styleFrom (
91
- backgroundColor: Colors .white,
92
- foregroundColor: Colors .black,
123
+ const SizedBox (height: 16 ), // Use AppSpacing later
124
+ // Add divider for clarity
125
+ const Row (
126
+ children: [
127
+ Expanded (child: Divider ()),
128
+ Padding (
129
+ padding: EdgeInsets .symmetric (horizontal: 8 ),
130
+ child: Text ('OR' ), // Needs localization
131
+ ),
132
+ Expanded (child: Divider ()),
133
+ ],
93
134
),
94
- child: const Text ('Sign In with Google' ),
95
- ),
96
- const SizedBox (height: 16 ),
97
- ElevatedButton (
98
- onPressed: () {
99
- context.read <AuthenticationBloc >().add (
100
- const AuthenticationAnonymousSignInRequested (),
101
- );
102
- },
103
- child: const Text ('Sign In Anonymously' ),
104
- ),
105
- ],
106
- ),
107
- ),
108
- );
135
+ const SizedBox (height: 16 ), // Use AppSpacing later
136
+ ElevatedButton (
137
+ // Removed duplicate onPressed here
138
+ // Style adjustments for Google button might be needed via Theme
139
+ onPressed: isLoading // Disable button when loading
140
+ ? null
141
+ : () {
142
+ context.read <AuthenticationBloc >().add (
143
+ const AuthenticationGoogleSignInRequested ());
144
+ },
145
+ // Consider adding Google icon
146
+ child: const Text (
147
+ 'Sign In with Google' ), // Needs localization
148
+ ),
149
+ const SizedBox (height: 16 ), // Use AppSpacing later
150
+ OutlinedButton (
151
+ // Use OutlinedButton for less emphasis
152
+ onPressed: isLoading // Disable button when loading
153
+ ? null
154
+ : () {
155
+ context.read <AuthenticationBloc >().add (
156
+ const AuthenticationAnonymousSignInRequested (),
157
+ );
158
+ },
159
+ child: const Text (
160
+ 'Continue Anonymously' ), // Needs localization
161
+ ),
162
+ ],
163
+ ), // Column
164
+ ), // SingleChildScrollView
165
+ ), // Center
166
+ ); // Padding
109
167
},
110
- ),
111
- ),
112
- );
168
+ ), // BlocConsumer
169
+ ), // SafeArea
170
+ ); // Scaffold
113
171
}
114
172
}
0 commit comments