delay / flutter_starter Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
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.
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.
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
Is there a plan to support login via google and facebook?
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.
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
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).
Any plans to update to support Null Safety?
Thanks
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.)
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!
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!
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
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
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
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.
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
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();
}
}
`
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!
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.
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
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!
Steps to reproduce:
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!
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?
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.