vendredi 5 novembre 2021

Flutter Web) There is a problem with firebase Auth status management

I'm using flutter web and firebase. I'm using firebase Auth's email authentication, and there are two problems.

  1. When refresh the web, authentication is disconnected.
  2. Sometimes there is a problem of falling into infinite loading when logging in

I used almost the same code that I made in the previous app, and when I run it on the app, it works fine.

pubspec.yaml

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
      firebase_core: ^0.5.0 
  firebase_auth: ^0.18.0 
  cloud_firestore: ^0.14.0 
  firebase_storage: ^4.0.0 
  flutter_web_frame: ^0.0.2 #Web size
  carousel_slider: ^3.0.0
  get: ^3.3.0
  cached_network_image: ^2.2.0+1
  provider: ^4.3.3
  google_sign_in: ^4.5.9

index.html

</script>

<script src = "https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.22.1/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-storage.js"></script>

<script>

  var firebaseConfig = {
    apiKey: ,
    authDomain: ,
    projectId: ,
    storageBucket: ,
    messagingSenderId: ,
    appId: ,
    measurementId: 
  };

  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
  firebase.getAnalytics(app);

</script>

This is part of my authentication code.

firebase_auth_state.dart

enum FirebaseAuthStatus { signout, progress, signin }

class FirebaseAuthState extends ChangeNotifier {
  FirebaseAuthStatus _firebaseAuthStatus = FirebaseAuthStatus.progress;
  FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
  User _firebaseUser;
        
  //check user state
  void watchAuthChange() {
    _firebaseAuth.authStateChanges().listen((firebaseUser) {
      //when first
      if (firebaseUser == null && _firebaseUser == null) {
          changeFirebaseAuthStatus();

        return;
        //firebaseUser update
      } else if (firebaseUser != _firebaseUser) {
        _firebaseUser = firebaseUser;
        //auth state change check
        changeFirebaseAuthStatus();
      }
    });
  }

  void changeFirebaseAuthStatus([FirebaseAuthStatus firebaseAuthStatus]) {
    if (firebaseAuthStatus != null) {
      _firebaseAuthStatus = firebaseAuthStatus;
    } else {
      if (_firebaseUser != null) {
        _firebaseAuthStatus = FirebaseAuthStatus.signin;
      } else {
        _firebaseAuthStatus = FirebaseAuthStatus.signout;
      }
    }

    notifyListeners();
  }

  void registerUser(BuildContext context,
      {@required String email, @required String password}) async {
    if (_firebaseUser != null) {
      //loading
      changeFirebaseAuthStatus(FirebaseAuthStatus.progress);
    }

    UserCredential userCredential = await _firebaseAuth
        .createUserWithEmailAndPassword(
            email: email.trim(),
            password: password.trim())

    _firebaseUser = userCredential.user;
    if (_firebaseUser == null) {
      SnackBar snackBar = SnackBar(
        content: Text("error?"),
      );
      ScaffoldMessenger.of(context).showSnackBar(snackBar);
    } else {
      //User firestore upload
      userNetworkRepo.attempCreatUser(
          userKey: _firebaseUser.uid,
          userEmail: _firebaseUser.email);
    }
  }

  void signIn(BuildContext context,
      {@required String email, @required String password}) async {
    if (_firebaseUser != null) {
      changeFirebaseAuthStatus(FirebaseAuthStatus.progress);
    }

    UserCredential userCredential = await _firebaseAuth
        .signInWithEmailAndPassword(
            email: email.trim(), password: password.trim())
        .catchError((error) {
      print(error);
     }

    _firebaseUser = userCredential.user;
    if (_firebaseUser == null) {
      SnackBar snackBar = SnackBar(
        content: Text("error?"),
      );
      ScaffoldMessenger.of(context).showSnackBar(snackBar);
    }
  }

  void signOut() async {
    changeFirebaseAuthStatus(FirebaseAuthStatus.progress);

    _firebaseAuthStatus = FirebaseAuthStatus.signout;
    if (_firebaseUser != null) {
      _firebaseUser = null;
      _firebaseAuth.signOut();
    }

    notifyListeners();
  }

  //create instance
  FirebaseAuthStatus get firebaseAuthStatus => _firebaseAuthStatus;

  User get firebaseUser => _firebaseUser;
}

And in main.dart, sign in or sign out according to the authentication status.

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  FirebaseAuthState _firebaseAuthState = FirebaseAuthState();

  //current auth state
  Widget _currentWidget;

  @override
  Widget build(BuildContext context) {
    _firebaseAuthState.watchAuthChange();

    //Web max size
    return FlutterWebFrame(
      builder: (BuildContext context) {
        return MultiProvider(
          providers: [
            ChangeNotifierProvider<FirebaseAuthState>.value(
                value: _firebaseAuthState),
            ChangeNotifierProvider<UserModelState>(
              create: (_) => UserModelState(),
            ),
          ],
          child: GetMaterialApp(
            debugShowCheckedModeBanner: false,
            theme: ThemeData(
              primarySwatch: white,
            ),

            home: Consumer<FirebaseAuthState>(
              builder: (BuildContext context, FirebaseAuthState firebaseAuthState,
                  Widget child) {
                switch (firebaseAuthState.firebaseAuthStatus) {
                  case FirebaseAuthStatus.signout:
                    _clearUserModel(context);
                    _currentWidget = AuthScreen();
                    break;

                  case FirebaseAuthStatus.signin:
                    _initUserModel(firebaseAuthState, context);
                    _currentWidget = HomeScreen();
                    break;

                  default:
                    _currentWidget = CustomLoading();
                    break;
                }

                return AnimatedSwitcher(
                  duration: Duration(milliseconds: 300),
                  child: _currentWidget,
                );
              },
            ),
          ),
        );
      },

      //Web max size
      maximumSize: Size(768.0, 1024.0),
      enabled: true,
    );
  }

  //userModel update
  _initUserModel(FirebaseAuthState firebaseAuthState, BuildContext context) {
    UserModelState userModelState =
    Provider.of<UserModelState>(context, listen: false);

    // if (userModelState.currentStreamSub == null) {
    userModelState.currentStreamSub = userNetworkRepo
        .getUserModelStream(firebaseAuthState.firebaseUser.uid)
        .listen((userModel) {
      userModelState.userModel = userModel;

      print('userModel: ${userModel.username} , ${userModel.userKey}');
    });
  }

  _clearUserModel(BuildContext context) {
    UserModelState userModelState =
    Provider.of<UserModelState>(context, listen: false);
    userModelState.clear();
  }
}

The biggest problem is that sometimes I can't signIn well. May I know the cause and solution of this?

Thank you!




Aucun commentaire:

Enregistrer un commentaire