Flutter : New error after dart migrate and null safety - flutter

After running dart migrate I got a ton of errors, most of them I believe I have fixed, but the last one does not make sense to me.
Stream<UserData> get user{
return _auth.authStateChanges()
.asyncMap(_userFromFireBaseUser as FutureOr<UserData> Function(User?));
}
The problematic part is the .asyncMap... The part "as FutureOr<UserData> Function(User?));" Was added by the dart migrate.
The errors I am getting are
error: Undefined class 'FutureOr'. (undefined_class) and error: The
argument type 'dynamic Function(User?)' can't be assigned to the
parameter type 'FutureOr Function(User?)'.
Posting rest of the code as well, it is used for Authentication.
class AuthService extends ChangeNotifier
{
// UserData _currentUser = AuthService();
String? _uid;
String? _email;
String? get getUid => _uid;
String? get getEmail => _email;
final FirebaseAuth _auth = FirebaseAuth.instance;
//Create user ojb based on firebaseuser
UserData? _userFromFireBaseUser(User? user) {
return user != null ? UserData(uid: user.uid) : null;
}
Stream<UserData> get user{
return _auth.authStateChanges()
.asyncMap(_userFromFireBaseUser as FutureOr<UserData> Function(User?));
}
//Get UID
Future getCurrentUID() async
{
final currentUid = await _auth.currentUser!.uid;
return currentUid;
}
//Sign in(anon)
Future signInAnon() async
{
try
{
UserCredential result = await _auth.signInAnonymously();
User? user = result.user;
return _userFromFireBaseUser(user);
}
catch(e) {
print(e.toString());
return null;
}
}
What is causing the error?

You can simply remove type cast to FutureOr<UserData> Function(User?) because _userFromFireBaseUser is already the function that gets User? and returns UserData?. To avoid returning null values from the stream just filter them with where. Use this code:
Stream<UserData> get user {
return _auth.authStateChanges()
.asyncMap(_userFromFireBaseUser)
.where((user) => user != null)
.map((user) => user!);
}

Related

The body might complete normally, causing 'null' to be returned, but the return type, 'Future<Useri, is a potentially non-nullable type

class FirebaseAuthService implements AuthBase {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
#override
Future<Userim> currentUser() async {
try {
User? user = await _firebaseAuth.currentUser;
return _userFromFirebase(user);
} catch (e) {
print('ERROR CURRENT USER' + e.toString());
}
}
Userim _userFromFirebase(User? user) {
if (user == null) {
return null;
} else {
return Userim(userID: user.uid);
}
}
}
class Userim{
final String userID;
Userim({required this.userID});
}
In my code when using Flutter Firebase currentUser() in the method :
The body might complete normally, causing 'null' to be returned, but the return type, 'Future<Userim>', is a potentially non-nullable type.
Try adding either a return or a throw statement at the end.
i am getting the error.
also return null
A value of type 'Null' can't be returned from the method '_userFromFirebase' because it has a return type of 'Userim'
If you want your return value to be nullable just add ? to its type declaration:
Future<Userim?> currentUser() async... etc.
and in
Userim? _userFromFirebase(User? user) {... etc.

show display name after signUp

I have a flutter firebase createUserWithEmailAndPassword function with the displayName update.
display name prints normally at the moment of fb user creation.
After signup MainPage loads with the users email and displayName. But displayName returns null value error. If I delete displayName from the MainPage - all works fine.
If I reload app, it works fine.
When I login, it works fine.
It can't pass the displayName at the moment of signup only.
Where I am wrong?
class AuthServiceProvider extends ChangeNotifier {
final auth.FirebaseAuth _firebaseAuth = auth.FirebaseAuth.instance;
final googleSingIn = GoogleSignIn();
UserModel? _userFromFirebase(auth.User? user) {
if (user == null) {
return null;
}
return UserModel(
user.displayName,
user.uid,
user.email,
);
}
Stream<UserModel?>? get user {
return _firebaseAuth.authStateChanges().map(_userFromFirebase);
}
Future<UserModel?> createUserWithEmailAndPassword(
String name,
String email,
String password,
) async {
try {
final userCred = await _firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
);
auth.User? firebaseUser = _firebaseAuth.currentUser;
if (firebaseUser != null) {
await firebaseUser.updateDisplayName(name);
await firebaseUser.reload();
firebaseUser = _firebaseAuth.currentUser;
}
print('FIREBASE USER IS $firebaseUser');
return _userFromFirebase(firebaseUser);
} catch (e) {
print(e.toString());
return null;
}
}
}
If your class were to extend either StatelessWidget or StatefulWidget, then all you'd have to do is to pass the data (displayName) between the screens.
This is not an answer but a suggestion:
You should try changing the ChangeNotifier to a StatefulWidget
and pass the data between screens...
You could also setup an
Authentication class that will hold all these Future methods so that
these calls can be reusable in your code. With this method, all you have to do is to call the specific function and give its required parameters.
As usually the solution is very simple if you think a little bit.
As all this is through the firebase auth, at the main page loading I just grab the firebase user with its display name that is saved in FB both for GoogleSignIn and createUserWithEmailAndPassword (required at registration)
import 'package:firebase_auth/firebase_auth.dart' as auth;
final auth.FirebaseAuth _firebaseAuth = auth.FirebaseAuth.instance;
final String firebaseUser =
_firebaseAuth.currentUser!.displayName ?? 'Unknown user';

The argument type 'CurrentUser? Function(User)' can't be assigned to the parameter type 'CurrentUser Function(User?)'

The argument type 'CurrentUser? Function(User)' can't be assigned to the parameter type 'CurrentUser Function(User?)'.dartargument_type_not_assignable
CurrentUser? _userFromFirebase(User user)
package:brew_crew/services/auth.dart
im getting this error i was creating anonimouse user login on flutter firebase
can any help me out..
code is below
// Create user object based on FirebaseUser
CurrentUser? _userFromFirebase(User user) {
return user != null ? CurrentUser (uid: user.uid) : null;
}
// auth change obj stream
Stream<CurrentUser> get users{
return _auth.authStateChanges().map(_userFromFirebase);
}
full code is here
import 'package:brew_crew/model/user.dart';
import 'package:firebase_auth/firebase_auth.dart';
class AuthService{
final FirebaseAuth _auth = FirebaseAuth.instance;
// Create user object based on FirebaseUser
CurrentUser? _userFromFirebase(User user) {
return user != null ? CurrentUser (uid: user.uid) : null;
}
// auth change obj stream
Stream<CurrentUser> get users{
return _auth.authStateChanges().map(_userFromFirebase);
}
//sin in anon
Future signInAnon() async{
try {
UserCredential result = await _auth.signInAnonymously();
User? user = result.user;
return _userFromFirebase(user!);
}catch (e) {
print(e.toString());
return null;
}
}
//sign in with E-mail and password
//Register with E-mail and passqord
//Sign out
}
thanks
You can just change your Stream type to CurrentUser?:
CurrentUser? _userFromFirebase(User user) {
return user != null ? CurrentUser (uid: user.uid) : null;
}
// v
Stream<CurrentUser?> get users{
return _auth.authStateChanges().map(_userFromFirebase);
}

error: The argument type 'UserModel? Function(User?)' can't be assigned to the parameter type 'UserModel Function(User?)'

I am getting the following error in flutter.
UserModel is a class
class UserModel {
final String uid;
UserModel({this.uid});
}
And the code where this error is coming up is
Stream<UserModel> get user {
return _auth.authStateChanges()
.map(_userFromFirebaseUser);
}
Complete code:
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
UserModel? _userFromFirebaseUser(User? user) {
return user != null ? UserModel(uid: user.uid) : null;
}
Stream<UserModel> get user {
return _auth.authStateChanges()
.map(_userFromFirebaseUser);
}
Future signInAnon() async {
try {
UserCredential result = await _auth.signInAnonymously();
User user = result.user!;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
Future signInWithEmailAndPassword( String email, String password) async {
try {
UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
User user = result.user!;
return _userFromFirebaseUser(user);
} catch(e){
print(e.toString());
return null;
}
}
Future signUpWithEmailAndPassword( String email, String password) async {
try {
UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
User user = result.user!;
return _userFromFirebaseUser(user);
} catch(e){
print(e.toString());
return null;
}
}
Future signOut() async {
try {
return await _auth.signOut();
} catch (e){
print(e.toString());
return null;
}
}
}
This is happening because your _userFromFirebaseUser is defined something like this,
UserModel? _userFromFirebaseUser(User? user) {
So this means that you are saying, your _userFromFirebaseUser might return a UserModel or might return a null.
One way to fix this is to make your getter return Stream<UserModel?> instead of Stream<UserModel>.
Stream<UserModel?> get user {
return _auth.authStateChanges()
.map(_userFromFirebaseUser);
}
Now your getter might return a UserModel or it might return a null.
I had the same problem and I'm glad I found the solution :
UserModel _userFromFirebase (User? user){
return UserModel(uid: user!.uid);
}
Stream<UserModel> get user{
return _auth.authStateChanges().map(_userFromFirebase);
}
and if _userFromFirebase appears error use:
_userFromFirebase(user.user) ;

Cannot use data from GraphQl query after getting data using Flutter and Ferry

I currently have a function in a bloc which is calling my repository to grab data from my server using GraphQL. I am able to get the data back. However I am not able to return it to my bloc as the function exits out after grabbing the data.
Here is the code in my bloc....
Either<AuthFailure, GLoginData_login> failureOrSuccess;
failureOrSuccess = await loginWithUsernameAndPassword(username: state.username, password: state.password)
.whenComplete(() { <---------- This line is never triggered (why not?)
failureOrSuccess.fold((l) => null, (r) {
print('You have the data $r');
});
});
As you can see I am awaiting for the response from the forwardedCall.
Here is the code in my repository which the bloc calls....
abstract class LoginRepository<TData, TVars, TRequest extends OperationRequest<TData, dynamic>> {
Future<Either<AuthFailure, GLoginData_login>> loginWithUsernameAndPassword({
#required Username username,
#required Password password,
});
}
This repository is an abstract class where the method is implemented in the following class...
class LoginUser extends LoginRepository {
#override
Future<Either<AuthFailure, GLoginData_login>> loginWithUsernameAndPassword(
{#required Username username, #required Password password}) =>
_runQuery(username: username, password: password);
Future<Either<AuthFailure, GLoginData_login>> _runQuery(
{#required Username username, #required Password password}) async {
final loginReq = GLoginReq(
(b) => b
..vars.LoginInput.username = usernameStr
..vars.LoginInput.password = passwordStr,
);
try {
return await GetIt.instance<Client>().request(loginReq).listen((response) {
if (!response.loading && response.dataSource == DataSource.Link &&
response.data != null) {
GLoginData data = response.data;
GLoginData_login login = data.login;
return login;
}
if (response.linkException != null) {
return response.graphqlErrors;
}
}).asFuture(); <------ I am marking it as a future so that it can be passed back
} on Exception catch (e) {
// Will need a created AuthException depending on our API and requirements
if (e.toString() == 'ERROR_NO_ACCOUNT_MATCHES_DETAILS_GIVEN') {
return left(const AuthFailure.invalidUsernameAndPaswordCombination());
} else {
return left(const AuthFailure.serverError());
}
}
}
}
I do receive the data from the serverising the client response. However in my bloc I cannot do anything with it as it just jumps out of the bloc after the loginWithUsernameAndPassword function completes.
How can I use the return value in my bloc, the whenComplete value line isn't working.
Thanks for any help you can provide.
just do:
either.fold(
(l) => Something(),
(r) => Something(),
);
If you have a function that returns the values then put the l or r into the function.