Different content for different user Flutter - firebase

I've been building an app where users can make a reservation for cat grooming. I already connected the app to Firebase where users can register and log in to the app. Here is the problem, every time I log in with different user account, the reservation history from the other users still there.
How can I make different content for different users that login? so each user can have their own content.
Here is the code from history page.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class HistoryPage extends StatefulWidget {
static const String id = 'HistoryPage';
#override
_HistoryPageState createState() => _HistoryPageState();
}
class _HistoryPageState extends State<HistoryPage> {
final _firestore = Firestore.instance;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(25.0, 68.0, 70.0, 25.0),
child: Text(
'History',
style: TextStyle(fontSize: 35.0),
),
),
Column(
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('ReservationData').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
final messages = snapshot.data.documents;
List<HistoryBox> historyWidgets = [];
for (var message in messages) {
final historyDate = message.data['Reservation Date'];
final historyTime = message.data['Reservation Time'];
final historyWidget =
HistoryBox(date: historyDate, time: historyTime);
historyWidgets.add(historyWidget);
}
return Column(
children: historyWidgets,
);
},
),
],
)
],
)),
);
}
}
class HistoryBox extends StatelessWidget {
final String date;
final String time;
HistoryBox({this.date, this.time});
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Material(
elevation: 5.0,
child: Container(
child: Text(
'Date Reservation : \n $date and $time',
style: TextStyle(
fontSize: 20.0,
),
),
),
),
);
}
}
(Updated)
This is the code for users to sign up.
import 'package:flutter/material.dart';
import 'package:project_pi/screens/HomePage/home_page.dart';
import 'inputform_signup.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class SignUpPage extends StatefulWidget {
static const String id = 'SignUpPage';
#override
_SignUpPageState createState() => _SignUpPageState();
}
class _SignUpPageState extends State<SignUpPage> {
final _firestore = Firestore.instance;
final _auth = FirebaseAuth.instance;
bool showSpinner = false;
String nama;
String email;
String password;
String phoneNumber;
#override
Widget build(BuildContext context) {
return Scaffold(
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: Form(
child: SafeArea(
child: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'SIGN UP',
style: TextStyle(
fontSize: 28.0,
),
),
InputForm(
hint: 'Full Name',
hidetext: false,
onChanged: (value) {
nama = value;
},
),
InputForm(
hint: 'Email Address',
hidetext: false,
onChanged: (value) {
email = value;
},
),
InputForm(
hint: 'Phone Number',
hidetext: false,
onChanged: (value) {
phoneNumber = value;
},
),
InputForm(
hint: 'Password',
hidetext: true,
onChanged: (value) {
password = value;
},
),
InputForm(
hint: 'Confirm Password',
hidetext: true,
),
SizedBox(height: 15.0),
Container(
height: 45.0,
width: 270.0,
child: RaisedButton(
child: Text('SIGN UP'),
onPressed: () async {
setState(() {
showSpinner = true;
});
try {
final newUser =
await _auth.createUserWithEmailAndPassword(
email: email, password: password);
_firestore.collection('UserAccount').add({
'Email Address': email,
'Full Name': nama,
'Phone Number': phoneNumber,
});
if (newUser != null) {
Navigator.pushNamed(context, HomePage.id);
}
setState(() {
showSpinner = false;
});
} catch (e) {
print(e);
}
},
),
),
SizedBox(
height: 15.0,
),
Text('Have an Account?'),
SizedBox(
height: 7.5,
),
InkWell(
child: Text(
'SIGN IN',
style: TextStyle(
color: Colors.red,
),
),
onTap: () {
AlertDialog(
title: Text("Finish?"),
content: Text("Are you sure with the data?"),
actions: <Widget>[
FlatButton(onPressed: null, child: null)
],
);
},
),
],
),
),
),
),
),
),
);
}
}
And this is the class for the current user that logged in
import 'package:flutter/material.dart';
import 'package:project_pi/screens/HomePage/homebutton.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:project_pi/screens/LiveMaps/live_maps.dart';
import 'package:project_pi/screens/LoginPage/HalamanLogin.dart';
import 'package:project_pi/screens/ReservationHistory/history_page.dart';
import 'package:project_pi/screens/ReservationPage/information_detail.dart';
class HomePage extends StatefulWidget {
static const String id = "HomePage";
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _auth = FirebaseAuth.instance;
FirebaseUser loggedInUser;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() async {
try {
final user = await _auth.currentUser();
if (user != null) {
loggedInUser = user;
}
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Expanded(
child: Container(
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(25.0, 68.0, 256.0, 47.0),
child: Text(
'Home',
style: TextStyle(fontSize: 35.0),
),
),
Center(
child: Column(
children: <Widget>[
HomeNavButton(
prefixIcon: Icons.date_range,
textbutton: 'Make Reservation',
onPressed: () {
Navigator.pushNamed(context, InformationDetail.id);
},
),
SizedBox(
height: 40.0,
),
HomeNavButton(
prefixIcon: Icons.list,
textbutton: 'Reservation History',
onPressed: () {
Navigator.pushNamed(context, HistoryPage.id);
},
),
SizedBox(
height: 40.0,
),
HomeNavButton(
prefixIcon: Icons.gps_fixed,
textbutton: 'Live Maps Track',
onPressed: () {
Navigator.pushNamed(context, LiveMaps.id);
},
),
SizedBox(
height: 40.0,
),
HomeNavButton(
prefixIcon: Icons.person,
textbutton: 'Account Profile',
onPressed: () {
FirebaseAuth.instance.signOut();
Navigator.pushNamed(context, HalamanLogin.id);
},
),
],
),
),
],
),
),
),
),
);
}
}
how to implement the filter for each current user that logged in so it can show the content based on users?

when user creates an account via firebase they get assigned a uid userId which can be obtained by
String userId;
getCurrentUser() async {
FirebaseUser firebaseUser = await FirebaseAuth.instance.currentUser();
setState(() {
userId = firebaseUser.uid;
});
}
and then while saving reservations you can include a field "userId":userid
now when you query you can query for your currentUser
_firestore.collection('ReservationData') .where("userId", isEqualTo: userId).snapshots(),

Related

firebase firestore chat timestamp order not working corectly

