Closed trof-app closed 3 years ago
This bug should have been fixed a couple of weeks ago. https://github.com/delay/flutter_starter/commit/793b5654f82ae5f2d3f28b441c7011f7210d388f
Basically you need to change super.onInit to super.onReady in auth_controller.dart
void onReady() async {
//run every time auth state changes
ever(firebaseUser, handleAuthChanged);
firebaseUser.value = await getUser;
firebaseUser.bindStream(user);
super.onReady();
}
I am going to close this issue. Let me know if the above fix does not work for you.
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:
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(); }
}
// 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();
}
}
`