Giter Club home page Giter Club logo

flutter_starter's People

Contributors

delay avatar nipodemos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flutter_starter's Issues

Localizations

Hello Jeff,

Great project that I think is very helpful and time-saving for other devs. I have one question because it seems that when I have my google sheet and update the documentId and the sheetId and run the command line dart update_localizations.dart it works fine as seen below

---------------------------------------
Downloading Google sheet url "https://docs.google.com/spreadsheets/d/1Ye9FMIJocRGBdOPk7CSo5obWlltcz2hPFiIn0B0P8ls/export?format=csv&id=1Ye9FMIJocRGBdOPk7CSo5obWlltcz2hPFiIn0B0P8ls&gid=0" ...
---------------------------------------

---------------------------------------
Saving localization.g.dart
---------------------------------------
Done...

But my file localizations.g.dart does not download the content in the google sheet

import 'package:get/get.dart';

class Localization extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
            };
      }

It works fine when I use your google sheet document Id. Is it maybe that I need to do something with my google sheet? For example, make it public or download it somewhere else. Because it doesn’t seem that the code realizes there is content in my google sheet.

Admin Role suggestion

Hey Jeff,

First things first: This Project is extremely helpful and saves a lot of time - thank you for that!

I wanted to ask, why it is needed to save the admin role in a separate collection, since you can restrict access to specific fields of a document e.g.:

allow update: if (!request.resource.data.diff(resource.data).affectedKeys()
.hasAny(['role', 'other_field']));

I'm not an expert so correct me If a am worng but I think this would reduce load/traffic and save miniscule time.

name can only contain letters

cool start for a starter! when signing up, if you choose your name to be like elon musk's child and put a number in it, you get a validation error

Update User Success Notice Bug

When you update your email with an email that already exists in the database, you get an update user success notice even though the update should fail and the snack bar notice should be "Email is already in use" or something like that.

Loading issue

Hi Jeff,

I am a Flutter enthusiast and have been studying a lot lately.

I liked very much this project sample and I'm using it as an example for me.

Especially the Loader that it can be called anywhere in the code.

But I notice a problem, despite the loading ignore touches due to Overlay, the physical back button on Android Devices still works. Therefore, during loading I may end up leaving the screen if I press back button.

I tried to use WillPopScore, but it didn't work.

Do you have any ideas to workaround it?

Thank you very much in advance

Fabio Hideki

Possible to access translation labels without context?

Great tutorial on Medium!! Thanks a lot!

Is there a way to eliminate the necessity of passing BuildContext in

final labels = AppLocalizations.of(context);

using GetX? I sometimes have to reference the translation labels also in some of my controller/services classes where I usually try to avoid using BuildContext as much as possible (trying to separate UI and Business Logic).

Error with dependencies when running the project

When running your sample project i receive the following error.

Because firebase_auth >=0.18.4 <=0.18.4 depends on firebase_auth_web ^0.3.2+2 and firebase_auth ^0.18.4+1 depends on firebase_auth_web ^0.3.2+3, firebase_auth ^0.18.4 requires firebase_auth_web ^0.3.2+2.
(1) So, because firebase_auth >=0.18.3+1 <0.18.4 depends on firebase_auth_web ^0.3.2+1, firebase_auth ^0.18.3+1 requires firebase_auth_web ^0.3.2+1.

