Я занимаюсь разработкой флаттера, следуя этой архитектуре, которую можно визуализировать здесь . Существует требование, что мне нужно использовать другой входящий поток, когда пользователь регистрируется впервые, помимо обычного потока.
Итак, немного покопавшись, я обнаружил, что Firebase предоставляет переменная bool isNewUser
в объекте additionalUserInfo
класса AuthResult
. Поэтому, естественно, моей первой мыслью было передать это bool в модель User
, чтобы я мог проверить, зарегистрировался ли пользователь впервые и пройти соответствующий маршрут в классе AuthWidget
, как этот.
class AuthWidget extends StatelessWidget {
const AuthWidget({Key key, @required this.userSnapshot}) : super(key: key);
final AsyncSnapshot<User> userSnapshot;
@override
Widget build(BuildContext context) {
if (userSnapshot.connectionState == ConnectionState.active) {
if (userSnapshot.hasData) {
return userSnapshot.data.isNew ? OnBoardingPage() : RootWidget();
} else {
return SignInPageBuilder();
}
}
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
));
}
}
Поэтому, передавая логическую переменную в пользовательскую модель из моего класса FirebaseAuthService
, я столкнулся с некоторыми проблемами. Это то, что я думал делать в классе FirebaseAuthService
. Я оставил комментарии внутри кода для лучшего понимания.
class FirebaseAuthService {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
User _userFromFirebase(FirebaseUser user, AdditionalUserInfo additionalUserInfo) {
if(user == null){
return null;
}
return User(
uid: user.uid,
email: user.email,
photoUrl: user.photoUrl,
displayName: user.displayName,
isNew: additionalUserInfo.isNewUser // Passing this new variable from the AdditionalUserInfo var we passed as an argument
);
}
Stream<User> get onAuthStateChanged {
// This is where the first trouble is. The linter shows me the error :
// The argument type 'User Function(FirebaseUser, AdditionalUserInfo)' can't be assigned to the parameter type 'User Function(FirebaseUser)'.
// So I guess no other arguments can be passed to the _userFromFirebase function
return _firebaseAuth.onAuthStateChanged.map(_userFromFirebase);
}
Future<User> signInUsingGoogle() async {
final GoogleSignIn googleSignIn = GoogleSignIn();
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: googleSignInAuthentication.idToken,
accessToken: googleSignInAuthentication.accessToken
);
final AuthResult authResult = await _firebaseAuth.signInWithCredential(credential);
// passing the additionalUserInfo variable
return _userFromFirebase(authResult.user, authResult.additionalUserInfo);
}
Future<User> signInUsingFacebook() async {
final FacebookLogin facebookLogin = FacebookLogin();
final FacebookLoginResult facebookLoginResult = await facebookLogin.logIn(['email']);
switch(facebookLoginResult.status) {
case FacebookLoginStatus.cancelledByUser:
print("Cancelled by user");
break;
case FacebookLoginStatus.error:
print("error sigining using facebook");
break;
case FacebookLoginStatus.loggedIn:
print("Logged In with facebook");
break;
}
final accessToken = facebookLoginResult.accessToken.token;
if(facebookLoginResult.status == FacebookLoginStatus.loggedIn) {
final facebookAuthcred = FacebookAuthProvider.getCredential(accessToken: accessToken);
final AuthResult authResult = await _firebaseAuth.signInWithCredential(facebookAuthcred);
// Same as Google login flow
return _userFromFirebase(authResult.user, authResult.additionalUserInfo);
}
return null;
}
Future<User> currentUser() async {
final FirebaseUser user = await _firebaseAuth.currentUser();
// This is the second confusion.
// Since we don't have an AuthResult object, how do I pass that variable.
// I could set the default value for the variable to null/false but I don't think that will be a scalable solution
return _userFromFirebase(user);
}
Future<void> signOut() async {
return _firebaseAuth.signOut();
}
}
Пожалуйста, предложите, если есть лучший способ реализовать это. Спасибо!