below is my code, i have a chat made in flutter and it should be sorted by timestamp however it is still seemingly random, on firebase it is recording the correct time stamp in json and i thought i had it coded correctly with the firestore.collection order by call. image attached shows the messages they should be ordered 1-6
import 'package:flutter/material.dart';
import 'package:bardsf/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
late String messageText;
class BodyBuildingChat extends StatefulWidget {
static const String id = 'body_building_chat';
#override
_BodyBuildingChatState createState() => _BodyBuildingChatState();
}
class _BodyBuildingChatState extends State<BodyBuildingChat> {
final messageTextController = TextEditingController();
final _firestore = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance;
late User loggedInUser;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() async {
try {
final user = await _auth.currentUser;
if (user != null) {
loggedInUser = user;
print(loggedInUser.email);
}
} catch (e) {
print (e);
}
}
// void getMessages() async{
// final messages = await _firestore.collection('messages').get();
// for (var message in messages.docs) {
// print(message.data().cast());
// }
// }
void messagesStream() async {
await for( var snapshot in _firestore.collection('bodybuilding').orderBy('timestamp').snapshots()) {
for (var message in snapshot.docs) {
print(message.data().cast());
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
messagesStream();
_auth.signOut();
Navigator.pop(context);
}),
],
title: Text('🏔Body Building'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('bodybuilding').snapshots(),
builder: (context, snapshot){
List<MessageBubble> messageBubbles = [];
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data!.docs.reversed;
for (var message in messages) {
final messageText = message['text'];
final messageSender = message['sender'];
final currentUser = loggedInUser.email;
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
isMe: currentUser == messageSender,
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
children: messageBubbles,
),
);
},
),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
TextButton(
onPressed: () {
messageTextController.clear();
_firestore.collection('bodybuilding').add({
'text': messageText,
'sender': loggedInUser.email,
'timestamp': FieldValue.serverTimestamp(),
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class MessageBubble extends StatelessWidget {
MessageBubble({required this.sender,required this.text,required this.isMe});
final String sender;
final String text;
final bool isMe;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(sender,
style: TextStyle(
fontSize: 12.0,
),
),
Material(
borderRadius: isMe ? BorderRadius.only(topLeft: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
) : BorderRadius.only(topRight: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
),
elevation: 5.0,
color: isMe ? Colors.lightBlueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
child: Text('$text',
style: TextStyle( fontSize: 15.0,
color: isMe ? Colors.white : Colors.black,),
),
),
),
],
),
);
}
}
You did not use the appropriate stream.
Change this line
stream: _firestore.collection('bodybuilding').snapshots(),
into this line
stream: _firestore.collection('bodybuilding').orderBy('timestamp').snapshots(),
You will notice that you used the correct stream in the messagesStream but not in the StremBuilder.
Let me know if this does not help.

how to add CircularProgressIndicator using provider with firebase