Because firebase_auth >=0.18.3 <=0.18.3 depends on firebase_auth_web ^0.3.2 and firebase_auth >=0.18.2 <0.18.3 depends on firebase_auth_web ^0.3.1+2, firebase_auth >=0.18.2 <=0.18.3 requires firebase_auth_web ^0.3.1+2.        
And because firebase_auth >=0.18.1+2 <0.18.2 depends on firebase_auth_web ^0.3.1+1, firebase_auth >=0.18.1+2 <=0.18.3 requires firebase_auth_web ^0.3.1+1.
And because firebase_auth >=0.18.1 <=0.18.1+1 depends on firebase_auth_web ^0.3.1 and no versions of firebase_auth match >0.18.0+1 <0.18.1, firebase_auth >0.18.0+1 <=0.18.3 requires firebase_auth_web ^0.3.1.
And because firebase_auth ^0.18.3+1 requires firebase_auth_web ^0.3.2+1 (1), firebase_auth >0.18.0+1 <0.19.0 requires firebase_auth_web ^0.3.1.
And because firebase_auth 0.18.0+1 depends on firebase_auth_web ^0.3.0+1, firebase_auth ^0.18.0+1 requires firebase_auth_web ^0.3.0+1.
And because firebase_auth_web >=0.3.0-dev.1 <0.4.0-1.0.nullsafety.0 depends on intl ^0.16.1 and every version of flutter_localizations from sdk depends on intl 0.17.0-nullsafety.2, firebase_auth ^0.18.0+1 is incompatible with 

flutter_localizations from sdk.
So, because flutter_starter depends on both flutter_localizations any from sdk and firebase_auth ^0.18.0+1, version solving failed.
Running "flutter pub get" in flutter_starter-master...
pub get failed (1; So, because flutter_starter depends on both flutter_localizations any from sdk and firebase_auth ^0.18.0+1, version solving failed.)

remove google-services.json in android file

Hi guys! I've read your article on medium about auth with Firebase.
I do not recommend adding google services configs files to PUBLIC repo :D because is very crucial data and with this, some person can use it:
https://github.com/delay/flutter_starter/blob/master/android/app/google-services.json (the same situation for iOS)
Have a nice day!

Phone auth using Getx

have you considered adding a phone authentication feature as another option for signing in. Because I think It's related to the project. I think it would be a great add!

Issue with snackBarTheme

Hi,
Changing the snackBarTheme in the themes as no effect... for example it is impossible for me to change color from text or background.
Seems you got the same issue since you have hard coded SnackBar color in your controller code.
Do you know why it doesn't work ?
Thanks

Sample List & Details Pages

Hello, wondering if you can provide a sample that includes a real world scenario to see how you structure and list things.

One example would be a list of restaurants. When you click on the name of the restaurant you get a details page with: Name, Address, Phone Number, Photos, Lat/Lon, Rating etc.

Just curious how you would do things with your starter and feel it would help people learn by example.

Thanks

When signed in it shows the data of previous user which was signed in before

import 'package:flutter/services.dart';
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:get/get.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:simple_gravatar/simple_gravatar.dart';
import 'package:flutter_starter/localizations.dart';
import 'package:flutter_starter/models/models.dart';
import 'package:flutter_starter/ui/auth/auth.dart';
import 'package:flutter_starter/ui/ui.dart';
import 'package:flutter_starter/ui/components/components.dart';

class AuthController extends GetxController {
  static AuthController to = Get.find();
  AppLocalizations_Labels labels;
  TextEditingController nameController = TextEditingController();
  TextEditingController emailController = TextEditingController();
  TextEditingController passwordController = TextEditingController();
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final FirebaseFirestore _db = FirebaseFirestore.instance;
  Rx<User> firebaseUser = Rx<User>();
  Rx<UserModel> firestoreUser = Rx<UserModel>();
  final RxBool admin = false.obs;
  final RxBool teacher =false.obs;
  @override
  void onReady() async {
    //run every time auth state changes
    ever(firebaseUser, handleAuthChanged);
    firebaseUser.value = await getUser;
    firebaseUser.bindStream(user);
    super.onInit();
  }

  @override
  void onClose() {
    nameController?.dispose();
    emailController?.dispose();
    passwordController?.dispose();
    super.onClose();
  }

  handleAuthChanged(_firebaseUser) async {
    //get user data from firestore
    if (_firebaseUser?.uid != null) {
      firestoreUser.bindStream(streamFirestoreUser());
      await isAdmin();
    }

    if (_firebaseUser == null) {
      Get.offAll(SignInUI());
    } else {
      Get.offAll(HomeUI());
    }
  }

