Giter Site home page Giter Site logo

Comments (10)

brianegan avatar brianegan commented on July 19, 2024

Hey, ermagerd, so sorry I missed this notification! I'll take a look this evening and report back :)

Thanks for the kind words and submitting this issue!

from flutter_redux.

JMichaelYang avatar JMichaelYang commented on July 19, 2024

No problem at all, thanks for being available to answer these questions!

from flutter_redux.

brianegan avatar brianegan commented on July 19, 2024

Hey there! Reading through the code, I don't see anything obviously wrong... You mentioned an error: Could you describe what error you're running into? Are you getting an error from the Flutter framework itself or from Firebase / parsing?

Just to be sure: You're providing the navigatorKey to your MaterialApp as well, correct? Once that's in place, it should work without a context unless you're calling this action before the MaterialApp is in place and has constructed the NavigatorState.

from flutter_redux.

brianegan avatar brianegan commented on July 19, 2024

Coded up a quick example showing navigation with a Middleware if this helps: https://github.com/brianegan/flutter_redux/blob/simple-navigation-example/example/lib/main.dart#L20

from flutter_redux.

JMichaelYang avatar JMichaelYang commented on July 19, 2024

Hi, thanks for the quick response!

The issue is that the google_sign_in plugin is unable to run its signIn() method found in my signIn() method in the SignIn class. The method simply returns null without prompting the user to sign in, which it was able to do before I switched to Redux. I don't know if this is a problem that is under the scope of your plugin or not, but I figured I might as well try and ask.

The prompt that google_sign_in should provide is not something that I created myself, before it would just overlay over whatever I currently had on screen without the need for a Navigator or BuildContext. To be honest I don't really know how it worked.

Something that could possibly help: do you know of any examples where someone has successfully used the google_sign_in plugin in conjunction with your flutter_redux plugin?

Thanks again.

from flutter_redux.

brianegan avatar brianegan commented on July 19, 2024

No worries! I work on both redux and this plugin, so happy to cover both scopes :)

google_sign_in shouldn't need context or anything like that. Generally, it will open a native view on Android or iOS rather than displaying flutter widgets.

I tried a simplified test case to see if google sign in works within Middleware. When you tap the Button, it should launch google sign in from within the middleware. This worked from my end, does it work for you?

Hrm, there are some projects I know of that use them in combination, but they're private repos or companies :(

import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:redux/redux.dart';

void main() => runApp(new MyApp());

final _googleSignIn = new GoogleSignIn(
  scopes: [
    'email',
    'https://www.googleapis.com/auth/contacts.readonly',
  ],
);

void signInMiddleware(
  Store<String> store,
  dynamic action,
  NextDispatcher next,
) {
  next(action);

  try {
    _googleSignIn.signIn();
  } catch (error) {
    print(error);
  }
}

final store = new Store<String>((state, action) => action.toString(),
    middleware: [signInMiddleware]);

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              'You have pushed the button this many times:',
            ),
            new Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          store.dispatch("Sign in");
        },
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

from flutter_redux.

JMichaelYang avatar JMichaelYang commented on July 19, 2024

I was somehow able to fix the problem by making my GoogleSignIn instance a non-static field within the SignIn class rather than a static field in a different class (do you have any insight into why this worked?).

I have, however, run into another problem. It seems that calling the googleSignIn.signIn() method works, but for some reason it does not return the signed in account. I must call googleSignIn.signInSilently() afterwards in order to get a reference to the signed in account.

I found this out because I had to press my "sign in" button twice. The first time gave me the correct prompt, but set the account to null which then threw an error (which I caught). The second time pressing the button worked with a silent sign in (no prompt).

Any idea why this might be happening? Attached is the updated relevant code:

SignIn

/// Performs sign in operations with real network data.
class SignIn extends ISignIn {
  final IProfileStore store;
  final GoogleSignIn googleSignIn = new GoogleSignIn(scopes: [
    "email",
    "https://www.googleapis.com/auth/contacts.readonly",
  ]);

  SignIn() : store = new ProfileInjector().profileLoader;

  Future<ProfilePackage> signIn() async {
    // Check to see if there is currently a signed in user.
    final GoogleSignInAccount account = googleSignIn.currentUser;

    // Try to sign in without prompting the user.
    if (account == null) {
      account == await googleSignIn.signInSilently();
    }

    // If this doesn't work, prompt the user to sign in.
    if (account == null) {
      account == await googleSignIn.signIn();
    }

    // If this doesn't work, throw an error that should tell the user that
    // they must sign in.
    if (account == null) {
      throw new StateError("The user must log in.");
    }

    final GoogleSignInAuthentication auth = await account.authentication;

    // Authenticate the user with firebase.
    final FirebaseUser user = await Networking.firebaseAuth
        .signInWithGoogle(idToken: auth.idToken, accessToken: auth.accessToken);

    if (user == null || user.isAnonymous) {
      throw new StateError("Log in error.");
    }

    final ProfilePackage package = await store.loadProfile(user.uid);

    // No user was found, so create a new one and save it to the database.
    if (package == null) {
      ProfilePackage newPackage =
          new ProfilePackage.fromGoogleSignIn(account, user);
      await store.saveProfile(newPackage);
      return newPackage;
    } else {
      return package;
    }
  }

  Future<Null> signOut() async {
    await googleSignIn.signOut();
    await Networking.firebaseAuth.signOut();
  }

  Future<Null> signOutAndDelete(String uid) async {
    await store.deleteProfile(uid);
    await signOut();
  }
}

Middleware for good measure

/// Creates the [Middleware] associated with a sign in attempt.
Middleware<AppState> _createSignIn(ISignIn signIn) {
  return (Store<AppState> store, action, NextDispatcher next) {
    signIn.signIn().then(
      (user) {
        store.dispatch(
          new SignedInAction(
            new Profile.fromPackage(user),
          ),
        );
        Keys.navigatorKey.currentState
            .pushReplacementNamed(InternalStrings.mainScreenRoute);
      },
    ).catchError(
      (_) {
        store.dispatch(new FailedSignInAction());
      },
    );

    next(action);
  };
}

from flutter_redux.

brianegan avatar brianegan commented on July 19, 2024

"I was somehow able to fix the problem by making my GoogleSignIn instance a non-static field within the SignIn class rather than a static field in a different class (do you have any insight into why this worked?)."

Dart is a bit weird about statics... if you use them in one file it will create the object, then if you use them in another file after importing it will recreate the object :( Don't ask me why :(

Because of that, I generally avoid statics unless I'm hacking something together quickly for an idea.

"I have, however, run into another problem. It seems that calling the googleSignIn.signIn() method works, but for some reason it does not return the signed in account"

Unfortunately, I'm not sure why that would be the case. Did it work before you introduced Redux? If not, you'd probably have to file a bug against the Flutter repo.

from flutter_redux.

JMichaelYang avatar JMichaelYang commented on July 19, 2024

Dart is a bit weird about statics... if you use them in one file it will create the object, then if you use them in another file after importing it will recreate the object :( Don't ask me why :(

Wow, that's good to know, thank you for that insight. I'll be sure to rearrange the rest of my code to avoid them as much as possible.

Unfortunately, I'm not sure why that would be the case. Did it work before you introduced Redux? If not, you'd probably have to file a bug against the Flutter repo.

It did work before, I'll go ahead and mess around with it to see if I can't figure out why it's broken.

Thank you again for your help, you're a lifesaver.

I will go ahead and mark this as closed.

from flutter_redux.

brianegan avatar brianegan commented on July 19, 2024

Sure thing, thanks for the Qs! Best of luck with the app :)

from flutter_redux.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.