i went through google code lab of flutter firebase using provider package every thing working fine as mentioned in codelab i like the way they design Authentication widget passing functions from it, in below code i want to add CircularProgressIndicator on waiting state, i don't understand where do i add condition of isLoading is equals to true then wait otherwise dosomething with functions passed by Authentication widget.
main.dart
import 'package:firebase_core/firebase_core.dart'; // new
import 'package:firebase_auth/firebase_auth.dart'; // new
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart'; // new
import 'src/authentication.dart'; // new
import 'src/widgets.dart';
void main() {
// Modify from here
runApp(
ChangeNotifierProvider(
create: (context) => ApplicationState(),
builder: (context, _) => App(),
),
);
// to here.
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firebase Meetup',
theme: ThemeData(
buttonTheme: Theme.of(context).buttonTheme.copyWith(
highlightColor: Colors.deepPurple,
),
primarySwatch: Colors.deepPurple,
textTheme: GoogleFonts.robotoTextTheme(
Theme.of(context).textTheme,
),
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Firebase Meetup'),
),
body: ListView(
children: <Widget>[
Image.asset('assets/codelab.png'),
SizedBox(height: 8),
IconAndDetail(Icons.calendar_today, 'October 30'),
IconAndDetail(Icons.location_city, 'San Francisco'),
// Add from here
Consumer<ApplicationState>(
builder: (context, appState, _) => Authentication(
email: appState.email,
loginState: appState.loginState,
startLoginFlow: appState.startLoginFlow,
verifyEmail: appState.verifyEmail,
signInWithEmailAndPassword: appState.signInWithEmailAndPassword,
cancelRegistration: appState.cancelRegistration,
registerAccount: appState.registerAccount,
signOut: appState.signOut,
),
),
// to here
Divider(
height: 8,
thickness: 1,
indent: 8,
endIndent: 8,
color: Colors.grey,
),
Header("What we'll be doing"),
Paragraph(
'Join us for a day full of Firebase Workshops and Pizza!',
),
],
),
);
}
}
class ApplicationState extends ChangeNotifier {
ApplicationState() {
init();
}
Future<void> init() async {
await Firebase.initializeApp();
FirebaseAuth.instance.userChanges().listen((user) {
if (user != null) {
_loginState = ApplicationLoginState.loggedIn;
} else {
_loginState = ApplicationLoginState.loggedOut;
}
notifyListeners();
});
}
ApplicationLoginState _loginState = ApplicationLoginState.loggedOut;
ApplicationLoginState get loginState => _loginState;
String? _email;
String? get email => _email;
void startLoginFlow() {
_loginState = ApplicationLoginState.emailAddress;
notifyListeners();
}
void verifyEmail(
String email,
void Function(FirebaseAuthException e) errorCallback,
) async {
try {
var methods = await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
if (methods.contains('password')) {
_loginState = ApplicationLoginState.password;
} else {
_loginState = ApplicationLoginState.register;
}
_email = email;
notifyListeners();
} on FirebaseAuthException catch (e) {
errorCallback(e);
}
}
void signInWithEmailAndPassword(
String email,
String password,
void Function(FirebaseAuthException e) errorCallback,
) async {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: password,
);
} on FirebaseAuthException catch (e) {
errorCallback(e);
}
}
void cancelRegistration() {
_loginState = ApplicationLoginState.emailAddress;
notifyListeners();
}
void registerAccount(String email, String displayName, String password,
void Function(FirebaseAuthException e) errorCallback) async {
try {
var credential = await FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
await credential.user!.updateProfile(displayName: displayName);
} on FirebaseAuthException catch (e) {
errorCallback(e);
}
}
void signOut() {
FirebaseAuth.instance.signOut();
/// here is not notifylistener();
}
}
authentication.dart
import 'package:flutter/material.dart';
import 'widgets.dart';
enum ApplicationLoginState {
loggedOut,
emailAddress,
register,
password,
loggedIn,
}
class Authentication extends StatelessWidget {
const Authentication({
required this.loginState,
required this.email,
required this.startLoginFlow,
required this.verifyEmail,
required this.signInWithEmailAndPassword,
required this.cancelRegistration,
required this.registerAccount,
required this.signOut,
});
final ApplicationLoginState loginState;
final String? email;
final void Function() startLoginFlow;
final void Function(
String email,
void Function(Exception e) error,
) verifyEmail;
final void Function(
String email,
String password,
void Function(Exception e) error,
) signInWithEmailAndPassword;
final void Function() cancelRegistration;
final void Function(
String email,
String displayName,
String password,
void Function(Exception e) error,
) registerAccount;
final void Function() signOut;
#override
Widget build(BuildContext context) {
switch (loginState) {
case ApplicationLoginState.loggedOut:
return Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 24, bottom: 8),
child: StyledButton(
onPressed: () {
startLoginFlow();
},
child: const Text('RSVP'),
),
),
],
);
case ApplicationLoginState.emailAddress:
return EmailForm(
callback: (email) =>
verifyEmail(email, (e) => _showErrorDialog(context, 'Invalid email', e)));
case ApplicationLoginState.password:
return PasswordForm(
email: email!,
login: (email, password) {
print("CONTEXT $context");
signInWithEmailAndPassword(
email, password, (e) => _showErrorDialog(context, 'Failed to sign in', e));
},
);
case ApplicationLoginState.register:
return RegisterForm(
email: email!,
cancel: () {
cancelRegistration();
},
registerAccount: (
email,
displayName,
password,
) {
registerAccount(email, displayName, password,
(e) => _showErrorDialog(context, 'Failed to create account', e));
},
);
case ApplicationLoginState.loggedIn:
return Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 24, bottom: 8),
child: StyledButton(
onPressed: () {
signOut();
},
child: const Text('LOGOUT'),
),
),
],
);
default:
return Row(
children: const [
Text("Internal error, this shouldn't happen..."),
],
);
}
}
void _showErrorDialog(BuildContext context, String title, Exception e) {
print("CONTEXT $context");
showDialog<void>(
context: context,
builder: (context) {
return AlertDialog(
title: Text(
title,
style: const TextStyle(fontSize: 24),
),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(
'${(e as dynamic).message}',
style: const TextStyle(fontSize: 18),
),
],
),
),
actions: <Widget>[
StyledButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text(
'OK',
style: TextStyle(color: Colors.deepPurple),
),
),
],
);
},
);
}
}
class EmailForm extends StatefulWidget {
const EmailForm({required this.callback});
final void Function(String email) callback;
#override
_EmailFormState createState() => _EmailFormState();
}
class _EmailFormState extends State<EmailForm> {
final _formKey = GlobalKey<FormState>(debugLabel: '_EmailFormState');
final _controller = TextEditingController();
#override
Widget build(BuildContext context) {
return Column(
children: [
const Header('Sign in with email'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _controller,
decoration: const InputDecoration(
hintText: 'Enter your email',
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter your email address to continue';
}
return null;
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 30),
child: StyledButton(
onPressed: () async {
if (_formKey.currentState!.validate()) {
widget.callback(_controller.text);
}
},
child: const Text('NEXT'),
),
),
],
),
],
),
),
),
],
);
}
}
class RegisterForm extends StatefulWidget {
const RegisterForm({
required this.registerAccount,
required this.cancel,
required this.email,
});
final String email;
final void Function(String email, String displayName, String password) registerAccount;
final void Function() cancel;
#override
_RegisterFormState createState() => _RegisterFormState();
}
class _RegisterFormState extends State<RegisterForm> {
final _formKey = GlobalKey<FormState>(debugLabel: '_RegisterFormState');
final _emailController = TextEditingController();
final _displayNameController = TextEditingController();
final _passwordController = TextEditingController();
#override
void initState() {
super.initState();
_emailController.text = widget.email;
}
#override
Widget build(BuildContext context) {
return Column(
children: [
const Header('Create account'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _emailController,
decoration: const InputDecoration(
hintText: 'Enter your email',
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter your email address to continue';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _displayNameController,
decoration: const InputDecoration(
hintText: 'First & last name',
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter your account name';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _passwordController,
decoration: const InputDecoration(
hintText: 'Password',
),
obscureText: true,
validator: (value) {
if (value!.isEmpty) {
return 'Enter your password';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: widget.cancel,
child: const Text('CANCEL'),
),
const SizedBox(width: 16),
StyledButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
widget.registerAccount(
_emailController.text,
_displayNameController.text,
_passwordController.text,
);
}
},
child: const Text('SAVE'),
),
const SizedBox(width: 30),
],
),
),
],
),
),
),
],
);
}
}
class PasswordForm extends StatefulWidget {
const PasswordForm({
required this.login,
required this.email,
});
final String email;
final void Function(String email, String password) login;
#override
_PasswordFormState createState() => _PasswordFormState();
}
class _PasswordFormState extends State<PasswordForm> {
final _formKey = GlobalKey<FormState>(debugLabel: '_PasswordFormState');
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
#override
void initState() {
super.initState();
_emailController.text = widget.email;
}
#override
Widget build(BuildContext context) {
return Column(
children: [
const Header('Sign in'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _emailController,
decoration: const InputDecoration(
hintText: 'Enter your email',
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter your email address to continue';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _passwordController,
decoration: const InputDecoration(
hintText: 'Password',
),
obscureText: true,
validator: (value) {
if (value!.isEmpty) {
return 'Enter your password';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const SizedBox(width: 16),
StyledButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
widget.login(
_emailController.text,
_passwordController.text,
);
}
},
child: const Text('SIGN IN'),
),
const SizedBox(width: 30),
],
),
),
],
),
),
),
],
);
}
}
widgets.dart
import 'package:flutter/material.dart';
class Header extends StatelessWidget {
const Header(this.heading);
final String heading;
#override
Widget build(BuildContext context) => Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
heading,
style: const TextStyle(fontSize: 24),
),
);
}
class Paragraph extends StatelessWidget {
const Paragraph(this.content);
final String content;
#override
Widget build(BuildContext context) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: Text(
content,
style: const TextStyle(fontSize: 18),
),
);
}
class IconAndDetail extends StatelessWidget {
const IconAndDetail(this.icon, this.detail);
final IconData icon;
final String detail;
#override
Widget build(BuildContext context) => Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Icon(icon),
const SizedBox(width: 8),
Text(
detail,
style: const TextStyle(fontSize: 18),
)
],
),
);
}
class StyledButton extends StatelessWidget {
const StyledButton({required this.child, required this.onPressed});
final Widget child;
final void Function() onPressed;
#override
Widget build(BuildContext context) => OutlinedButton(
style: OutlinedButton.styleFrom(
side: const BorderSide(color: Colors.deepPurple)),
onPressed: onPressed,
child: child,
);
}
pubspec.yaml (version numbers at time of posting)
cloud_firestore: ^1.0.0 # new
firebase_auth: ^1.0.0 # new
google_fonts: ^2.0.0
provider: ^5.0.0
I answer my question, you could do this by adding bool isLoading variable in ApplicationState class and set its value on conditioned base from any method(signInWithEmailAndPassword) present in ApplicationState and pass isLoading to Authentication widget and check condition in build method e.g if isLoading true then show CircularProgressIndicator check below code for more details:
main.dart
import 'package:firebase_core/firebase_core.dart'; // new
import 'package:firebase_auth/firebase_auth.dart'; // new
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart'; // new
import 'src/authentication.dart'; // new
import 'src/widgets.dart';
void main() {
// Modify from here
runApp(
ChangeNotifierProvider(
create: (context) => ApplicationState(),
builder: (context, _) => App(),
),
);
// to here.
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firebase Meetup',
theme: ThemeData(
buttonTheme: Theme.of(context).buttonTheme.copyWith(
highlightColor: Colors.deepPurple,
),
primarySwatch: Colors.deepPurple,
textTheme: GoogleFonts.robotoTextTheme(
Theme.of(context).textTheme,
),
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Firebase Meetup'),
),
body: ListView(
children: <Widget>[
Image.asset('assets/codelab.png'),
SizedBox(height: 8),
IconAndDetail(Icons.calendar_today, 'October 30'),
IconAndDetail(Icons.location_city, 'San Francisco'),
// Add from here
Consumer<ApplicationState>(
builder: (context, appState, _) => Authentication(
isLoading: appState.isLoading,
email: appState.email,
loginState: appState.loginState,
startLoginFlow: appState.startLoginFlow,
verifyEmail: appState.verifyEmail,
signInWithEmailAndPassword: appState.signInWithEmailAndPassword,
cancelRegistration: appState.cancelRegistration,
registerAccount: appState.registerAccount,
signOut: appState.signOut,
),
),
// to here
Divider(
height: 8,
thickness: 1,
indent: 8,
endIndent: 8,
color: Colors.grey,
),
Header("What we'll be doing"),
Paragraph(
'Join us for a day full of Firebase Workshops and Pizza!',
),
],
),
);
}
}
class ApplicationState extends ChangeNotifier {
ApplicationState() {
init();
}
Future<void> init() async {
await Firebase.initializeApp();
FirebaseAuth.instance.userChanges().listen((user) {
if (user != null) {
_loginState = ApplicationLoginState.loggedIn;
} else {
_loginState = ApplicationLoginState.loggedOut;
}
notifyListeners();
});
}
ApplicationLoginState _loginState = ApplicationLoginState.loggedOut;
ApplicationLoginState get loginState => _loginState;
bool get isLoading => _isLoading;
String? _email;
String? get email => _email;
bool _isLoading = false;
void startLoginFlow() {
_loginState = ApplicationLoginState.emailAddress;
notifyListeners();
}
void verifyEmail(
String email,
void Function(FirebaseAuthException e) errorCallback,
) async {
try {
var methods = await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
if (methods.contains('password')) {
_loginState = ApplicationLoginState.password;
} else {
_loginState = ApplicationLoginState.register;
}
_email = email;
notifyListeners();
} on FirebaseAuthException catch (e) {
errorCallback(e);
}
}
void signInWithEmailAndPassword(
String email,
String password,
void Function(FirebaseAuthException e) errorCallback,
) async {
try {
if (!this.isLoading) {
this._isLoading = true;
notifyListeners();
}
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: password,
);
} on FirebaseAuthException catch (e) {
errorCallback(e);
this._isLoading = false;
notifyListeners();
}
}
void cancelRegistration() {
_loginState = ApplicationLoginState.emailAddress;
notifyListeners();
}
void registerAccount(String email, String displayName, String password,
void Function(FirebaseAuthException e) errorCallback) async {
try {
var credential = await FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
await credential.user!.updateProfile(displayName: displayName);
} on FirebaseAuthException catch (e) {
errorCallback(e);
}
}
void signOut() {
FirebaseAuth.instance.signOut();
/// here is not notifylistener();
}
}
authentication.dart
import 'package:flutter/material.dart';
import 'widgets.dart';
enum ApplicationLoginState {
loggedOut,
emailAddress,
register,
password,
loggedIn,
}
class Authentication extends StatelessWidget {
const Authentication({
required this.isLoading,
required this.loginState,
required this.email,
required this.startLoginFlow,
required this.verifyEmail,
required this.signInWithEmailAndPassword,
required this.cancelRegistration,
required this.registerAccount,
required this.signOut,
});
final bool isLoading;
final ApplicationLoginState loginState;
final String? email;
final void Function() startLoginFlow;
final void Function(
String email,
void Function(Exception e) error,
) verifyEmail;
final void Function(
String email,
String password,
void Function(Exception e) error,
) signInWithEmailAndPassword;
final void Function() cancelRegistration;
final void Function(
String email,
String displayName,
String password,
void Function(Exception e) error,
) registerAccount;
final void Function() signOut;
#override
Widget build(BuildContext context) {
if (this.isLoading) {
return Stack(
children: [Center(child: CircularProgressIndicator(value: null))],
);
}
switch (loginState) {
case ApplicationLoginState.loggedOut:
return Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 24, bottom: 8),
child: StyledButton(
onPressed: () {
startLoginFlow();
},
child: const Text('RSVP'),
),
),
],
);
case ApplicationLoginState.emailAddress:
return EmailForm(
callback: (email) =>
verifyEmail(email, (e) => _showErrorDialog(context, 'Invalid email', e)));
case ApplicationLoginState.password:
return PasswordForm(
email: email!,
login: (email, password) {
print("CONTEXT $context");
signInWithEmailAndPassword(
email, password, (e) => _showErrorDialog(context, 'Failed to sign in', e));
},
);
case ApplicationLoginState.register:
return RegisterForm(
email: email!,
cancel: () {
cancelRegistration();
},
registerAccount: (
email,
displayName,
password,
) {
registerAccount(email, displayName, password,
(e) => _showErrorDialog(context, 'Failed to create account', e));
},
);
case ApplicationLoginState.loggedIn:
return Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 24, bottom: 8),
child: StyledButton(
onPressed: () {
signOut();
},
child: const Text('LOGOUT'),
),
),
],
);
default:
return Row(
children: const [
Text("Internal error, this shouldn't happen..."),
],
);
}
}
void _showErrorDialog(BuildContext context, String title, Exception e) {
print("CONTEXT $context");
showDialog<void>(
context: context,
builder: (context) {
return AlertDialog(
title: Text(
title,
style: const TextStyle(fontSize: 24),
),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(
'${(e as dynamic).message}',
style: const TextStyle(fontSize: 18),
),
],
),
),
actions: <Widget>[
StyledButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text(
'OK',
style: TextStyle(color: Colors.deepPurple),
),
),
],
);
},
);
}
}
class EmailForm extends StatefulWidget {
const EmailForm({required this.callback});
final void Function(String email) callback;
#override
_EmailFormState createState() => _EmailFormState();
}
class _EmailFormState extends State<EmailForm> {
final _formKey = GlobalKey<FormState>(debugLabel: '_EmailFormState');
final _controller = TextEditingController();
#override
Widget build(BuildContext context) {
return Column(
children: [
const Header('Sign in with email'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _controller,
decoration: const InputDecoration(
hintText: 'Enter your email',
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter your email address to continue';
}
return null;
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 30),
child: StyledButton(
onPressed: () async {
if (_formKey.currentState!.validate()) {
widget.callback(_controller.text);
}
},
child: const Text('NEXT'),
),
),
],
),
],
),
),
),
],
);
}
}
class RegisterForm extends StatefulWidget {
const RegisterForm({
required this.registerAccount,
required this.cancel,
required this.email,
});
final String email;
final void Function(String email, String displayName, String password) registerAccount;
final void Function() cancel;
#override
_RegisterFormState createState() => _RegisterFormState();
}
class _RegisterFormState extends State<RegisterForm> {
final _formKey = GlobalKey<FormState>(debugLabel: '_RegisterFormState');
final _emailController = TextEditingController();
final _displayNameController = TextEditingController();
final _passwordController = TextEditingController();
#override
void initState() {
super.initState();
_emailController.text = widget.email;
}
#override
Widget build(BuildContext context) {
return Column(
children: [
const Header('Create account'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _emailController,
decoration: const InputDecoration(
hintText: 'Enter your email',
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter your email address to continue';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _displayNameController,
decoration: const InputDecoration(
hintText: 'First & last name',
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter your account name';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _passwordController,
decoration: const InputDecoration(
hintText: 'Password',
),
obscureText: true,
validator: (value) {
if (value!.isEmpty) {
return 'Enter your password';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: widget.cancel,
child: const Text('CANCEL'),
),
const SizedBox(width: 16),
StyledButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
widget.registerAccount(
_emailController.text,
_displayNameController.text,
_passwordController.text,
);
}
},
child: const Text('SAVE'),
),
const SizedBox(width: 30),
],
),
),
],
),
),
),
],
);
}
}
class PasswordForm extends StatefulWidget {
const PasswordForm({
required this.login,
required this.email,
});
final String email;
final void Function(String email, String password) login;
#override
_PasswordFormState createState() => _PasswordFormState();
}
class _PasswordFormState extends State<PasswordForm> {
final _formKey = GlobalKey<FormState>(debugLabel: '_PasswordFormState');
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
#override
void initState() {
super.initState();
_emailController.text = widget.email;
}
#override
Widget build(BuildContext context) {
return Column(
children: [
const Header('Sign in'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _emailController,
decoration: const InputDecoration(
hintText: 'Enter your email',
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter your email address to continue';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextFormField(
controller: _passwordController,
decoration: const InputDecoration(
hintText: 'Password',
),
obscureText: true,
validator: (value) {
if (value!.isEmpty) {
return 'Enter your password';
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const SizedBox(width: 16),
StyledButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
widget.login(
_emailController.text,
_passwordController.text,
);
}
},
child: const Text('SIGN IN'),
),
const SizedBox(width: 30),
],
),
),
],
),
),
),
],
);
}
}