  // Firebase user one-time fetch
  Future<User> get getUser async => _auth.currentUser;

  // Firebase user a realtime stream
  Stream<User> get user => _auth.authStateChanges();

  //Streams the firestore user from the firestore collection
  Stream<UserModel> streamFirestoreUser() {
    print('streamFirestoreUser()');
    if (firebaseUser?.value?.uid != null) {
      isAdmin();
      if(admin.value){

        return _db
            .doc('/admin/${firebaseUser.value.uid}')
            .snapshots()
            .map((snapshot) => UserModel.fromMap(snapshot.data()));
      }
      return _db
          .doc('/users/${firebaseUser.value.uid}')
          .snapshots()
          .map((snapshot) => UserModel.fromMap(snapshot.data()));
    }

    return null;
  }

  //get the firestore user from the firestore collection
  Future<UserModel> getFirestoreUser() {

    if (firebaseUser?.value?.uid != null) {
      isAdmin();
      if(admin.value){

        return _db.doc('admin/${firebaseUser.value.uid}').get().then(
            (documentSnapshot) =>UserModel.fromMap(documentSnapshot.data())
        );
      }
      else{
      return _db.doc('/users/${firebaseUser.value.uid}').get().then(
          (documentSnapshot) => UserModel.fromMap(documentSnapshot.data()));
      }
    }
    return null;
  }

  //Method to handle user sign in using email and password
  signInWithEmailAndPassword(BuildContext context) async {
    final labels = AppLocalizations.of(context);
    showLoadingIndicator();
    try {
      await _auth.signInWithEmailAndPassword(
          email: emailController.text.trim(),
          password: passwordController.text.trim());
      emailController.clear();
      passwordController.clear();
      hideLoadingIndicator();
    } catch (error) {
      hideLoadingIndicator();
      Get.snackbar(labels.auth.signInErrorTitle, labels.auth.signInError,
          snackPosition: SnackPosition.BOTTOM,
          duration: Duration(seconds: 7),
          backgroundColor: Get.theme.snackBarTheme.backgroundColor,
          colorText: Get.theme.snackBarTheme.actionTextColor);
    }
  }

  // User registration using email and password
  registerWithEmailAndPassword(BuildContext context) async {
    final labels = AppLocalizations.of(context);
    showLoadingIndicator();
    try {
      await _auth
          .createUserWithEmailAndPassword(
              email: emailController.text, password: passwordController.text)
          .then((result) async {
        print('uID: ' + result.user.uid);
        print('email: ' + result.user.email);
        //get photo url from gravatar if user has one
        Gravatar gravatar = Gravatar(emailController.text);
        String gravatarUrl = gravatar.imageUrl(
          size: 200,
          defaultImage: GravatarImage.retro,
          rating: GravatarRating.pg,
          fileExtension: true,
        );
        //create the new user object
        UserModel _newUser = UserModel(
            uid: result.user.uid,
            email: result.user.email,
            name: nameController.text,
            photoUrl: gravatarUrl);
        //create the user in firestore
        _createUserFirestore(_newUser, result.user);
        emailController.clear();
        passwordController.clear();
        hideLoadingIndicator();
      });
    } catch (error) {
      hideLoadingIndicator();
      Get.snackbar(labels.auth.signUpErrorTitle, error.message,
          snackPosition: SnackPosition.BOTTOM,
          duration: Duration(seconds: 10),
          backgroundColor: Get.theme.snackBarTheme.backgroundColor,
          colorText: Get.theme.snackBarTheme.actionTextColor);
    }
  }

