How to Send Images in chat - firebase

I'm working on a chat room and I want to enable users send photos in chat. But I don't seem to be getting a hang of it.
I have the image picker widget, but I'm still yet to implement it cos I can't get a hang of it.
Here is the code to the chat screen and a photo as well. I have initialised Firebase properly and everything is working fine, messages are sending, and all. But I want to implement a message send feature into the project.
import 'package:chat/constants.dart';
import 'package:chat/utilities/constants.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:chat/models/auth.dart';
import 'package:chat/models/message.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class ChatScreen extends StatefulWidget {
final AuthImplementation auth;
final VoidCallback signedOut;
ChatScreen({
this.auth,
this.signedOut,
});
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final Firestore _firestore = Firestore.instance;
TextEditingController messageController = TextEditingController();
ScrollController scrollController = ScrollController();
String userName;
#override
void initState() {
super.initState();
widget.auth.getCurrentUserEmail().then((email) {
setState(() {
final String userEmail = email;
final endIndex = userEmail.indexOf("#");
userName = userEmail.substring(0, endIndex);
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: new Container(
padding: new EdgeInsets.all(8.0),
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/images/social-logo.png"),
fit: BoxFit.fill),
color: Colors.white,
borderRadius: new BorderRadius.all(new Radius.circular(80.0)),
border: new Border.all(
color: Colors.white,
width: 1.0,
),
),
),
title: Text("One Gov FX Signal Room",
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: 'Spartan',
)),
backgroundColor: kPrimaryColor,
actions: <Widget>[
IconButton(
icon: FaIcon(FontAwesomeIcons.signOutAlt),
color: Colors.white,
onPressed: logOut),
],
),
backgroundColor: antiFlashWhite,
body: Column(
children: <Widget>[
Container(
color: Colors.white,
padding: EdgeInsets.only(left: 10, right: 0, bottom: 10, top: 10),
child: Row(
children: [
CircleAvatar(
backgroundColor: Colors.white,
backgroundImage: AssetImage("assets/images/social-logo.png"),
),
SizedBox(
width: 50,
),
Flexible(
child: Column(children: const <Widget>[
Text('Message From the Admins'),
Text(
'Keep your messages polite and do not abuse the channel. Try to keep your discussions within the community guidelines'),
]),
)
],
),
),
Expanded(
child: Container(
//margin: EdgeInsets.symmetric(horizontal: 5),
child: StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection("messages")
.orderBy(
"timestamp",
)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(
child: CircularProgressIndicator(
backgroundColor: kPrimaryColor,
),
);
List<DocumentSnapshot> docs = snapshot.data.documents;
List<Widget> messages = docs
.map((doc) => Message(
user: doc.data['user'],
text: doc.data['text'],
timestamp: doc.data['timestamp'],
mine: userName == doc.data['user'],
))
.toList();
return ListView(
controller: scrollController,
children: messages,
);
}),
),
),
Container(
color: Colors.white,
child: Row(
children: <Widget>[
IconButton(
icon: FaIcon(
FontAwesomeIcons.image,
color: kPrimaryColor,
),
onPressed: sendChat,
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10),
child: TextField(
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 15,
),
onSubmitted: (value) => sendChat(),
controller: messageController,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
maxLines: null,
cursorColor: kPrimaryColor,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20)),
filled: true,
hintText: "Say Something. Be Nice...",
hintStyle:
TextStyle(fontFamily: 'Montserrat', fontSize: 12),
),
),
),
),
IconButton(
icon: FaIcon(
FontAwesomeIcons.paperPlane,
color: kPrimaryColor,
),
onPressed: sendChat,
),
],
),
),
],
),
);
}
void logOut() async {
try {
await widget.auth.signOut();
widget.signedOut();
} catch (e) {
print("error :" + e.toString());
}
}
Future<void> sendChat() async {
if (messageController.text.length > 0) {
await _firestore.collection("messages").add({
'user': userName,
'text': messageController.text,
'timestamp': FieldValue.serverTimestamp(),
});
messageController.clear();
scrollController.animateTo(scrollController.position.maxScrollExtent,
duration: Duration(milliseconds: 300), curve: Curves.easeOut);
}
}
}
Screenshot of the chat screen:

To send images in a chat, you need a place to host those images. One way of doing this is by using file hosting services like Firebase Cloud Storage. This boils down to these steps.
Upload images on Cloud Storage. The image paths from the
device's local storage can be fetched using image_picker
Store the Cloud Storage path of the uploaded image i.e. using Cloud
Firestore
Display the image from the Cloud Storage path using Image.network()

Related

Implementing comment section for each post in flutter with cloud firestore

I'm creating instagram app clone in flutter with firebase at backend. It's a beginner level project so the coding and structure is basic.
I am stuck at adding comment section under each post. I'm using streambuilder to display data and trying to create a function in which with every image is on the feed screen would have a comment box which is connected to the current-image document in cloud-firestore.
Below is my code and images of database:
class FeedScreen extends StatefulWidget {
const FeedScreen({Key? key}) : super(key: key);
#override
_FeedScreenState createState() => _FeedScreenState();
}
class _FeedScreenState extends State<FeedScreen> {
User? user = FirebaseAuth.instance.currentUser;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
bottomNavigationBar: BottomNavigation(),
appBar: AppBar(
backgroundColor: Colors.black,
automaticallyImplyLeading: false,
title: Text(
"Platform",
style: TextStyle(
color: Colors.white,
fontSize: 32.96,
fontWeight: FontWeight.w500,
fontFamily: 'Yaldevi',
),
),
),
body: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('users').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot){
if(snapshot.hasData){
final List<DocumentSnapshot> documents = snapshot.data!.docs;
return ListView(
children: documents.map((doc) => SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
leading: doc['profileImage'] == null ?
CircleAvatar(
radius: 16.6,
backgroundColor: Colors.white24,
) :
CircleAvatar(
radius: 16.6,
backgroundImage: NetworkImage(
doc['profileImage']
)
),
title: Text(
doc['displayName'],
style: TextStyle(
color: Colors.white,
fontSize: 16.5,
)
),
subtitle: doc['title'] !=null ?
Text(
doc['title'],
style: TextStyle(
color: Colors.white,
fontSize: 12.5,
),
) :
Text(
"Some Title",
style: TextStyle(
color: Colors.white,
)
),
),
if(doc['photoURL'] != null) ... [
Container(
height: 400,
width: 400,
child: Image(
image: NetworkImage(
doc['photoURL'],
),
fit: BoxFit.contain,
)
),
IconButton(
icon: Icon(
Icons.mode_comment_outlined,
color: Colors.white,
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) =>
CommentSection(),
));
},
)
] else if(doc['photoURL'] == null) ...[
Container(
height: 400,
width: 400,
child: Image(
image: AssetImage(
"assets/images/placeholder.png"
),
fit: BoxFit.contain,
)
)
],
ListTile(
leading: Padding(
padding: EdgeInsets.only(bottom: 13.5 ),
child: Text( "# " +
doc['displayName'],
style: TextStyle(
color: Colors.white,
),
),
),
subtitle: Padding(
padding: EdgeInsets.only(bottom: 13.5),
child: doc['decsription'] != null ?
Text( ":" +
doc['decsription'],
style: TextStyle(
color: Colors.white,
)
) :
Text(
"Some Descritiption",
style: TextStyle(
color: Colors.white,
)
)
)
),
]
),
)).toList(),
);
} else {
return CircularProgressIndicator();
}
}
)
);
}
}
and here`s the comment screen code
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class CommentSection extends StatefulWidget {
// const CommentSection({Key? key}) : super(key: key);
#override
_CommentSectionState createState() => _CommentSectionState();
}
class _CommentSectionState extends State<CommentSection> {
var username = ' ';
List photoURL = [];
User? user = FirebaseAuth.instance.currentUser;
CollectionReference userRef = FirebaseFirestore.instance.collection('users');
final _formKey = GlobalKey<FormState>();
late String comments = ' ';
sendComment() async {
final isValid = _formKey.currentState!.validate();
final name = user!.displayName;
var res = await userRef.where('userid', isEqualTo: user!.uid).get();
_formKey.currentState!.save();
var doc = userRef.doc('photoURL');
doc.set({
'comment' : comments,
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: 50),
child: TextFormField(
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
labelText: "Leave a Comment..",
labelStyle: TextStyle(
color: Colors.white,
)
),
onSaved: (value) {
comments = value!;
}
),
)
],
)
),
ElevatedButton.icon(
onPressed: sendComment,
icon: Icon(Icons.send,
color: Colors.white,
),
label: Text(
"Send"
))
],
)
),
);
}
}
That's a really broad use-case, and honestly a bit too broad to answer on Stack Overflow. I recommend focusing on a more concrete, specific problem.
For example, you mention in your comment:
I tried creating a separate collection for comment but the comment would be fetched for every image in database and I'm trying to save and retrieve the comment data for particular image
To allow reading only comments on a specific image, you'll need to associate each comment in the database with an image. The two most common approaches for this are:
Create a document for each image in a top-level collection, and then create a subcollection under that document for the comments on that specific image.
Create a single top-level comments collection, and store the ID of the image in each comment document.

1LateInitializationError: Field 'initUserName' has not been initialized

I am trying to built a social app,Where I am going to post images.When I run the code, I am facing some issues in retrieving data from the firebase.
firebase_auth: ^3.1.1
firebase_core: ^1.6.0
google_sign_in: ^5.1.0
firebase_storage: ^10.0.3
cloud_firestore: ^2.5.3
firebase_analytics: ^8.3.2
lottie: ^1.1.0
image_picker: ^0.8.4
Above is the pubspec.yaml file dependencies.
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _currentIndex = 0;
final List<Widget> _children = [
WeCareHomeScreen(),
WeCareReminder(),
Feed(),
Chatroom(),
Profile(),
];
#override
void initState() {
super.initState();
Provider.of<FirebaseOperations>(context, listen: false)
.initUserData(context)
.whenComplete(() {
setState(() {});
});
}
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: CurvedNavigationBar(
index: 0,
height: 50.0,
items: <Widget>[
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
],
color: Color.fromRGBO(241, 201, 57, 1.0),
buttonBackgroundColor: Colors.black,
backgroundColor: Colors.white,
animationCurve: Curves.easeInOut,
animationDuration: Duration(milliseconds: 600),
onTap: (index) {
setState(() {
_currentIndex = index;
});
}),
);
}
}
Above is the homescreen.dart file code.
class Authentication with ChangeNotifier {
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
late String userUid;
String get getUserUid => userUid;
Future logIntoAccount(String email, String password) async {
UserCredential userCredential = await firebaseAuth
.signInWithEmailAndPassword(email: email, password: password);
String userUid;
User? user = userCredential.user;
userUid = user!.uid;
print(userUid);
notifyListeners();
}
Future createAccount(String email, String password) async {
UserCredential userCredential = await firebaseAuth
.createUserWithEmailAndPassword(email: email, password: password);
User? user = userCredential.user;
userUid = user!.uid;
print('Created Account Uid => $userUid');
notifyListeners();
}
Future logoutViaEmail() {
return firebaseAuth.signOut();
}
Future signInWithGoogle() async {
final GoogleSignInAccount? googleSignInAccount =
await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount!.authentication;
final AuthCredential authCredential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken);
final UserCredential userCredential =
await firebaseAuth.signInWithCredential(authCredential);
final User? user = userCredential.user;
assert(user!.uid != null);
userUid = user!.uid;
print('Google User Uid => $userUid');
notifyListeners();
}
Future signOutWithGoogle() async {
return googleSignIn.signOut();
}
}
Above is Authentification.dart file.
class FirebaseOperations with ChangeNotifier {
late UploadTask imageUploadTask;
late String initUserEmail;
late String initUserImage;
late String initUserName;
String get getInitUserImage => initUserImage;
String get getInitUserName => initUserName;
String get getInitUserEmail => initUserEmail;
Future uploadUserAvatar(BuildContext context) async {
Reference imageReference = FirebaseStorage.instance.ref().child(
'userProfileAvatar/${Provider.of<LandingUtils>(context, listen:
false).getUserAvatar.path}/${TimeOfDay.now()}');
imageUploadTask = imageReference.putFile(
Provider.of<LandingUtils>(context, listen: false).getUserAvatar);
await imageUploadTask.whenComplete(() {
print('Image uploaded!');
});
imageReference.getDownloadURL().then((url) {
Provider.of<LandingUtils>(context, listen: false).userAvatarUrl =
url.toString();
print(
'the user profile avatar url => ${Provider.of<LandingUtils>(context, listen:
false).userAvatarUrl}');
notifyListeners();
});
}
Future createUserCollection(BuildContext context, dynamic data) async {
return FirebaseFirestore.instance
.collection('users')
.doc(Provider.of<Authentication>(context, listen: false).getUserUid)
.set(data);
}
Future initUserData(BuildContext context) async {
return FirebaseFirestore.instance
.collection('users')
.doc(Provider.of<Authentication>(context, listen: false).getUserUid)
.get()
.then((doc) {
print('Fetching user data');
initUserName = doc.data()!['username'];
initUserEmail = doc.data()!['useremail'];
initUserImage = doc.data()!['userimage'];
print(initUserName);
print(initUserEmail);
print(initUserImage);
notifyListeners();
});
}
Future uploadPostData(String postId, dynamic data) async {
return FirebaseFirestore.instance.collection('posts').doc(postId).set(data);
}
}
Above is the firebaseoperations.dart file.
Here once it printed 'Fetching user Data' in the console,it is showing 'Unhandled Exception: Null check operator used on a null value' error.
Also once the image is uploaded ,instead of printing the url of image, '*************' is printed.
And 'Unhandled Exception: LateInitializationError: Field 'initUserName' has not been initialized.' is also printed.
It will me more helpful,if anyone pointout my mistakes and give me a solution.
Unhandled Exception: LateInitializationError: Field 'initUserName' has not been
initialized.
.
.
.
I/flutter (18214): Post image uploaded to storage
I/flutter (18214): Image uploaded
I/flutter (18214):
*************************************************************************************
*************************************************************************************
*********************************************
.
.
.
E/flutter (18214): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception:
LateInitializationError: Field 'initUserName' has not been initialized.
This is how the error looks.
class ProfileHelpers with ChangeNotifier {
ConstantColors constantColors = ConstantColors();
Widget headerProfile(
BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
print(snapshot.data);
return SizedBox(
height: MediaQuery.of(context).size.height * 0.26,
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
height: 150.0,
width: 170.0,
child: Column(
children: [
GestureDetector(
onTap: () {},
child: CircleAvatar(
backgroundColor: constantColors.transparent,
radius: 38.0,
backgroundImage: NetworkImage(
'${Provider.of<FirebaseOperations>
(context).getInitUserImage}'),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
'Vijay',
//snapshot.data?['username'],
//snapshot.data!.data()['username'],
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 20.0),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(EvaIcons.email,
color: constantColors.greenColor, size: 16),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
'username#gmail.com',
// snapshot.data!.get('useremail'),
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 12.0),
),
),
],
),
)
],
),
),
Above is the profile page code.
enter code here
class FeedHelpers with ChangeNotifier {
ConstantColors constantColors = ConstantColors();
Widget appBar(BuildContext context) {
return AppBar(
backgroundColor: constantColors.darkColor.withOpacity(0.6),
centerTitle: true,
actions: [
IconButton(
icon: Icon(Icons.camera_enhance_rounded,
color: constantColors.greenColor),
onPressed: () {
Provider.of<UploadPost>(context, listen: false)
.selectPostImageType(context);
})
],
title: RichText(
text: TextSpan(
text: 'Social ',
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
children: <TextSpan>[
TextSpan(
text: 'Feed',
style: TextStyle(
color: constantColors.blueColor,
fontWeight: FontWeight.bold,
fontSize: 20.0,
))
]),
),
);
}
Widget feedBody(BuildContext context) {
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
child: StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
stream:
FirebaseFirestore.instance.collection('posts').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>>
snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
{
return Center(
child: SizedBox(
height: 500.0,
width: 400.0,
child:
Lottie.asset('assets/animations/loading.json'),
),
);
} else {
return loadPosts(context, snapshot);
}
},
),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: constantColors.darkColor.withOpacity(0.6),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(18.0),
topRight: Radius.circular(18.0))),
),
),
);
}
Widget loadPosts(
BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot
documentSnapshot) {
Map<String, dynamic> data =
documentSnapshot.data()! as Map<String, dynamic>;
return Container(
height: MediaQuery.of(context).size.height * 0.62,
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 8.0, left: 8.0),
child: Row(
children: [
GestureDetector(
child: CircleAvatar(
backgroundColor: constantColors.blueGreyColor,
radius: 20.0,
backgroundImage: NetworkImage(
'${Provider.of<UploadPost>
(context).getUploadPostImage}'),
// NetworkImage(documentSnapshot['userimage']),
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.6,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: RichText(
text: TextSpan(
text: data['username'],
style: TextStyle(
color: constantColors.blueColor,
fontSize: 14.0,
fontWeight: FontWeight.bold),
children: <TextSpan>[
TextSpan(
text: ' , 12 hours ago',
style: TextStyle(
color:
constantColors.lightColor
.withOpacity(0.8)))
]),
)),
Container(
child: Text(
data['username'],
style: TextStyle(
color: constantColors.greenColor,
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
),
),
],
),
),
)
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
height: MediaQuery.of(context).size.height * 0.46,
width: MediaQuery.of(context).size.width,
child: FittedBox(
// child: Image.network(downloadURL.toString()),
child: Image.network(data['postimage'], scale:
2))),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Padding(
padding: const EdgeInsets.only(left: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 80.0,
child: Row(
children: [
GestureDetector(
child: Icon(
FontAwesomeIcons.heart,
color: constantColors.redColor,
size: 22.0,
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
'0',
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0),
),
)
],
),
),
Above is feed_helper file.
class UploadPost with ChangeNotifier {
TextEditingController captionController = TextEditingController();
ConstantColors constantColors = ConstantColors();
late File uploadPost;
late File uploadPostImage;
File get getUploadPostImage => uploadPostImage;
late String uploadPostImageUrl;
String get getUploadPostImageUrl => uploadPostImageUrl;
final picker = ImagePicker();
late UploadTask imagePostUploadTask;
Future pickUploadPostImage(BuildContext context, ImageSource
source) async {
final uploadPostImageVal = await picker.pickImage(source: source);
uploadPostImageVal == null
? print('Select Image')
: uploadPostImage = File(uploadPostImageVal.path);
print(uploadPostImageVal!.path);
uploadPostImage != null
? showPostImage(context)
: print('Image upload error');
notifyListeners();
}
Future uploadPostImageToFirebase() async {
Reference imageReference = FirebaseStorage.instance
.ref()
.child('posts/${uploadPostImage!.path}/${TimeOfDay.now()}');
imagePostUploadTask = imageReference.putFile(uploadPostImage!);
await imagePostUploadTask.whenComplete(() {
print('Post image uploaded to storage');
});
imageReference.getDownloadURL().then((imageUrl) {
uploadPostImageUrl = imageUrl;
print(uploadPostImageUrl);
});
notifyListeners();
}
Above file is the uploadpost.dart file
The problem is that you're declaring the initUserName field as late and trying to access it before initializing it (giving it a value)
The late keyword tells the compiler not to worry about the variable being null because you guarantee that you'll have given it a value before trying to access it.
You could either declare initUserName as String? initUserName
This way you'll have initialized it with the null value;
Otherwise you can make sure you set a value to it like that: FirebaseOperations.initUserName = 'username'; before you try to read it's value

How to get email of user from firebase in Text Widget

I want to write the User's email under the User's name in the Navigation drawer, but I cannot access the email in Text Widget
I used this code for fetching user email id from Firebase but unable to write inside Text
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
firebase_auth.FirebaseAuth firebaseAuth = firebase_auth.FirebaseAuth.instance;
Future<void> signOut() async {
await firebaseAuth.signOut();
}
dynamic user;
String userEmail;
getCurrentUserInfo() async {
user = await firebaseAuth.currentUser;
userEmail = user.email;
print(userEmail);
return userEmail;
}
static var chartdisplay;
bool isSwitched = true;
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Padding(
padding: EdgeInsets.symmetric(horizontal: 15),
child: Builder(
builder: (context) => IconButton(
icon: Image.asset(
"assets/images/menu.png",
),
onPressed: () => Scaffold.of(context).openDrawer(),
),
),
),
backgroundColor: const Color(0xffe8e5af),
elevation: 0,
centerTitle: false,
titleSpacing: 0,
),
drawer: new Drawer(
child: new ListView(
padding: EdgeInsets.zero,
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(vertical: 50, horizontal: 30),
color: const Color(0xffe8e5af),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
CircleAvatar(
radius: 46,
backgroundColor: Colors.white,
child: CircleAvatar(
backgroundImage: AssetImage('assets/images/avatar.jpg'),
radius: 40,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Nabia Salman',
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 13,
color: const Color(0xff000000),
fontWeight: FontWeight.w700,
),
textAlign: TextAlign.left,
),
Text(
//"${user.email}",
"nabia.salman99#gmail.com",
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 9,
color: const Color(0xff000000),
),
textAlign: TextAlign.left,
),
],
),
],
),
),
This is how my screen looks like
Please help me out in finding the solution for this as I am new to Flutter
Thank you in advance

Want to pass the total price in the bottom navigation bar in flutter

How can i show the total amount in the bottom navigation bar... The app uses firebase backend... I have a filed in my database name total price of each item... Now I want to fetch the total price of each item and then add it and display in the bottom navigation bar..
I have attach my firebase backend screen shot.. what i need is to get all the value of the field 'total' add it up and show it in the bottom bar below the Total which is hardcoded as 999 currently section...
It would be helpful if some let me know how to do it.. I am new to app development and flutter as well
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
import 'dart:async';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final myController = TextEditingController(); ///Alert Dialog box input text myController will be use to store the number of qty
String id;
var qty;
var price;
var total;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home:Scaffold(
bottomNavigationBar: new Container( //// Bottom Naviagtion Bar for check out and Total price
color: Colors.white,
child: Row(
children: <Widget>[
Expanded(child: ListTile(
title: Text("Total"),
subtitle: Text("Rs 999"),
),),
Expanded(
child: MaterialButton(onPressed:() {},
child: Text("Check Out",style: TextStyle(color: Colors.white),),
color: Colors.red,) ,
)
],
),
),
appBar: AppBar(title: Text('MyKart'),
),
body: (
StreamBuilder(
stream: Firestore.instance.collection('KartDetails').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot kartDetails = snapshot.data.documents[index];
return Container(
height: 150,
child: Card(
elevation: 10,
child: Container(
height: 100,
width: 100,
child: Row(
children: <Widget>[
Container(
width: 100,
height: 100,
child: Image.network(kartDetails['img']),
),
Container(
child: (Text(kartDetails['item'])),
),
Container(
width: 50,
child: (Text('Rs '+kartDetails['price'].toString(),textAlign: TextAlign.end,)),
),
Container(
margin: EdgeInsets.only(left: 20),
height: 120,
width: 50,
color: Colors.white10,
child: Column(
children: <Widget>[
RaisedButton(
color: Colors.grey,
onPressed: (){
showDialog(context: context,
builder: (BuildContext context){
return Dialog(
child: Container(
height: 250,
color: Colors.white10,
child: Container(
margin: EdgeInsets.all(40.0),
child: Column(
children: <Widget>[
TextField(
controller: myController,
keyboardType: TextInputType.number,
decoration: InputDecoration(hintText: 'Enter the Quantity'),
),
Container(
height: 50,
),
RaisedButton(
color: Colors.blue,
child: Text('Submit'),
onPressed: () async{
qty = myController.text;
//==================================================================Total Number of QTY ENTERED==========================================//
if (int.parse(qty)>0 && int.parse(qty)>=5) {
CollectionReference collectionRefernce = Firestore
.instance.collection(
'KartDetails');
QuerySnapshot querySnapshot = await collectionRefernce
.getDocuments();
querySnapshot
.documents[index]
.reference
.updateData(
{"quantity": qty});
//==================================================================Calculate price for each product==========================================//
price = kartDetails['price'];
total=int.parse(qty)*price;
querySnapshot
.documents[index]
.reference
.updateData(
{"total": total});
print(myController
.toString());
Navigator.of(context)
.pop();
myController.clear();
Fluttertoast.showToast(msg: "Quantity Updated",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 20.0
);
}
else if(int.parse(qty) < 5 || int.parse(qty)<0) {
Fluttertoast.showToast(msg: "Minimum 5 quanity",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 20.0
);
myController.clear();
}
else {
Fluttertoast.showToast(msg: "Please enter valid quantity",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 20.0
);
myController.clear();
}
//Firebase query
},
)
],
),
),
),
);
});
},
child: Icon(Icons.shopping_basket),
),
Container(
height: 20,
),
RaisedButton(
color: Colors.grey,
child: Icon(Icons.delete,color: Colors.black87,),
)
],
),
),
Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 3),
height: 50,
width: 70,
child: Center(child: Text('Quantity')),
),
Container(
width: 70,
child: Center(child: Text((kartDetails['quantity']).toString())),
),
Container(
margin: EdgeInsets.only(top: 25),
child: Center(child: Text('Total Price')),),
Container(
margin: EdgeInsets.only(left: 3),
width: 70,
child: Center(child: Text(("Rs " + (kartDetails['total']).toString()))),
),
],
),
],
),
),
),
);
},
);
}
else{
return Center(
child: Container(),
);;
}
},
)
),
),
);
}
}
You can easily do it with this method:
var totalCartValue = 0;
String getCartTotal() async {
QuerySnapshot snapshot = await Firestore.instance
.collection('KartDetails')
.getDocuments();
snapshot.documents.forEach((doc) {
setState((){
totalCartValue += doc.data['total'];
});
});
return totalCartValue.toString();
}
P.S: This method will give you the total of all values in the KartDetails collection not the total for the current user, for the current user it should be like this:
var totalCartValue = 0;
String getCartTotal() async {
QuerySnapshot snapshot = await Firestore.instance
.collection('KartDetails')
.where("UID", isEqualTo: FirebaseAuth.instance.currentUser().toString())
.getDocuments();
snapshot.documents.forEach((doc) {
setState((){
totalCartValue += doc.data['total'];
});
});
return totalCartValue.toString();
}
And use it in the UI that way:
class YourClassName extends StatefulWidget {
#override
_YourClassNameState createState() => _YourClassNameState();
}
class _YourClassNameState extends State<YourClassName> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: //your body code,
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.cart_shopping),
title: new Text(totalCartValue),
),
]
)
);
}
}
You should call it inside your initState so it gets executed whenever app starts:
#override
initState(){
super.initState();
getCartTotal();
}
This is a very vague question, so I will give a shot at one method of solving this. In order to do this you will need some sort of state management solution. I suggest using provider. Flutter has a tutorial on provider here. Essentially you will have to create a ChangeNotifier that every time would onAddItem and onDeleteItem and call notifyListeners() whenever you add or delete items. Then your bottom bar would simply use a Consumer to get the values from your ChangeNotifier. As I said this is just one approach, but since you did not give a replicable example this is the best I can do.

Trying to access an instance of user. NoSuchMethod error when widget loads email = null. calling loggedInUser.email

Im calling a Firebase user email, i want to display user details on the screen. When widget loads, NoSuchMethod error displays and crashes app. Not sure where to go from here
import 'package:flutter/material.dart';
import 'package:simmanager/constaints.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class SettingScreen extends StatefulWidget {
#override
_SettingScreenState createState() => _SettingScreenState();
}
class _SettingScreenState extends State<SettingScreen> {
final _auth = FirebaseAuth.instance;
final _firestore = Firestore.instance;
FirebaseUser loggedInUser;
#override
void initState() {
getCurrentUser();
super.initState();
}
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(
appBar: AppBar(
title: Text('Settings'),
backgroundColor: primaryColor,
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(
Icons.edit,
color: Colors.black,
),
backgroundColor: secondaryColor,
),
body: SafeArea(
child: Container(
color: backgroundColor,
child: Column(
children: <Widget>[
Center(
child: Container(
margin: EdgeInsets.only(top: 20.0),
child: Icon(
Icons.account_circle,
size: 75.0,
color: primaryLight,
),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
blurRadius: 5.0,
color: Colors.grey[300],
spreadRadius: 5.0,
),
],
borderRadius: BorderRadius.circular(20.0),
),
padding: EdgeInsets.all(25.0),
child: Row(
children: <Widget>[
Container(
child: Text(
'Name: ',
style: TextStyle(fontSize: 16.0),
),
),
// TODO: add stream for user details
Container(
child: Text('Test'),
),
],
),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
blurRadius: 5.0,
color: Colors.grey[300],
spreadRadius: 5.0,
),
],
borderRadius: BorderRadius.circular(20.0),
),
padding: EdgeInsets.all(25.0),
child: Row(
children: <Widget>[
Container(
child: Text(
'Email: ',
style: TextStyle(fontSize: 16.0),
),
),
// TODO: add stream for user details
Container(
child: Text(loggedInUser.email),
),
],
),
),
),
The following NoSuchMethodError was thrown building SettingScreen(dirty, state: _SettingScreenState#b9d92):
The getter 'email' was called on null.
Receiver: null
Tried calling: email
I've passed through it too. The way I managed so that I could fix the error was change the position of auth.currentUser() declaration. You probably have created your Auth auth inside the StatelessWidget.
Try to move the instance of Auth from StatelessWidget to your State, right before your void initState().

Resources