The getter 'data' was called on null. Receiver: null Tried calling: data

Tried signing up user with Firebase but got the above error instead, and the code is formatted in such a way that it should redirect the user to homepage after a successful signup.
My main.dart
import 'package:bedc_app/home_page.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:bedc_app/auth/login_page.dart';
void main() async{
//solution study
WidgetsFlutterBinding.ensureInitialized();
FirebaseAuth.instance.currentUser()
.then((FirebaseUser user) {
if(user != null){
Firestore.instance.collection('users').document(user.uid).get().then((DocumentSnapshot doc){
runApp(MyApp(true, doc));
});
return;
}
runApp(MyApp(false, null));
});
}
// void main() =>runApp(MyApp());
class MyApp extends StatelessWidget {
bool isLoggedIn;
DocumentSnapshot doc;
MyApp(this.isLoggedIn, this.doc);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Multifunctional bedc project App',
debugShowCheckedModeBanner: false,
home: isLoggedIn ? HomePage(userDoc: doc) : loginPage(),
);
}
}
My Signup_page.dart
import 'package:bedc_app/auth/login_page.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:bedc_app/utils/constants.dart';
import '../home_page.dart';
class SignUpPage extends StatefulWidget {
#override
_SignUpPageState createState() => _SignUpPageState();
}
class _SignUpPageState extends State<SignUpPage> {
String email, password;
bool isLoggedIn = false;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: ListView(
children: [
SizedBox(
height: 50,
),
Align(
alignment: Alignment.topCenter,
child: (
Image.asset(
'assets/bedclogo.jpg'
)),
),
SizedBox(
height: 100,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 26.0),
child: TextField(
decoration: InputDecoration(
hintText: 'email',
border: OutlineInputBorder(),
labelText: 'Email',
suffixIcon: Icon(Icons.email, color: Colors.green)
),
keyboardType: TextInputType.emailAddress,
onChanged: (String val){
email = val;
},
),
),
SizedBox(
height: 10,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 26.0),
child: TextField(
decoration: InputDecoration(
hintText: 'Password',
border: OutlineInputBorder(),
labelText: 'Password',
suffixIcon: Icon(Icons.lock, color: Colors.green)
),
obscureText: true,
obscuringCharacter: '!',
keyboardType: TextInputType.emailAddress,
onChanged: (String val){
password = val;
},
),),
SizedBox(
height: 5,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 26),
child: MaterialButton(
color: Color(0xFF88C540),
child: isLoading ? Container(
height: 24,
width: 24,
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.black),
strokeWidth: 2,
)
):Text(
'SignUp'.toUpperCase(),
style: TextStyle(fontWeight: FontWeight.bold),
),
onPressed: (){
checkUserInput();
},
),
),
SizedBox(
height: 10,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: RichText(
text: TextSpan(
text: 'Already have an Account ?',
style: TextStyle(color: Colors.black),
children: [
TextSpan(
text: 'Login here',
style: TextStyle(color: Colors.blue),
recognizer: TapGestureRecognizer()..onTap = (){
Navigator.of(context).pushReplacement(CupertinoPageRoute(builder: (_) => loginPage()));
},
)
]
)),
)
],
));
}
//SIGNUP FUNCTION USING FIREBASE
bool isLoading = false;
signUpUserWithFirebase(){
FirebaseAuth.instance.createUserWithEmailAndPassword(
email: email,
password: password
).then((AuthResult result){
//Authresult cant be stored to string.....
storeUserDataToFirestore(result.user.uid);
if(result.user.uid != null){
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) => HomePage()));
}
}).catchError((e){
print(e);
isLoading = false;
setState(() { });
});
}
//storeUserDataToFirestore
storeUserDataToFirestore(String userId){
Map<String, dynamic> userData = Map<String, dynamic>();
userData = {
Constants.USERNAME: '#username',
Constants.USER_ID: userId,
Constants.EMAIL : email,
Constants.ACCOUNT_NUM : '00000000',
Constants.IS_ADMIN: false,
Constants.PROFILE_IMAGE: '',
Constants.PROFILE_IMAGE_THUMB: '',
};
CollectionReference usersRef = Firestore.instance.collection(Constants.USERS_COLLECTION);
usersRef.document(userId).setData(userData).then((_){
isLoading = false;
setState(() { });
}).catchError((e){
print(e);
});
}
//FUNCTION TO CHECK USER ENTRY
checkUserInput(){
isLoading = true;
setState(() { });
if(email == null || email.isEmpty){
print('Enter email');
isLoading = false;
setState(() { });
return;
}
if(password == null || email.isEmpty){
print('Enter password');
isLoading = false;
setState(() { });
}
//SIGNUP THE USER
signUpUserWithFirebase();
}
getUserData(String UserId){
Firestore.instance.collection(Constants.USERS_COLLECTION)
.document(UserId)
.get().then((DocumentSnapshot userDoc){
Navigator.of(context).pop();
Navigator.of(context).pushReplacement(CupertinoPageRoute(builder: (_) => HomePage(userDoc: userDoc)));
}).catchError((e){
print(e);
});
}
}
My Home_page.dart
import 'dart:ui';
import 'package:bedc_app/auth/login_page.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:bedc_app/auth/signup_page.dart';
import 'model/user.dart';
User currentUser;
class HomePage extends StatefulWidget {
DocumentSnapshot userDoc;
HomePage({this.userDoc,});
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
//user cant access this page unless logged in
bool userIsLoggedIn = true;
#override
void initState() {
// TODO: implement initState
super.initState();
currentUser = User.fromSnapshot(widget.userDoc);
}
//HERE IS BUILDING PROFILE IMAGE
Widget buildProfileImage(){
if(currentUser.profileImage == ''){
return CircleAvatar(
backgroundColor: Colors.white70,
radius: 20,
child: Icon(Icons.person, size: 30),
);
}else{
return CircleAvatar(
backgroundImage: NetworkImage(currentUser.profileImage),
);
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.brown,
title: Text('Homepage'),
),
body: ListView(
children: [
SizedBox(height: 20),
Align(
alignment: Alignment.topRight,
child: (
Image.asset(
'assets/bedclogo.jpg',
scale: 2,
)),
),
ListTile(
title: Text(currentUser.username, style: TextStyle(color: Colors.brown, fontWeight: FontWeight.bold),),
leading: buildProfileImage(),
),
SizedBox(height: 30),
//CAPTURE METER READING UI
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: GestureDetector(
onTap: (){
//print(currentUser.isAdmin);
},
child: Row(
children: [
//CAPTURE METR READING
Container(
width: 100,
height: 100,
color: Colors.green,
child: Align(
alignment: Alignment.center,
child: (
Image.asset(
'assets/meterIcon.png',
scale: 3,
)),
),
),
Container(
width: 100,
height: 100,
child: Align(
alignment: Alignment.center,
child: Text('Capture Meter Reading'.toUpperCase()),
),
),
],
),
),
),
SizedBox(height: 30),
//UPDATE PROFILE UI DESIGN
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: GestureDetector(
onTap:(){
//print(currentUser.isAdmin);
},
child: Row(
children: [
Container(
width: 100,
height: 100,
color: Colors.green,
child: Align(
alignment: Alignment.center,
child: (
Image.asset(
'assets/profileAvatar.png',
scale: 3,
)),
),
),
Container(
width: 100,
height: 100,
child: Align(
alignment: Alignment.center,
child: Text('Update Profile'.toUpperCase()),
),
),
],
),
),
),
// TextButton (
// onPressed: (){
// //just logout, implement pop dialog later
// // FirebaseAuth.instance.signOut();
// // Navigator.of(context).pushReplacement(CupertinoPageRoute(builder: (_)=> loginPage()));
// // currentUser = null;
// // setState(() {
// // });
// // still showing error... try to fix asap
// FirebaseAuth.instance.signOut().then((_){
// userIsLoggedIn = false;
// Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_)=> loginPage()));
// //currentUser = null;
// setState(() {
//
// });
// });
// },
// child: Text('SignOut'))
],
)
);
}
}
User.dart for user Model
import 'package:bedc_app/utils/constants.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class User{
String username;
String email;
String userId;
String accountNum;
bool isAdmin;
String profileImage;
String profileImageThumb;
User({
this.username,
this.email,
this.userId,
this.accountNum,
this.isAdmin,
this.profileImage,
this.profileImageThumb
});
factory User.fromSnapshot(DocumentSnapshot doc){
return User(
username: doc.data[Constants.USERNAME],
email: doc.data[Constants.EMAIL],
userId: doc.data[Constants.USER_ID],
accountNum: doc.data[Constants.ACCOUNT_NUM],
isAdmin: doc.data[Constants.IS_ADMIN],
profileImage: doc.data[Constants.PROFILE_IMAGE],
profileImageThumb: doc.data[Constants.PROFILE_IMAGE_THUMB]
);
}
}
Having signed the user up, im getting error The getter 'data' was called on null. Receiver: null Tried calling: data.
i dont know which part of the code is causing this exception
This error generally show when you try to get some attribute on null object.
In your case, call one of doc.data[..] in file User.dart generate the error that means doc == null is true.
Verify that widget.userDoc is not null at this line currentUser = User.fromSnapshot(widget.userDoc); on initState method of Home_page.dart file
So error provide in one of HomePage call who require a non null userDoc (todo: make sure your data is not null using assert and add #required before required variable on your class exp: HomePage({#required this.userDoc,}): assert(userDoc != null, "BOooh my userDoc may be not null"); that help very much when you debug your app)
finaly your problem provide in signUpUserWithFirebase() method of your Signup_page.dart file... here Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) => HomePage()));
Try to replace by this getUserData(result.user.uid) so your methode should become
signUpUserWithFirebase(){
FirebaseAuth.instance.createUserWithEmailAndPassword(
email: email,
password: password
).then((AuthResult result){
//Authresult cant be stored to string.....
storeUserDataToFirestore(result.user.uid);
if(result.user.uid != null){
getUserData(result.user.uid); // replaced line
}
}).catchError((e){
print(e);
isLoading = false;
setState(() { });
});
}