  //handles updating the user when updating profile
  Future<void> updateUser(BuildContext context, UserModel user, String oldEmail,
      String password) async {
    final labels = AppLocalizations.of(context);
    try {
      showLoadingIndicator();
      await _auth
          .signInWithEmailAndPassword(email: oldEmail, password: password)
          .then((_firebaseUser) {
        _firebaseUser.user
            .updateEmail(user.email)
            .then((value) => _updateUserFirestore(user, _firebaseUser.user));
      });
      hideLoadingIndicator();
      Get.snackbar(labels.auth.updateUserSuccessNoticeTitle,
          labels.auth.updateUserSuccessNotice,
          snackPosition: SnackPosition.BOTTOM,
          duration: Duration(seconds: 5),
          backgroundColor: Get.theme.snackBarTheme.backgroundColor,
          colorText: Get.theme.snackBarTheme.actionTextColor);
    } on PlatformException catch (error) {
      //List<String> errors = error.toString().split(',');
      // print("Error: " + errors[1]);
      hideLoadingIndicator();
      print(error.code);
      String authError;
      switch (error.code) {
        case 'ERROR_WRONG_PASSWORD':
          authError = labels.auth.wrongPasswordNotice;
          break;
        default:
          authError = labels.auth.unknownError;
          break;
      }
      Get.snackbar(labels.auth.wrongPasswordNoticeTitle, authError,
          snackPosition: SnackPosition.BOTTOM,
          duration: Duration(seconds: 10),
          backgroundColor: Get.theme.snackBarTheme.backgroundColor,
          colorText: Get.theme.snackBarTheme.actionTextColor);
    }
  }

  //updates the firestore user in users collection
  void _updateUserFirestore(UserModel user, User _firebaseUser) {
    _db.doc('/users/${_firebaseUser.uid}').update(user.toJson());
    update();
  }

  //create the firestore user in users collection
  void _createUserFirestore(UserModel user, User _firebaseUser) {
    _db.doc('/users/${_firebaseUser.uid}').set(user.toJson());
    update();
  }

  //password reset email
  Future<void> sendPasswordResetEmail(BuildContext context) async {
    final labels = AppLocalizations.of(context);
    showLoadingIndicator();
    try {
      await _auth.sendPasswordResetEmail(email: emailController.text);
      hideLoadingIndicator();
      Get.snackbar(
          labels.auth.resetPasswordNoticeTitle, labels.auth.resetPasswordNotice,
          snackPosition: SnackPosition.BOTTOM,
          duration: Duration(seconds: 5),
          backgroundColor: Get.theme.snackBarTheme.backgroundColor,
          colorText: Get.theme.snackBarTheme.actionTextColor);
    } catch (error) {
      hideLoadingIndicator();
      Get.snackbar(labels.auth.resetPasswordFailed, error.message,
          snackPosition: SnackPosition.BOTTOM,
          duration: Duration(seconds: 10),
          backgroundColor: Get.theme.snackBarTheme.backgroundColor,
          colorText: Get.theme.snackBarTheme.actionTextColor);
    }
  }

  //check if user is an admin user
  isAdmin() async {
    await getUser.then((user) async {
      DocumentSnapshot adminRef =
          await _db.collection('admin').doc(user?.uid).get();
      if (adminRef.exists) {
        admin.value = true;
      } else {
        admin.value = false;
      }
      update();
    });
  }

  isTeacher() async{
    await getUser.then((user) async{
      DocumentSnapshot teachRef =
          await _db.collection('teacher').doc(user?.uid).get();
      if(teachRef.exists){
        teacher.value=true;
      }
      else{
        teacher.value=false;
      }
      update();
    });
  }

  // Sign out
  Future<void> signOut() {
    nameController.clear();
    emailController.clear();
    passwordController.clear();
    _auth.signOut();
    update();
  }
}

This is the AuthController file

import 'package:flutter/material.dart';
import 'package:flutter_starter/localizations.dart';
import 'package:flutter_starter/controllers/controllers.dart';
import 'package:flutter_starter/ui/components/components.dart';
import 'package:flutter_starter/ui/ui.dart';
import 'package:get/get.dart';

