0

I have implemented the following login method and I am trying to use the isNewUser function to push a new screen:

Future<void> googleLogin() async {
    try {
      final googleUser = await GoogleSignIn().signIn();

      if (googleUser == null) return;

      final googleAuth = await googleUser.authentication;
      final authCredential = GoogleAuthProvider.credential(
        accessToken: googleAuth.accessToken,
        idToken: googleAuth.idToken,
      );
      UserCredential userCredential =
          await FirebaseAuth.instance.signInWithCredential(authCredential);
      if (userCredential.additionalUserInfo!.isNewUser) {
       return const SignUpNewUser();
      }
    } on FirebaseAuthException catch (e) {
      AlertDialog(
        title: const Text("Error"),
        content: Text('Failed to sign in with Google: ${e.message}'),
      );
    }
  }

I get the following error:

A value of type 'SignUpNewUser' can't be returned from the method 'googleLogin' because it has a return type of 'Future<void>'.

I'm pretty sure that I placed it in the correct spot to implement the function, but I have no idea how to do it in a Future.

DB Cooper
  • 63
  • 1
  • 9
  • The issue with pushing to a new screen may be due to the asynchronous function. You may refer to the following Stackoverflow cases. 1. https://stackoverflow.com/questions/59518783/cant-pass-firebaseuser-object-to-a-new-screen-in-flutter 2. https://stackoverflow.com/questions/55463574/how-to-check-if-the-user-is-logged-in-if-so-show-other-screen Let me know if it helps! – Mousumi Roy Nov 19 '21 at 05:16

2 Answers2

0

The problem is in the return type, you need change the type from void to dynamic.

Future<dynamic> googleLogin() async {...}
Felipe Vergara
  • 849
  • 7
  • 12
  • This clears the error but does not push to the new screen. Do I need to change the return function? – DB Cooper Nov 14 '21 at 16:17
  • Where you call this function? You need the context to use Navigator.push( context, MaterialPageRoute(builder: (context) => SignUpNewUser()), ); – Felipe Vergara Nov 14 '21 at 16:21
  • I already tried that but the Conext throws an error in relation to the build context. ```The argument type 'Context' can't be assigned to the parameter type 'BuildContext'.``` – DB Cooper Nov 14 '21 at 17:53
  • You can put the code when you call the navigator.push, please? – Felipe Vergara Nov 14 '21 at 17:56
  • ```UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(authCredential); if (userCredential.additionalUserInfo!.isNewUser) { return Navigator.push( context, MaterialPageRoute(builder: (context) => SignUpNewUser()), ); } ``` – DB Cooper Nov 14 '21 at 18:05
  • I posted the code in the above comment – DB Cooper Nov 14 '21 at 18:15
  • This function is inside build method of stateless or stateful widget? Or is inside other class? – Felipe Vergara Nov 14 '21 at 18:16
  • It's in a custom class(AuthService). I keep all of my UI and business logic separated. I use a StreamBuilder in a different file for my AuthRouting – DB Cooper Nov 14 '21 at 18:49
  • Perfect, I understand, where you call the googleLogin() function? You can put this code – Felipe Vergara Nov 14 '21 at 18:51
  • I call it in multiple places. Here is the StreamBuilder to check AuthStatus: ```return StreamBuilder( stream: AuthService().userStream, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Text(''); } else if (snapshot.hasError) { return const Center( child: Text('error'), ); } else if (snapshot.hasData) { return const HomeScreenUser(); } else { return MaterialApp( home: HomeScreenPublic(key: key,),``` – DB Cooper Nov 14 '21 at 19:39
  • I also have a button on the login page to initalize the SignIn: ```GoogleLoginButton( text: 'Sign in with Google', icon: FontAwesomeIcons.google, color: const Color(0xff262626), loginMethod: AuthService().googleLogin, ),``` – DB Cooper Nov 14 '21 at 19:40
  • Do yo need pass the context when you instance this function and then use this context to push a new router. Ex: AuthService().googleLogin(context) and then inside of Future googleLogin(context){...} – Felipe Vergara Nov 14 '21 at 20:18
  • I do not need the context passed through my login buttons in order for the auth flow to work. The actual authentication works but I am just adding this feature for my firestore db. – DB Cooper Nov 15 '21 at 04:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/239248/discussion-between-db-cooper-and-felipe-vergara). – DB Cooper Nov 15 '21 at 18:24
0

you can return a widget directly but that doesn't makes sense so you need to use Navigator in order to push to a new screen.

  1. Add context as parameter in the method googleLogin()

  2. Use this Navigator.push(context,MaterialPageRoute(builder: (context) =>your_new_screen()),); in the condition userCredential.additionalUserInfo!.isNewUser

    In the above replace your_new_screen() with the widget you have returned before ie. SignUpNewUser()

Saffron-codes
  • 158
  • 1
  • 9
  • Your solution throws an error when the login button is presses ```The following NoSuchMethodError was thrown while handling a gesture: Closure call with mismatched arguments: function 'AuthService.googleLogin' Receiver: Closure: (dynamic) => Future from Function 'googleLogin':. Tried calling: AuthService.googleLogin() Found: AuthService.googleLogin(dynamic) => Future``` – DB Cooper Nov 15 '21 at 13:29