How to edit firebase existing document with flutter

I try to build a note taking app in flutter, when i try to edit old note i dont see any change,it takes old value.
Thats my collection
My home Page:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:story_note/pages/ajoutNote.dart';
import 'package:story_note/pages/authController.dart';
import 'package:story_note/pages/detailNote.dart';
import 'package:story_note/pages/modifierNote.dart';
import 'package:story_note/pages/modifyNote.dart';
import 'package:timeago/timeago.dart' as timeago;
class Home extends StatefulWidget{
#override
_HomeState createState()=>_HomeState();
}
class _HomeState extends State<Home>{
FirebaseUser currentUser;
String nomUser,emailUser;
Widget _boiteDuDialog(BuildContext, String nom, String email){
return SimpleDialog(
contentPadding: EdgeInsets.zero,
children:<Widget> [
Padding(padding: EdgeInsets.all(8.0),
child: Column(
children:<Widget> [
Text('$nom',style: Theme.of(context).textTheme.title,),
Text('$email',style: Theme.of(context).textTheme.subtitle1,),
SizedBox(height: 10.0,),
Wrap(
children:<Widget> [
FlatButton(color: Colors.red,onPressed:()async{
FirebaseAuth _auth = FirebaseAuth.instance;
await _auth.signOut();
setState(() {
Navigator.pop(context);
});
}, child:Text('Déconnexion')),
FlatButton(onPressed:(){
Navigator.pop(context);
}, child: Text('Annuler'))
],
)
],
),
),
],
);
}
#override
Widget build(BuildContext context) {
// TODO: implement build
final utilisateur = Provider.of<Utilisateur>(context);
FirebaseAuth.instance.currentUser().then((FirebaseUser user){
setState(() {
this.currentUser=user;
});
});
String _idUser(){
if(currentUser!=null){
return currentUser.uid;
}else{
return 'pas id';
}
}
GetCurrentUserData(idUser: utilisateur.idUser).dataUser.forEach((snapshot){
this.nomUser = snapshot.nomComplet;
this.emailUser = snapshot.email;
});
Widget _buildListItem(DocumentSnapshot document){
Firestore.instance.collection('utilisateurs').document(utilisateur.idUser).collection('notes').snapshots();
Timestamp t = document['timestamp'];
final DateTime d = t.toDate();
final DateTime h = DateTime.now();
final diff = d.difference(h).inMinutes;
final date = new DateTime.now().subtract(new Duration(minutes: diff));
String realdate = timeago.format(date);
return Dismissible (
key: new Key(ObjectKey(document.data.keys).toString()),
onDismissed: (direction)async{
await Firestore.instance.collection('utilisateurs').document(utilisateur.idUser).collection('notes').document().delete();
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('${document['titre']} was deleted',style: new TextStyle(color: Colors.red),),
)
);
},
background: new Container(
color: Colors.red,
),
child:Container(
padding: EdgeInsets.symmetric(horizontal: 10),
height: 80,
alignment: Alignment.center,
child:Card(
elevation: 10.0,
color: Theme.of(context).primaryColor,
shadowColor: Colors.white24,
child:new ListTile(
onTap:(){
print('cest fait');
Navigator.push(context, MaterialPageRoute(builder: (context)=>ModifierNote(
titre:document['titre'],
note:document['note']
)));
},
leading: Icon(Icons.mood_rounded,color: Colors.blue,size: 30,),
title: new Text('${document['titre']}',style: new TextStyle(fontSize: 20,fontWeight: FontWeight.bold),textAlign: TextAlign.justify,),
subtitle: new Text('${document['note']}',maxLines: 1,),
trailing: new Text(realdate),
),
)
)
);
}
return Scaffold(
appBar: AppBar(
title: Text('Story Notes',),
centerTitle: true,
backgroundColor: Theme.of(context).primaryColor,
actions: [
IconButton(icon: Icon(Icons.search_rounded), onPressed:(){
}),
IconButton(icon: Icon(Icons.person), onPressed:()=>showDialog(context: context,builder: (context)=>
_boiteDuDialog(context,nomUser,emailUser))),
],
),
body: Padding(
padding: EdgeInsets.only(top: 25),
child:StreamBuilder(
stream: Firestore.instance.collection('utilisateurs').document(utilisateur.idUser).collection('notes').snapshots(),
builder: (context,snapshot){
if(!snapshot.hasData)
return Text('loading....');
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder:(context,index)=>
_buildListItem(snapshot.data.documents[index]),
);
},
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue,
child: Icon(Icons.note_add,),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=>AjoutNote()));
},
),
);
}
}
my Modification page:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class ModifierNote extends StatefulWidget{
final String titre,note;
ModifierNote({this.titre,this.note});
#override
ModifierNoteState createState()=> ModifierNoteState();
}
class ModifierNoteState extends State<ModifierNote>{
final CollectionReference collectionUser = Firestore.instance.collection('utilisateurs');
FirebaseUser currentUser;
final _formkey = GlobalKey<FormState>();
bool _titreValid = true;
bool _noteValid = true;
#override
Widget build(BuildContext context) {
// TODO: implement build
FirebaseAuth.instance.currentUser().then((FirebaseUser user) {
setState(() {
this.currentUser = user;
});
});
String _idUser(){
if(currentUser!=null){
return currentUser.uid;
}else{
return 'Pas id';
}
}
String titre1 = widget.titre;
String note1 = widget.note;
final DateTime timestamp = DateTime.now();
modifierNotes()async{
await collectionUser.document(_idUser()).collection('notes')
.document('note')
.setData({
'titre': titre1,
'note': note1,
'timestamp':timestamp
});
this.setState(() {
Navigator.pop(context);
});
}
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).primaryColor,
title: Text('Notes'),
actions: [
RaisedButton(
onPressed:()async{
if(_formkey.currentState.validate()){
modifierNotes();
}
},
child:Text('Modifier')
),
],
),
body: Stack(
children: [
SingleChildScrollView(
child:Card(
elevation: 15,
color: Theme.of(context).primaryColor,
child: Form(
key: _formkey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children:<Widget> [
TextFormField(
initialValue: titre1,
decoration: InputDecoration(
labelText: 'Titre',
prefixIcon: Icon(Icons.speaker_notes_sharp),
),
validator: (val) =>
val.isEmpty ? 'Entrez un titre' : null,
onChanged: (val)=>setState(()=>titre1 = val),
),
TextFormField(
initialValue: note1,
keyboardType: TextInputType.multiline,
maxLines: 5000,
autofocus: true,
decoration: InputDecoration(
hintText: 'Comment vous sentez vous ?',
hintStyle: new TextStyle(fontSize: 20),
),
validator: (val) =>
val.isEmpty ? 'Entrez une note' : null,
onChanged: (val)=>setState(()=>note1 = val),
),
],
),
),
),
),
],
),
);
}
}
And Addpage:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class AjoutNote extends StatefulWidget{
AjoutNoteState createState()=> AjoutNoteState();
}
class AjoutNoteState extends State<AjoutNote>{
String titre;
String note;
final _formkey = GlobalKey<FormState>();
final CollectionReference collectionUser = Firestore.instance.collection('utilisateurs');
final DateTime timestamp = DateTime.now();
FirebaseUser currentUser;
#override
Widget build(BuildContext context) {
// TODO: implement build
FirebaseAuth.instance.currentUser().then((FirebaseUser user) {
setState(() {
this.currentUser = user;
});
});
String _idUser(){
if(currentUser!=null){
return currentUser.uid;
}else{
return 'Pas id';
}
}
enegistrezNote()async{
await collectionUser.document(_idUser()).collection('notes')
.document('note')
.setData({
'titre': titre,
'note': note,
'timestamp':timestamp
});
this.setState(() {
Navigator.pop(context);
});
}
return Scaffold(
backgroundColor: Theme.of(context).primaryColor,
appBar: AppBar(
title: Text('Ajouter une note'),
centerTitle: true,
backgroundColor: Theme.of(context).primaryColor,
actions: [
RaisedButton(onPressed:(){
if(_formkey.currentState.validate()){
enegistrezNote();
}
},
child: Text("Enregistrez"),
),
],
),
body: new Container(
child:SingleChildScrollView(
child: Card(
elevation: 15,
color: Theme.of(context).primaryColor,
child: Form(
key: _formkey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children:<Widget> [
TextFormField(
decoration: InputDecoration(
labelText: 'Titre',
prefixIcon: Icon(Icons.speaker_notes_sharp)
),
onChanged: (val)=>titre=val,
),
TextFormField(
keyboardType: TextInputType.multiline,
maxLines: 5000,
autofocus: true,
decoration: InputDecoration(
hintText: 'Comment vous sentez vous ?',
hintStyle: new TextStyle(fontSize: 20),
),
onChanged: (val)=>note=val,
)
],
),
),
),
),
),
resizeToAvoidBottomPadding: true,
);
}
}
When i try to modify i dont see any changes.
use update Method in place of set, I have made changes for you:
modifierNotes()async{
await collectionUser.document(_idUser()).collection('notes')
.document('note')
.update({
'titre': titre1,
'note': note1,
'timestamp':timestamp
});
this.setState(() {
Navigator.pop(context);
});
}