class HomeUI extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final labels = AppLocalizations.of(context);

    return GetBuilder<AuthController>(
      init: AuthController(),
      builder: (controller) => controller?.firestoreUser?.value?.uid == null
          ? Center(
              child: CircularProgressIndicator(),
            )
          : Scaffold(
              appBar: AppBar(
                title: Text(labels?.home?.title),
                actions: [
                  IconButton(
                      icon: Icon(Icons.settings),
                      onPressed: () {
                        Get.to(SettingsUI());
                      }),
                ],
              ),
              body: Center(
                child: Column(
                  children: <Widget>[
                    SizedBox(height: 120),
                    Avatar(controller.firestoreUser.value),
                    Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        FormVerticalSpace(),
                        Text(
                            labels.home.uidLabel +
                                ': ' +
                                controller.firestoreUser.value.uid,
                            style: TextStyle(fontSize: 16)),
                        FormVerticalSpace(),
                        Text(
                            labels.home.nameLabel +
                                ': ' +
                                controller.firestoreUser.value.name,
                            style: TextStyle(fontSize: 16)),
                        FormVerticalSpace(),
                        Text(
                            labels.home.emailLabel +
                                ': ' +
                                controller.firestoreUser.value.email,
                            style: TextStyle(fontSize: 16)),
                        FormVerticalSpace(),
                        Text(
                            labels.home.adminUserLabel +
                                ': ' +
                                controller.admin.value.toString(),
                            style: TextStyle(fontSize: 16)),
                      ],
                    ),
                  ],
                ),
              ),
            ),
    );
  }
}

This is the home ui file

Some deprecate warnings are produced during build

While building following warnings are generated.

Note: C:\git\flutter\.pub-cache\hosted\pub.dartlang.org\firebase_core-1.3.0\android\src\main\java\io\flutter\plugins\firebase\core\FlutterFirebaseCorePlugin.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: C:\git\flutter\.pub-cache\hosted\pub.dartlang.org\firebase_auth-1.4.1\android\src\main\java\io\flutter\plugins\firebase\auth\FlutterFirebaseAuthPlugin.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: C:\git\flutter\.pub-cache\hosted\pub.dartlang.org\cloud_firestore-2.2.2\android\src\main\java\io\flutter\plugins\firebase\firestore\FlutterFirebaseFirestorePlugin.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: C:\git\flutter\.pub-cache\hosted\pub.dartlang.org\cloud_firestore-2.2.2\android\src\main\java\io\flutter\plugins\firebase\firestore\streamhandler\TransactionStreamHandler.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

Breaking changes with latest Firebase Auth update

Hey Jeff,
Thanks for sharing your work and all was working well until Tuesday!
There are breaking changes with the newest version of Firebase Auth released a few days ago. I've managed to solve the other problems and just this one remains.

in the auth_controller.dart file you declare
final FirebaseAuth _auth = FirebaseAuth.instance;
and the getter
Future<User> get getUser => _auth.currentUser(); <===== this changed from <FirebaseUser> to just <User>
and
Stream<User> get user => _auth.authStateChanges(); <===== this changed from _auth.onAuthStateChanged()

the currentUser method has changed and this now fails due to 'the expression doesn't evaluate to a function, so it can't be invoked.'

BREAKING: Accessing the current user via currentUser() is now synchronous via the currentUser getter is the problem

I've updated the main.dart file to look like this:
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
Get.put(AuthController());
Get.put(ThemeController());
Get.put(LanguageController());
await Firebase.initializeApp(); <===== added to ensure that Firebase is initialized prior to runApp
await GetStorage.init();
runApp(MyApp());
}

Any thoughts on how to fix this synchronous issue ?
Thanks C

Updating to Flutter 1.22.3 causes looping calls to handleAuthChanged

