The last thing needed for each of these pages is a way to pass the user input for each field as credentials that can be processed for login/sign up.
Create a new file called auth_credentials.dart and add the following:
// 1
abstract class AuthCredentials {
final String username;
final String password;
AuthCredentials({this.username, this.password});
}
// 2
class LoginCredentials extends AuthCredentials {
LoginCredentials({String username, String password})
: super(username: username, password: password);
}
// 3
class SignUpCredentials extends AuthCredentials {
final String email;
SignUpCredentials({String username, String password, this.email})
: super(username: username, password: password);
}
Add these two functions to auth_service.dart:
... // showLogin closing } (line 28)
// 1
void loginWithCredentials(AuthCredentials credentials) {
final state = AuthState(authFlowStatus: AuthFlowStatus.session);
authStateController.add(state);
}
// 2
void signUpWithCredentials(SignUpCredentials credentials) {
final state = AuthState(authFlowStatus: AuthFlowStatus.verification);
authStateController.add(state);
}
And auth_credetials to auth_service.dart
... // import 'dart:async'; (line 1)
import 'auth_credentials.dart';
...
Let’s start by updating login_page.dart to send LoginCredentials via a ValueChanged property.
... // import 'package:flutter/material.dart'; (line 1)
import 'auth_credentials.dart';
... // class LoginPage extends StatefulWidget {
final ValueChanged<LoginCredentials> didProvideCredentials;
... // final VoidCallback shouldShowSignUp;
LoginPage({Key key, this.didProvideCredentials, this.shouldShowSignUp})
: super(key: key);
... // @override
We can now pass our credentials from the _login() method in _LoginPageState:
... // print('password: $password'); (line 80)
final credentials =
LoginCredentials(username: username, password: password);
widget.didProvideCredentials(credentials);
... // _login closing }
Let’s implement something similar for sign_up_page.dart:
... // import 'package:flutter/material.dart'; (line 1)
import 'auth_credentials.dart';
... // class SignUpPage extends StatefulWidget {
final ValueChanged<SignUpCredentials> didProvideCredentials;
... // final VoidCallback shouldShowLogin;
SignUpPage({Key key, this.didProvideCredentials, this.shouldShowLogin})
: super(key: key);
... // @override
And create the credentials:
... // print('password: $password'); (line 81)
final credentials = SignUpCredentials(
username: username,
email: email,
password: password
);
widget.didProvideCredentials(credentials);
... // _signUp closing }
Now connect everything in main.dart:
... // child: LoginPage( (line 42)
didProvideCredentials: _authService.loginWithCredentials,
... // shouldShowSignUp: _authService.showSignUp)),
... // child: SignUpPage( (line 50)
didProvideCredentials: _authService.signUpWithCredentials,
... // shouldShowLogin: _authService.showLogin))
That wraps up LoginPage and SignUpPage, but as we saw with AuthFlowStatus we still need to implement a page for verification and pages to represent a session.
Let’s add VerificationPage in a new file verification_page.dart:
import 'package:flutter/material.dart';
class VerificationPage extends StatefulWidget {
final ValueChanged<String> didProvideVerificationCode;
VerificationPage({Key key, this.didProvideVerificationCode})
: super(key: key);
@override
State<StatefulWidget> createState() => _VerificationPageState();
}
class _VerificationPageState extends State<VerificationPage> {
final _verificationCodeController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
minimum: EdgeInsets.symmetric(horizontal: 40),
child: _verificationForm(),
),
);
}
Widget _verificationForm() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Verification Code TextField
TextField(
controller: _verificationCodeController,
decoration: InputDecoration(
icon: Icon(Icons.confirmation_number),
labelText: 'Verification code'),
),
// Verify Button
FlatButton(
onPressed: _verify,
child: Text('Verify'),
color: Theme.of(context).accentColor)
],
);
}
void _verify() {
final verificationCode = _verificationCodeController.text.trim();
widget.didProvideVerificationCode(verificationCode);
}
}
The VerificationPage is really just a slimmed down version of LoginPage and only passes a verification code up the widget tree.
Back in auth_service.dart, there needs to be a method to handle the verification code and update the state to session.
... // signUpWithCredentials closing } (line 41)
void verifyCode(String verificationCode) {
final state = AuthState(authFlowStatus: AuthFlowStatus.session);
authStateController.add(state);
}
... // AuthService closing }
Now add the VerificationPage to the Navigator of main.dart.
... // import 'auth_service.dart'; (line 4)
import 'verification_page.dart';
... // shouldShowLogin: _authService.showLogin)), (line 54)
// Show Verification Code Page
if (snapshot.data.authFlowStatus == AuthFlowStatus.verification)
MaterialPage(child: VerificationPage(
didProvideVerificationCode: _authService.verifyCode))
... // pages closing ],
For the moment, we’re going to add a placeholder page that we will come back and add functionality to. Add gps_page.dart with the following content :
import 'package:flutter/material.dart';
// 1
class GpsPage extends StatelessWidget {
// 2
final VoidCallback shouldLogOut;
GpsPage({Key key, this.shouldLogOut}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('GPS Co-ordinates'),
actions: [
// Log Out Button
Padding(
padding: const EdgeInsets.all(8),
child:
GestureDetector(child: Icon(Icons.logout), onTap: shouldLogOut),
)
],
),
// 5
body: Container(),
);
}
}
To close the navigation loop of our UI, we need to add a log out method to auth_service.dart.
... // verifyCode closing } (line 46)
void logOut() {
final state = AuthState(authFlowStatus: AuthFlowStatus.login);
authStateController.add(state);
}
... // AuthService closing }
Finally, implement the case for GpsPage in the Navigator.pages of main.dart.
... // import 'verification_page.dart' (line 5)
import 'gps_page.dart';
... // _authService.verifyCode)), (line 62)
if (snapshot.data.authFlowStatus == AuthFlowStatus.session)
MaterialPage(
child: GpsPage(shouldLogOut: _authService.logOut))
... // pages closing ] ],
The application should allow you to navigate between sign up, login and the placeholder GPS Page (which allows you to log out).
Congratulations, you’re now ready to commence Module 2!