@@ -245,17 +245,34 @@ class PasswordLoginPage extends StatefulWidget {
245
245
}
246
246
247
247
class _PasswordLoginPageState extends State <PasswordLoginPage > {
248
- final GlobalKey <FormFieldState <String >> _usernameKey = GlobalKey ();
249
- final GlobalKey <FormFieldState <String >> _passwordKey = GlobalKey ();
248
+ bool _inProgress = false ;
250
249
251
- bool _obscurePassword = true ;
252
- void _handlePasswordVisibilityPress () {
253
- setState (() {
254
- _obscurePassword = ! _obscurePassword;
255
- });
256
- }
250
+ Future <void > _tryInsertAccountAndNavigate ({
251
+ required String email,
252
+ required String apiKey,
253
+ required int userId,
254
+ }) async {
255
+ final globalStore = GlobalStoreWidget .of (context);
256
+ // TODO(#108): give feedback to user on SQL exception, like dupe realm+user
257
+ final accountId = await globalStore.insertAccount (AccountsCompanion .insert (
258
+ realmUrl: widget.serverSettings.realmUrl,
259
+ email: email,
260
+ apiKey: apiKey,
261
+ userId: userId,
262
+ zulipFeatureLevel: widget.serverSettings.zulipFeatureLevel,
263
+ zulipVersion: widget.serverSettings.zulipVersion,
264
+ zulipMergeBase: Value (widget.serverSettings.zulipMergeBase),
265
+ ));
257
266
258
- bool _inProgress = false ;
267
+ if (! mounted) {
268
+ return ;
269
+ }
270
+
271
+ Navigator .of (context).pushAndRemoveUntil (
272
+ HomePage .buildRoute (accountId: accountId),
273
+ (route) => (route is ! _LoginSequenceRoute ),
274
+ );
275
+ }
259
276
260
277
Future <int > _getUserId (String email, apiKey) async {
261
278
final connection = ApiConnection .live ( // TODO make this widget testable
@@ -265,9 +282,51 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
265
282
return (await getOwnUser (connection)).userId;
266
283
}
267
284
285
+ @override
286
+ Widget build (BuildContext context) {
287
+ assert (! PerAccountStoreWidget .debugExistsOf (context));
288
+ final zulipLocalizations = ZulipLocalizations .of (context);
289
+
290
+ return Scaffold (
291
+ appBar: AppBar (title: Text (zulipLocalizations.loginPageTitle),
292
+ bottom: _inProgress
293
+ ? const PreferredSize (preferredSize: Size .fromHeight (4 ),
294
+ child: LinearProgressIndicator (minHeight: 4 )) // 4 restates default
295
+ : null ),
296
+ body: SafeArea (
297
+ minimum: const EdgeInsets .all (8 ),
298
+ child: Center (
299
+ child: ConstrainedBox (
300
+ constraints: const BoxConstraints (maxWidth: 400 ),
301
+ child: _UsernamePasswordForm (loginPageState: this )))));
302
+ }
303
+ }
304
+
305
+ class _UsernamePasswordForm extends StatefulWidget {
306
+ const _UsernamePasswordForm ({required this .loginPageState});
307
+
308
+ final _PasswordLoginPageState loginPageState;
309
+
310
+ @override
311
+ State <_UsernamePasswordForm > createState () => _UsernamePasswordFormState ();
312
+ }
313
+
314
+ class _UsernamePasswordFormState extends State <_UsernamePasswordForm > {
315
+ final GlobalKey <FormFieldState <String >> _usernameKey = GlobalKey ();
316
+ final GlobalKey <FormFieldState <String >> _passwordKey = GlobalKey ();
317
+
318
+ bool _obscurePassword = true ;
319
+ void _handlePasswordVisibilityPress () {
320
+ setState (() {
321
+ _obscurePassword = ! _obscurePassword;
322
+ });
323
+ }
324
+
268
325
void _submit () async {
326
+ final serverSettings = widget.loginPageState.widget.serverSettings;
327
+
269
328
final context = _usernameKey.currentContext! ;
270
- final realmUrl = widget. serverSettings.realmUrl;
329
+ final realmUrl = serverSettings.realmUrl;
271
330
final usernameFieldState = _usernameKey.currentState! ;
272
331
final passwordFieldState = _passwordKey.currentState! ;
273
332
final usernameValid = usernameFieldState.validate (); // Side effect: on-field error text
@@ -278,15 +337,15 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
278
337
final String username = usernameFieldState.value! ;
279
338
final String password = passwordFieldState.value! ;
280
339
281
- setState (() {
282
- _inProgress = true ;
340
+ widget.loginPageState. setState (() {
341
+ widget.loginPageState. _inProgress = true ;
283
342
});
284
343
try {
285
344
final FetchApiKeyResult result;
286
345
try {
287
346
result = await fetchApiKey (
288
347
realmUrl: realmUrl,
289
- zulipFeatureLevel: widget. serverSettings.zulipFeatureLevel,
348
+ zulipFeatureLevel: serverSettings.zulipFeatureLevel,
290
349
username: username, password: password);
291
350
} on ApiRequestException catch (e) {
292
351
if (! context.mounted) return ;
@@ -304,46 +363,32 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
304
363
}
305
364
306
365
// TODO(server-7): Rely on user_id from fetchApiKey.
307
- final int userId = result.userId ?? await _getUserId (result.email, result.apiKey);
366
+ final int userId = result.userId
367
+ ?? await widget.loginPageState._getUserId (result.email, result.apiKey);
308
368
// https://github.com/dart-lang/linter/issues/4007
309
369
// ignore: use_build_context_synchronously
310
370
if (! context.mounted) {
311
371
return ;
312
372
}
313
373
314
- final globalStore = GlobalStoreWidget .of (context);
315
- // TODO(#108): give feedback to user on SQL exception, like dupe realm+user
316
- final accountId = await globalStore.insertAccount (AccountsCompanion .insert (
317
- realmUrl: realmUrl,
374
+ await widget.loginPageState._tryInsertAccountAndNavigate (
318
375
email: result.email,
319
376
apiKey: result.apiKey,
320
377
userId: userId,
321
- zulipFeatureLevel: widget.serverSettings.zulipFeatureLevel,
322
- zulipVersion: widget.serverSettings.zulipVersion,
323
- zulipMergeBase: Value (widget.serverSettings.zulipMergeBase),
324
- ));
325
- // https://github.com/dart-lang/linter/issues/4007
326
- // ignore: use_build_context_synchronously
327
- if (! context.mounted) {
328
- return ;
329
- }
330
-
331
- Navigator .of (context).pushAndRemoveUntil (
332
- HomePage .buildRoute (accountId: accountId),
333
- (route) => (route is ! _LoginSequenceRoute ),
334
378
);
335
379
} finally {
336
- setState (() {
337
- _inProgress = false ;
380
+ widget.loginPageState. setState (() {
381
+ widget.loginPageState. _inProgress = false ;
338
382
});
339
383
}
340
384
}
341
385
342
386
@override
343
387
Widget build (BuildContext context) {
344
388
assert (! PerAccountStoreWidget .debugExistsOf (context));
389
+ final serverSettings = widget.loginPageState.widget.serverSettings;
345
390
final zulipLocalizations = ZulipLocalizations .of (context);
346
- final requireEmailFormatUsernames = widget. serverSettings.requireEmailFormatUsernames;
391
+ final requireEmailFormatUsernames = serverSettings.requireEmailFormatUsernames;
347
392
348
393
final usernameField = TextFormField (
349
394
key: _usernameKey,
@@ -399,28 +444,17 @@ class _PasswordLoginPageState extends State<PasswordLoginPage> {
399
444
selectedIcon: const Icon (Icons .visibility_off),
400
445
)));
401
446
402
- return Scaffold (
403
- appBar: AppBar (title: Text (zulipLocalizations.loginPageTitle),
404
- bottom: _inProgress
405
- ? const PreferredSize (preferredSize: Size .fromHeight (4 ),
406
- child: LinearProgressIndicator (minHeight: 4 )) // 4 restates default
407
- : null ),
408
- body: SafeArea (
409
- minimum: const EdgeInsets .all (8 ),
410
- child: Center (
411
- child: ConstrainedBox (
412
- constraints: const BoxConstraints (maxWidth: 400 ),
413
- child: Form (
414
- // TODO(#110) Try to highlight CZO / Zulip Cloud realms in autofill
415
- child: AutofillGroup (
416
- child: Column (mainAxisAlignment: MainAxisAlignment .center, children: [
417
- usernameField,
418
- const SizedBox (height: 8 ),
419
- passwordField,
420
- const SizedBox (height: 8 ),
421
- ElevatedButton (
422
- onPressed: _inProgress ? null : _submit,
423
- child: Text (zulipLocalizations.loginFormSubmitLabel)),
424
- ])))))));
447
+ return Form (
448
+ // TODO(#110) Try to highlight CZO / Zulip Cloud realms in autofill
449
+ child: AutofillGroup (
450
+ child: Column (mainAxisAlignment: MainAxisAlignment .center, children: [
451
+ usernameField,
452
+ const SizedBox (height: 8 ),
453
+ passwordField,
454
+ const SizedBox (height: 8 ),
455
+ ElevatedButton (
456
+ onPressed: widget.loginPageState._inProgress ? null : _submit,
457
+ child: Text (zulipLocalizations.loginFormSubmitLabel)),
458
+ ])));
425
459
}
426
460
}
0 commit comments