Thanks for creating the starter project, it was working brilliantly for me and far more elegant than I could of hoped to build myself. I have found an issue however since upgrading to flutter version 1.22.3 where the ever() method in the onReady function is repeadly called on a loop, the behaviour causes the get.offAll(HomeUI()) to be constantly hit maxing out the CPU and the app becomes unresponsive.
Pubspec.yaml:
`
name: trofng_core
description: Next Generation Project.

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
sdk: ">=2.7.0 <3.0.0"

dependencies:
get: ^3.17.1
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
cupertino_icons: ^1.0.0
json_annotation: ^3.1.0
firebase_core: '^0.5.0'
firebase_analytics: '^6.0.0'
firebase_auth: '^0.18.0+1'
cloud_firestore: '^0.14.0+2'
get_storage: ^1.3.2
uuid: ^2.2.2
simple_gravatar: ^1.0.5
flutter_sheet_localization: ^1.0.0

dev_dependencies:
flutter_test:
sdk: flutter
json_serializable: ^3.5.0
build_runner: ^1.0.0

flutter_sheet_localization_generator: ^1.0.0

flutter:
uses-material-design: true

assets:
- assets/images/default.png
- assets/images/defaultDark.png
Flutter Doctor:
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.3, on Mac OS X 10.15.7 19H2, locale en-GB)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 12.2)
[!] Android Studio (version 4.1)
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] VS Code (version 1.51.1)
[✓] Connected device (2 available)`