A non-null String must be provided to a Text widget flutter

I have this problem with this code. I tried to solve the problem, but I did not succeed. Please Help
Please see the screenshots to understand the problem well
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 370 pos 10: 'data != null'
Pictures description error
null in firebase
The users email address.Will be null if signing in anonymously.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flash_chat/constants.dart';
class ChatScreen extends StatefulWidget {
static const Id = 'chat_screen';
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
// ignore: deprecated_member_use
final _firestore = Firestore.instance;
final _auth = FirebaseAuth.instance;
// ignore: deprecated_member_use
FirebaseUser loggedInUser;
String messageText;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() async {
try {
// ignore: await_only_futures
final user = await _auth.currentUser;
if (user != null) {
loggedInUser = user;
print(loggedInUser.email);
}
} catch (e) {
print(e);
}
}
// void getMessages() async {
// // ignore: deprecated_member_use
// final messages = await _firestore.collection('Messages').getDocuments();
// // ignore: deprecated_member_use
// for (var message in messages.docs) {
// print(message.data());
// }
// }
void messagesStream() async {
await for (var snapshot in _firestore.collection('Messages').snapshots()) {
for (var message in snapshot.docs) {
print(message.data());
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
messagesStream();
//_auth.signOut();
//Navigator.pop(context);
}),
],
title: Text('⚡️Chat'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('Messages').snapshots(),
// ignore: missing_return
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
));
}
// ignore: deprecated_member_use
final messages = snapshot.data.documents;
List<Messagebubble> messagebubbles = [];
for (var message in messages) {
final messageText = message.data()['text'];
final messagesendar = message.data()['Sender'];
final messagebubble = Messagebubble(
sendar: messagesendar,
text: messageText,
);
messagebubbles.add(messagebubble);
}
return Expanded(
child: ListView(
padding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 20.0,
),
children: messagebubbles,
),
);
},
),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
_firestore.collection('Messages').add({
'text': messageText,
'Sender': loggedInUser,
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class Messagebubble extends StatelessWidget {
Messagebubble({
Key key,
this.sendar,
this.text,
}) : super(key: key);
final String sendar;
final String text;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
children: [
Text(
sendar,
style: TextStyle(
fontSize: 12.0,
color: Colors.black54,
),
),
Material(
borderRadius: BorderRadius.circular(30.0),
elevation: 5.0,
color: Colors.lightBlueAccent,
child: Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 20.0,
),
child: Text(
text,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
),
),
],
),
);
}
}
You just need to check whether the text that you are passing is null or not. If it is null, you can show that the user is Anonymous.
final messageText = message.data()['text'];
final messagesendar = message.data()['Sender'] ?? 'Anonymous'; // If null then use 'Anonymous'
final messagebubble = Messagebubble(
sendar: messagesendar,
text: messageText,
);
Flutter doesn't allow you to pass null to Text widgets.

Resources