The code in my auth_controller:
`

class AuthController extends GetxController {
static AuthController to = Get.find();
TextEditingController nameController = TextEditingController();
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _db = FirebaseFirestore.instance;
Rx firebaseUser = Rx();
Rx firestoreUser = Rx();
final RxBool admin = false.obs;

@OverRide
void onReady() async {
//run every time auth state changes
ever(firebaseUser, handleAuthChanged);
firebaseUser.value = await getUser;
firebaseUser.bindStream(_auth.authStateChanges());
super.onReady();
}

@OverRide
void onClose() {
nameController?.dispose();
emailController?.dispose();
passwordController?.dispose();
super.onClose();
}

handleAuthChanged(_firebaseUser) async {
//get user data from firestore
if (_firebaseUser?.uid != null) {
firestoreUser.bindStream(streamFirestoreUser());
//await isAdmin();
}

if (_firebaseUser == null) {
  Get.offAll(SignInUI());
} else {
  Get.offAll(HomeUI());
}

}

// Firebase user one-time fetch
Future get getUser async => _auth.currentUser;

// Firebase user a realtime stream
Stream get user => _auth.authStateChanges();

//Streams the firestore user from the firestore collection
Stream streamFirestoreUser() {
if (firebaseUser?.value?.uid != null) {
return _db
.doc('/users/${firebaseUser.value.uid}')
.snapshots()
.map((snapshot) => TrofUser.fromJson(snapshot.data()));
}
return null;
}

//get the firestore user from the firestore collection
Future getFirestoreUser() {
if (firebaseUser?.value?.uid != null) {
return _db.doc('/users/${firebaseUser.value.uid}').get().then(
(documentSnapshot) => TrofUser.fromJson(documentSnapshot.data()));
}
return null;
}

//Method to handle user sign in using email and password
signInWithEmailAndPassword(BuildContext context) async {
showLoadingIndicator();
try {
await _auth.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text.trim());
emailController.clear();
passwordController.clear();
hideLoadingIndicator();
} catch (error) {
hideLoadingIndicator();
Get.snackbar('Sign in Error', 'Error in Sign on',
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 7),
backgroundColor: Get.theme.snackBarTheme.backgroundColor,
colorText: Get.theme.snackBarTheme.actionTextColor);
}
}

// User registration using email and password
registerWithEmailAndPassword(BuildContext context) async {
showLoadingIndicator();
try {
await _auth
.createUserWithEmailAndPassword(
email: emailController.text, password: passwordController.text)
.then((result) async {
print('uID: ' + result.user.uid);
print('email: ' + result.user.email);
//get photo url from gravatar if user has one
Gravatar gravatar = Gravatar(emailController.text);
String gravatarUrl = gravatar.imageUrl(
size: 200,
defaultImage: GravatarImage.retro,
rating: GravatarRating.pg,
fileExtension: true,
);
//create the new user object
TrofUser _newUser = TrofUser(
uid: result.user.uid,
userEmail: result.user.email,
firstName: nameController.text,
photoUrl: gravatarUrl);
//create the user in firestore
_createUserFirestore(_newUser, result.user);
emailController.clear();
passwordController.clear();
hideLoadingIndicator();
});
} catch (error) {
hideLoadingIndicator();
Get.snackbar('Sign Up Error', error.message,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 10),
backgroundColor: Get.theme.snackBarTheme.backgroundColor,
colorText: Get.theme.snackBarTheme.actionTextColor);
}
}

//handles updating the user when updating profile
Future updateUser(BuildContext context, TrofUser user, String oldEmail,
String password) async {
try {
showLoadingIndicator();
await _auth
.signInWithEmailAndPassword(email: oldEmail, password: password)
.then((_firebaseUser) {
_firebaseUser.user
.updateEmail(user.userEmail)
.then((value) => _updateUserFirestore(user, _firebaseUser.user));
});
hideLoadingIndicator();
Get.snackbar(
'Update Profile Success', 'Profile update has been successful',
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 5),
backgroundColor: Get.theme.snackBarTheme.backgroundColor,
colorText: Get.theme.snackBarTheme.actionTextColor);
} on PlatformException catch (error) {
//List errors = error.toString().split(',');
// print("Error: " + errors[1]);
hideLoadingIndicator();
print(error.code);
String authError;
switch (error.code) {
case 'ERROR_WRONG_PASSWORD':
authError = 'Wrong Password';
break;
default:
authError = 'Auth Error';
break;
}
Get.snackbar('Wrong Password', authError,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 10),
backgroundColor: Get.theme.snackBarTheme.backgroundColor,
colorText: Get.theme.snackBarTheme.actionTextColor);
}
}

//updates the firestore user in users collection
void _updateUserFirestore(TrofUser user, User _firebaseUser) {
_db.doc('/users/${_firebaseUser.uid}').update(user.toJson());
update();
}

//create the firestore user in users collection
void _createUserFirestore(TrofUser user, User _firebaseUser) {
_db.doc('/users/${_firebaseUser.uid}').set(user.toJson());
update();
}

//password reset email
Future sendPasswordResetEmail(BuildContext context) async {
showLoadingIndicator();
try {
await _auth.sendPasswordResetEmail(email: emailController.text);
hideLoadingIndicator();
Get.snackbar('Password Reset Sent', 'Check your email for the reset link',
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 5),
backgroundColor: Get.theme.snackBarTheme.backgroundColor,
colorText: Get.theme.snackBarTheme.actionTextColor);
} catch (error) {
hideLoadingIndicator();
Get.snackbar('Reset Password Error', error.message,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 10),
backgroundColor: Get.theme.snackBarTheme.backgroundColor,
colorText: Get.theme.snackBarTheme.actionTextColor);
}
}

//check if user is an admin user
isAdmin() async {
await getUser.then((user) async {
DocumentSnapshot adminRef =
await _db.collection('admin').doc(user?.uid).get();
if (adminRef.exists) {
admin.value = true;
} else {
admin.value = false;
}
update();
});
}

// Sign out
Future signOut() {
nameController.clear();
emailController.clear();
passwordController.clear();
return _auth.signOut();
}
}
`

Minimal version for Firebase Auth

Hey! First of all, this is a great project and I love some of the features you have put together, but I wanted to ask for a minimal starter project that includes GetX and Firebase authentication. I think that is something that many people need right now, but having all the other features is not always the best for everyone. I am personally going to take this starter project and try to extract many things that I'm not using or that I like to make in some other way myself, and leave the Firebase Auth workflow pretty much intact.

I understand this is your personal preference, so feel free to ignore this request :)

Cheers!

Update Profile Password Dialog

Hi Jeff,

When you enter a wrong or empty password when trying to update profile info, the progress indicator keeps showing up and you no longer can press anything. I have to kill and rerun the code to work again.

update_localizations.dart File

I'm carious about how update_localizations.dart file works. is the localization.g.dart file auto-generated? If so, how is it generated since build_runner package isn't used in this project. Because I want to use my own google translate sheet. Do I just manually write the localizations.g.dart file?

update_localizations.dart: https://github.com/delay/flutter_starter/blob/master/lib/helpers/update_localizations.dart
localization.g.dart: https://github.com/delay/flutter_starter/blob/master/lib/helpers/localization.g.dart

Not able to update localizations

Hi, I am trying to run dart update_localizations.dart, but I keep getting this error you see below.

update_localizations.dart: Warning: Interpreting this as package URI, 'package:rotary_game_app/helpers/update_localizations.dart'.
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:35:52: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
Future<Response> head(Uri url, {Map<String, String>? headers}) =>
                                                   ^
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:45:51: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
Future<Response> get(Uri url, {Map<String, String>? headers}) =>
                                                  ^
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:67:29: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
        {Map<String, String>? headers, Object? body, Encoding? encoding}) =>
                            ^
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:67:46: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
        {Map<String, String>? headers, Object? body, Encoding? encoding}) =>
                                             ^
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:67:62: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
        {Map<String, String>? headers, Object? body, Encoding? encoding}) =>
                                                             ^
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:90:29: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
        {Map<String, String>? headers, Object? body, Encoding? encoding}) =>
                            ^
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:90:46: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
        {Map<String, String>? headers, Object? body, Encoding? encoding}) =>
                                             ^
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:90:62: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
        {Map<String, String>? headers, Object? body, Encoding? encoding}) =>
                                                             ^
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:114:29: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
        {Map<String, String>? headers, Object? body, Encoding? encoding}) =>
                            ^
../../../../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.3/lib/http.dart:114:46: Error: This requires the 'non-nullable' experiment to be enabled.
Try enabling this experiment by adding it to the command line when compiling and running.
        {Map<String, String>? headers, Object? body, Encoding? encoding}) =>

Any idea on why? The lib version is the same as the default.
dart --version : Dart VM version: 2.7.0 (Fri Dec 6 16:26:51 2019 +0100) on "macos_x64"

PS: Thank you for the repo!

Home page not showing latest name

Steps to reproduce:

  1. Create a new account
  2. (or login to an existing account)
  3. Go to setting
  4. Go to update your profile
  5. Change name
  6. UPDATE PROFILE + input password
  7. Go to homepage
  8. Updated name is showing correctly
  9. Go to setting (without signing out)
  10. Go to update your profile
  11. Change name
  12. UPDATE PROFILE + input password
  13. Go to homepage
  14. Name is not updated <- bug
  15. Go to setting (without signing out)
  16. Go to update your profile
  17. Change name
  18. UPDATE PROFILE + input password
  19. Go to homepage
  20. Previous name change is showing <- bug

ever(firebaseUser, handleAuthChanged) fires non-stop

Authentication was working perfectly fine until I decided to update Android Studio, Flutter, and dependencies.

All of a sudden, the ever(firebaseUser, handleAuthChanged) in auth_controller now fires non-stop when a user logs in. Eventually Firebase will not allow any additional queries due to hitting the quota limit and the app crashes.
I tried rolling back the dependencies to when this was working, but it didn't help, which leads me to believe it's something that has changed in Flutter or Dart.

[✓] Flutter (Channel master, 1.24.0-8.0.pre.236, on Mac OS X 10.15.7 19H2
darwin-x64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 12.2)
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.50.1)
[✓] Connected device (1 available)

firebase_auth: 0.18.3
firebase_core: 0.5.2

Would you by chance have any idea why this is happening? I can't seem to figure it out. Thanks!

firebase setup

Hi thanks for sharing great work!

I set up email authentication and firebase so all the functions are working great.
But still I get "[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation." this error while it is running.

What other permission do I need to give in firebase?

Splash UI

Hi, could you please explain to me how you connected the Splash UI defined as initial route ('/') in GetMaterialApp?
I do not understand how you get to login page if you have not defined a "home" parameter in GetMaterialApp.

Cheers,
Andrea

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.