How to call multiple collections from fire store firebase using flutter? - firebase

body: SafeArea(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection("Daily Recipe ")
.snapshots(),
builder: (____,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.hasData && snapshot.data != null) {
print("Total Documents : ${snapshot.data!.docs.length}");
if (snapshot.data!.docs.isNotEmpty) {
return ListView.separated(
itemBuilder: (___, int index) {
Map<String, dynamic> docData =
snapshot.data!.docs[index].data();
if (docData.isEmpty) {
return const Text(
"Document is empty.",
textAlign: TextAlign.center,
);
}
String Name =
snapshot.data!.docs.elementAt(index).get("Name");
String Duration =
snapshot.data!.docs.elementAt(index).get("Duration");
List<dynamic> Ingredients = snapshot.data!.docs
.elementAt(index)
.get("Ingredients");
List<dynamic> Directions = snapshot.data!.docs
.elementAt(index)
.get("Directions");
return Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Card(
elevation: 100.0,
child: Stack(
children: [
Image.network(snapshot.data!.docs
.elementAt(index)
.get("Image")),
Center(
child: Padding(
padding: const EdgeInsets.only(
top: 150.0, left: 10.0),
child: Text(
Name,
style: const TextStyle(
fontSize: 25.0,
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
const Padding(
padding: EdgeInsets.all(10.0),
child: Text(
"Appetizers",
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
),
Card(
// child: cards(),
)
],
),
);
},
separatorBuilder: (___, ____) {
return const Divider();
},
itemCount: snapshot.data!.docs.length);
} else {
return const Center(
child: Text("Document aren't available."),
);
}
} else {
return Center(
child: Text("Getting Error"),
);
}
},
),
),

Related

Flutter update UI on button press

If I remove the awaits from my viewModel.sendMessage() it works as expected, however I can't set the state with the value returned. Is there a way to update the UI from setState?
I'm just not sure how to do both at the same time, the parent class for this widget is a StatefulWidget, Idk if that matters. My ConversationViewModel is just a changeNotifier.
#override
Widget build(BuildContext context) {
UsViewModel viewModel = Provider.of<UsViewModel>(context, listen: false);
viewModel.setUs();
var us = Provider.of<UsViewModel>(context, listen: true).us;
return Consumer<ConversationViewModel>(builder: (BuildContext context, viewModel, Widget child) {
return Scaffold(
key: viewModel.scaffoldKey,
appBar: AppBar(
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.keyboard_backspace,
),
),
elevation: 0.0,
titleSpacing: 0,
title: buildName(),
),
body: Container(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
Flexible(
child: StreamBuilder(
stream: messageListStream(widget.chatId),
builder: (context, snapshot) {
if (snapshot.hasData) {
List messages = snapshot.data.docs;
return ListView.builder(
controller: scrollController,
padding: EdgeInsets.symmetric(horizontal: 10.0),
itemCount: messages.length,
reverse: true,
itemBuilder: (BuildContext context, int index) {
Message message = Message.fromJson(
messages.reversed.toList()[index].data());
return ChatBubble(
message: '${message.content}',
time: message?.time,
isMe: message?.senderUid == us?.uid,
type: message?.type);
},
);
} else {
return Center(child: circularProgress(context));
}
},
),
),
Align(
alignment: Alignment.bottomCenter,
child: BottomAppBar(
elevation: 10.0,
child: Container(
constraints: BoxConstraints(maxHeight: 100.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: TextField(
controller: messageController,
focusNode: focusNode,
style: TextStyle(
fontSize: 15.0,
color:
Theme.of(context).textTheme.headline6.color,
),
decoration: InputDecoration(
contentPadding: EdgeInsets.all(10.0),
enabledBorder: InputBorder.none,
border: InputBorder.none,
hintText: "Type your message",
hintStyle: TextStyle(
color:
Theme.of(context).textTheme.headline6.color,
),
),
maxLines: null,
),
),
IconButton(
icon: Icon(
Feather.send,
color: Theme.of(context).colorScheme.secondary,
),
onPressed: () {
if (messageController.text.trim().isNotEmpty) {
sendMessage(viewModel, us);
}
},
),
],
),
),
),
)
],
),
),
);
});
}
sendMessage(ConversationViewModel viewModel, var us,
{bool isImage = false, int imageType}) async {
String msg;
msg = messageController.text.trim();
messageController.clear();
Message message = Message(
content: '$msg',
senderUid: us?.uid,
time: Timestamp.now(),
);
if (msg.isNotEmpty) {
String id = await viewModel.sendMessage(widget.usId, message);
setState(() {
chatId = id;
});
}
}
If you using ChangeNotifier with Provider package you don't need setState method. You should read Provider documentation: https://pub.dev/packages/provider
ft: That you create listeners for each item in this line.
isMe: message?.senderUid == context.watch<UsViewModel>.us ?.uid,
How to use a provider according to your question, added an example;
#override
Widget build(BuildContext context) {
context.read<UsViewModel>().setUs();
return Scaffold(
key: context.read<UsViewModel>().scaffoldKey,
appBar: AppBar(
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.keyboard_backspace,
),
),
elevation: 0.0,
titleSpacing: 0,
title: buildName(),
),
body: Container(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
Flexible(
child: StreamBuilder(
stream: messageListStream(widget.chatId),
builder: (context, snapshot) {
if (snapshot.hasData) {
List messages = snapshot.data.docs;
return ListView.builder(
controller: scrollController,
padding: EdgeInsets.symmetric(horizontal: 10.0),
itemCount: messages.length,
reverse: true,
itemBuilder: (BuildContext context, int index) {
Message message = Message.fromJson(
messages.reversed.toList()[index].data());
return ChatBubble(
message: '${message.content}',
time: message?.time,
isMe: message?.senderUid == context.watch<UsViewModel>.us ?.uid,
type: message?.type);
},
);
} else {
return Center(child: circularProgress(context));
}
},
),
),
Align(
alignment: Alignment.bottomCenter,
child: BottomAppBar(
elevation: 10.0,
child: Container(
constraints: BoxConstraints(maxHeight: 100.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: TextField(
controller: messageController,
focusNode: focusNode,
style: TextStyle(
fontSize: 15.0,
color:
Theme.of(context).textTheme.headline6.color,
),
decoration: InputDecoration(
contentPadding: EdgeInsets.all(10.0),
enabledBorder: InputBorder.none,
border: InputBorder.none,
hintText: "Type your message",
hintStyle: TextStyle(
color:
Theme.of(context).textTheme.headline6.color,
),
),
maxLines: null,
),
),
IconButton(
icon: Icon(
Feather.send,
color: Theme.of(context).colorScheme.secondary,
),
onPressed: () {
if (messageController.text.trim().isNotEmpty) {
sendMessage(context);
}
},
),
],
),
),
),
)
],
),
),
);
}
sendMessage(BuildContext context) async {
String msg;
msg = messageController.text.trim();
messageController.clear();
Message message = Message(
content: '$msg',
senderUid: context.read<UsViewModel>().us?.uid,
time: Timestamp.now(),
);
if (msg.isNotEmpty) {
String id = await context.read<UsViewModel>().sendMessage(widget.usId, message);
setState((){
chatId = id;
});
}
}

snapshot.data becomes null after half a second

I have a collection called pending_appointments and I want to access all of the documents which have the field patienduid equal to the current user's uid. Then there is a stream builder, but snapshots.data becomes null.
Like when I go to that screen, it shows me the expected results for about half a second and then it changes to 'No appointment found'.
Also, if I remove that 'where' statement, it shows me all the pending appointments which is the expect result, but as soon as I add the where statement which should give me the desired result, it goes back to no appointment after showing me the desired results for half a second.
Widget build(BuildContext context) {
return SafeArea(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('pending_appointments')
.where('patientUid', isEqualTo: user.uid)
.orderBy('date')
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.data != null) {
return ListView.builder(
scrollDirection: Axis.vertical,
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data.size,
itemBuilder: (context, index) {
DocumentSnapshot document = snapshot.data.docs[index];
print(_compareDate(document['date'].toDate().toString()));
if (_checkDiff(document['date'].toDate())) {
deleteAppointment(document.id);
}
return Card(
elevation: 2,
child: InkWell(
onTap: () {},
child: ExpansionTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(left: 5),
child: Text(
'Dr. ${document['doctor']}',
style: GoogleFonts.lato(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Text(
_compareDate(document['date'].toDate().toString())
? "TODAY"
: "",
style: GoogleFonts.lato(
color: Colors.green,
fontSize: 18,
fontWeight: FontWeight.bold),
),
SizedBox(
width: 0,
),
],
),
subtitle: Padding(
padding: const EdgeInsets.only(left: 5),
child: Text(
_dateFormatter(
document['date'].toDate().toString()),
style: GoogleFonts.lato(),
),
),
children: [
Padding(
padding: const EdgeInsets.only(
bottom: 20, right: 10, left: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Patient name: " + document['name'],
style: GoogleFonts.lato(
fontSize: 16,
),
),
SizedBox(
height: 10,
),
Text(
"Time: " +
_timeFormatter(
document['date']
.toDate()
.toString(),
),
style: GoogleFonts.lato(
fontSize: 16,
),
),
],
),
IconButton(
tooltip: 'Delete Appointment',
icon: Icon(
Icons.delete,
color: Colors.black87,
),
onPressed: () {
print(">>>>>>>>>" + document.id);
_documentID = document.id;
showAlertDialog(context);
},
),
],
),
),
],
),
),
);
},
);
} else {
return Center(
child: Text(
'No Appointment Scheduled',
style: GoogleFonts.lato(
color: Colors.grey,
fontSize: 18,
),
),
);
}
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
remove this
if (snapshot.connectionState == ConnectionState.active) {
}
add this to your code
if (Snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (Snapshot.connectionState == ConnectionState.none) {
return Container();
}
if (Snapshot.data.docs.isEmpty) {
return Text(
'Document Empty',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
);
}
if (!Snapshot.hasData) {
return Text(
'0',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
);
}
return ListView.builder(
scrollDirection: Axis.vertical,
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
final document = snapshot.data.docs[index].data();
print(_compareDate(document['date'].toDate().toString()));
if (_checkDiff(document['date'].toDate())) {
deleteAppointment(document.id);
}
});

Show Spinner using ModalProgressHUD in Flutter whilst ListView.builder reads information from Firebase

I have a screen where I try to read all my documents as a list using a Listview.builder in Flutter. I want to use ModalProgressHUD to show circular spinner whilst data is read from Firebase. When it's done building, I want to stop showing circular spinner by setting showSpinner to false.
I can hack this for a form screen but can't seem to for this view all screen, perhaps it's because it's a Listview.builder.
Thanks in advance.
Code below:
//class wide declaration
bool showSpinner = true;
Widget build(BuildContext context) {
ExpenseNotifier expenseNotifier = Provider.of<ExpenseNotifier>(context);
Future<void> _resfreshList() async {
expenseNotifier.getExpenses(expenseNotifier);
}
return Scaffold(
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: RefreshIndicator(
onRefresh: _resfreshList,
child: Consumer<ExpenseNotifier>(
builder: (context, expense, child) {
return expense == null
? Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
PaddingClass(bodyImage: 'images/empty.png'),
SizedBox(
height: 20.0,
),
Text(
'You don\'t have any expenses',
style: kLabelTextStyle,
),
],
)
: ListView.separated(
itemBuilder: (context, int index) {
var myExpense = expense.expenseList[index];
return Card(
elevation: 8.0,
color: Colors.white70,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
RegularExpenseTextPadding(
regText:
'${_formattedDate(myExpense.updatedAt)}',
),
Container(
margin: EdgeInsets.all(20.0),
padding: const EdgeInsets.all(15.0),
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(5.0)),
border: Border.all(
color: kThemeStyleBorderHighlightColour),
),
child: Row(
children: <Widget>[
Expanded(
flex: 5,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text(
'${myExpense.amount}',
style: kRegularTextStyle,
),
SizedBox(
height: 20.0,
),
Text(
myExpense.description,
style: kRegularTextStyle,
),
],
),
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
expenseNotifier.currentExpense =
expenseNotifier
.expenseList[index];
Navigator.of(context).push(
MaterialPageRoute(builder:
(BuildContext context) {
return ExpenseDetailsScreen();
}));
},
child: Icon(
FontAwesomeIcons.caretDown,
color: kThemeIconColour,
),
),
),
],
),
),
],
),
);
},
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
height: 20.0,
);
},
itemCount: expenseNotifier.expenseList.length,
);
},
),
),
),
);
}

How to pass an initial value to the Timer widget - Flutter

I have this timer from this package https://pub.dev/packages/stop_watch_timer
and I am trying to pass an initial value to it:
DateTime dateNow = DateTime.now () // this is my current Time.
Duration initialTime;
initialTime = dateNow.difference (timeStampfromFirestore.toDate ());
initialTime -> this is the value with which I want the Timer to start, but I have not been able to understand how the package works
for example:
the timer right now starts like this: 00:00:00
I'm trying to make it start like this for example: 00:15:00
where initialTime = 00:15:00
import 'package:flutter/material.dart';
import 'package:stop_watch_timer/stop_watch_timer.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final StopWatchTimer _stopWatchTimer = StopWatchTimer(
onChange: (value) => print('onChange $value'),
onChangeSecond: (value) => print('onChangeSecond $value'),
onChangeMinute: (value) => print('onChangeMinute $value'),
);
final _scrollController = ScrollController();
#override
void initState() {
super.initState();
_stopWatchTimer.rawTime.listen((value) =>
print('rawTime $value ${StopWatchTimer.getDisplayTime(value)}'));
_stopWatchTimer.minuteTime.listen((value) => print('minuteTime $value'));
_stopWatchTimer.secondTime.listen((value) => print('secondTime $value'));
_stopWatchTimer.records.listen((value) => print('records $value'));
_stopWatchTimer.onExecute.add(StopWatchExecute.start);
/// Can be set preset time. This case is "00:01.23".
// _stopWatchTimer.setPresetTime(mSec: 1234);
}
#override
void dispose() async {
super.dispose();
await _stopWatchTimer.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
/// Display stop watch time
Padding(
padding: const EdgeInsets.only(bottom: 0),
child: StreamBuilder<int>(
stream: _stopWatchTimer.rawTime,
initialData: _stopWatchTimer.rawTime.value,
builder: (context, snap) {
final value = snap.data;
final displayTime = StopWatchTimer.getDisplayTime(value);
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8),
child: Text(
displayTime,
style: TextStyle(
fontSize: 40,
fontFamily: 'Helvetica',
fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: Text(
value.toString(),
style: TextStyle(
fontSize: 16,
fontFamily: 'Helvetica',
fontWeight: FontWeight.w400),
),
),
],
);
},
),
),
/// Display every minute.
Padding(
padding: const EdgeInsets.only(bottom: 0),
child: StreamBuilder<int>(
stream: _stopWatchTimer.minuteTime,
initialData: _stopWatchTimer.minuteTime.value,
builder: (context, snap) {
final value = snap.data;
print('Listen every minute. $value');
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Padding(
padding: EdgeInsets.symmetric(horizontal: 4),
child: Text(
'minute',
style: TextStyle(
fontSize: 17,
fontFamily: 'Helvetica',
),
),
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 4),
child: Text(
value.toString(),
style: TextStyle(
fontSize: 30,
fontFamily: 'Helvetica',
fontWeight: FontWeight.bold),
),
),
],
)),
],
);
},
),
),
/// Display every second.
Padding(
padding: const EdgeInsets.only(bottom: 0),
child: StreamBuilder<int>(
stream: _stopWatchTimer.secondTime,
initialData: _stopWatchTimer.secondTime.value,
builder: (context, snap) {
final value = snap.data;
print('Listen every second. $value');
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Padding(
padding: EdgeInsets.symmetric(horizontal: 4),
child: Text(
'second',
style: TextStyle(
fontSize: 17,
fontFamily: 'Helvetica',
),
),
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 4),
child: Text(
value.toString(),
style: TextStyle(
fontSize: 30,
fontFamily: 'Helvetica',
fontWeight: FontWeight.bold),
),
),
],
)),
],
);
},
),
),
/// Lap time.
Container(
height: 120,
margin: const EdgeInsets.all(8),
child: StreamBuilder<List<StopWatchRecord>>(
stream: _stopWatchTimer.records,
initialData: _stopWatchTimer.records.value,
builder: (context, snap) {
final value = snap.data;
if (value.isEmpty) {
return Container();
}
Future.delayed(const Duration(milliseconds: 100), () {
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut);
});
print('Listen records. $value');
return ListView.builder(
controller: _scrollController,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
final data = value[index];
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8),
child: Text(
'${index + 1} ${data.displayTime}',
style: TextStyle(
fontSize: 17,
fontFamily: 'Helvetica',
fontWeight: FontWeight.bold),
),
),
const Divider(
height: 1,
)
],
);
},
itemCount: value.length,
);
},
),
),
],
),
),
),
);
}
}
Can be used setPresetTime interface.
Please see.
https://github.com/hukusuke1007/stop_watch_timer
Set Preset Time
Can be set preset time. This case is "00:01.23". When timer is idle state, can be set this.
// Set Millisecond.
_stopWatchTimer.setPresetTime(mSec: 1234);
// Set Hours. (ex. 1 hours)
_stopWatchTimer.setPresetHoursTime(1);
// Set Minute. (ex. 30 minute)
_stopWatchTimer.setPresetMinuteTime(30);
// Set Second. (ex. 120 second)
_stopWatchTimer.setPresetSecondTime(120);

Download data from firebase Firestore to flutter

I am using Firestore as a database for a Chat in one part of the application that I am building. I have a collection on my Firestore that looks like this:
messages(collection)
userId
userId-otherUserId(sub-collection)
randomId
content : String,
timestamp : Date
...
and I would like to retrieve firstly all of the userIs-otherUserId in a ListView and then to retrieve the lastMessage by retrieving the last randomId(and in that randomId the last message is the last element with key 'content') and I would like it to look something like this.
Prototype
where the Loading represents last message but the name and profilePicture I can get from my API.
The pictures of my Firestore database:
First Image
Second Image
Third Image
Is there any chance that I could save the name and Profile picture on the database in the userId-otherUserId(collection)?
The code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:dio/dio.dart';
import 'package:disby_app/const.dart';
import 'package:disby_app/data/request_model.dart';
import 'package:disby_app/global_widgets/loading_indicator.dart';
import 'package:disby_app/main_screens/main_chat_and_request_screens/chat.dart';
import 'package:disby_app/main_screens/main_chat_and_request_screens/profile_details_screen.dart';
import 'package:disby_app/public/keys.dart';
import 'package:disby_app/services/json_requests.dart';
import 'package:flutter/material.dart';
import 'package:flutter_translate/flutter_translate.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../global_widgets/chat_and_requests_placeholder.dart';
class MainChatScreen extends StatefulWidget {
#override
_MainChatScreenState createState() => _MainChatScreenState();
}
class _MainChatScreenState extends State<MainChatScreen> {
bool _areThereChats = false;
bool _isLoading = true;
String groupChatId;
String userId = '1';
List<String> listOfLastMessages = [];
List<String> listOfIds = [];
List<ArrayOfRequestsModel> arrayOfRequests = [];
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
Future readLocal() async {
var prefs = await SharedPreferences.getInstance();
userId = prefs.getString(kUserId) ?? '';
print(userId);
setState(() {});
}
Future<void> _getRequests() async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString(kUserId);
try {
await Dio().post(baseUrl + acceptedUsers + "/" + userId).then((snapshot) {
print(snapshot);
final Map<String, dynamic> response = snapshot.data;
print(response);
if (response['response'] == 'success') {
List<dynamic> arrayFromServer = response['acceptedUsers'];
if (arrayFromServer.isNotEmpty) {
arrayFromServer.forEach((userData) {
arrayOfRequests.add(ArrayOfRequestsModel.fromJson(userData));
listOfIds.add(userData['userId']);
print(userData['userId']);
});
_areThereChats = true;
_isLoading = false;
getMessages(userId);
} else {
_areThereChats = false;
_isLoading = false;
}
setState(() {});
} else {
_areThereChats = false;
_isLoading = false;
setState(() {});
}
});
} catch (e) {
print(e);
}
}
getMessages(String userId) {
int i = 0;
print(listOfIds.length);
print(listOfIds);
listOfIds.forEach((element) {
Firestore.instance
.collection('messages')
.document('$userId')
.collection('$userId-$element')
.orderBy('timestamp', descending: true)
.limit(3)
.getDocuments()
.then((QuerySnapshot snapshot) {
print(snapshot.documents[0].data['content']);
snapshot.documents.forEach((f) {
print(f.data['content']);
listOfLastMessages.add(f.data['content']);
setState(() {});
i++;
});
if (i == listOfIds.length) {
setState(() {});
print(listOfLastMessages);
}
});
});
}
#override
void initState() {
readLocal();
_getRequests();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Container(
width: double.infinity,
height: double.infinity,
child: SingleChildScrollView(
// child: (userId != '1')
// ? StreamBuilder(
// stream: Firestore.instance
// .collection('messages')
// .document('5ef4d83175b07cf074525c08')
// .snapshots(),
// builder: (context, snapshot) {
// // if (snapshot.hasData) {
// if (!snapshot.hasData) {
// return Center(
// child: CircularProgressIndicator(
// valueColor: AlwaysStoppedAnimation<Color>(themeColor),
// ),
// );
// } else {
// return Container(
// width: 100,
// height: 200,
// child: ListView.builder(
// padding: EdgeInsets.all(10.0),
// itemBuilder: (context, index) =>
// buildItem(context, snapshot.data.documents),
// itemCount: snapshot.data.documents.length,
// ),
// );
// }
// },
// )
// : LoadingIndicator(
// loading: _isLoading,
// ),
// ),
child: Column(
children: <Widget>[
(_isLoading == false)
? (_areThereChats == true)
? Container(
child: AnimatedList(
key: _listKey,
shrinkWrap: true,
initialItemCount: arrayOfRequests.length,
itemBuilder:
(BuildContext context, index, animation) {
return _buildItem(context, arrayOfRequests[index],
animation, index);
},
),
)
: ChatAndRequestPlaceholder(
text: translate('when_someone_sends_you_a_request'))
: LoadingIndicator(
loading: _isLoading,
),
],
),
),
),
);
}
Widget buildItem(BuildContext context, DocumentSnapshot document) {
if (document['id'] == userId) {
return Container();
} else {
return Container(
child: FlatButton(
child: Row(
children: <Widget>[
Flexible(
child: Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Nickname: ${document['content']}',
style: TextStyle(color: primaryColor),
),
alignment: Alignment.centerLeft,
margin: EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 5.0),
),
Container(
child: Text(
'About me: ${document['content'] ?? 'Not available'}',
style: TextStyle(color: primaryColor),
),
alignment: Alignment.centerLeft,
margin: EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 0.0),
)
],
),
margin: EdgeInsets.only(left: 20.0),
),
),
],
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
peerId: document.documentID,
peerAvatar: document['photoUrl'],
),
),
);
},
color: greyColor2,
padding: EdgeInsets.fromLTRB(25.0, 10.0, 25.0, 10.0),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
),
margin: EdgeInsets.only(bottom: 10.0, left: 5.0, right: 5.0),
);
}
}
_buildItem(BuildContext context, ArrayOfRequestsModel arrayOfSentRequests,
Animation animation, int index) {
return GestureDetector(
onTap: () {
print(arrayOfSentRequests.profilePictureUrl);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
peerId: arrayOfSentRequests.userId,
peerAvatar: arrayOfSentRequests.profilePictureUrl,
),
),
);
},
child: Container(
height: 82,
child: ScaleTransition(
scale: animation,
child: Padding(
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Color.fromRGBO(0, 0, 0, 0.07),
offset: Offset(0, 5),
blurRadius: 11,
),
],
),
width: double.infinity,
height: 78,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Container(
height: double.infinity,
child: GestureDetector(
onTap: () {
Navigator.of(context, rootNavigator: true).push(
MaterialPageRoute(
builder: (context) => ProfileDetailsScreen(),
),
);
},
child: Row(
children: <Widget>[
SizedBox(width: 24),
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Image(
image: NetworkImage(
arrayOfSentRequests.profilePictureUrl,
),
width: 48,
),
),
SizedBox(width: 10),
Expanded(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
arrayOfSentRequests.nameAndSurname,
style: TextStyle(
color: Colors.black,
fontFamily: 'Avenir',
fontWeight: FontWeight.w700,
fontSize: 18,
),
),
Text(
'11/11/2020', //arrayOfSentRequests.nameAndSurname
style: TextStyle(
color: Colors.grey,
fontFamily: 'Avenir',
fontWeight: FontWeight.w500,
fontSize: 15,
),
),
],
),
),
Container(
child: Text(
// (arrayOfSentRequests.lastMessage !=
// null)
// ? arrayOfSentRequests.lastMessage
// : 'Loading..',
(listOfLastMessages.isNotEmpty)
? listOfLastMessages[index]
.toString()
: 'Loading...',
maxLines: 2,
softWrap: true,
style: TextStyle(
color: Colors.black54,
fontFamily: 'Avenir',
fontSize: 15,
),
),
),
],
),
),
),
SizedBox(width: 10),
],
),
),
),
),
Container(
child: Center(
child: Icon(
Icons.keyboard_arrow_right,
size: 22,
color: Colors.black54,
),
),
),
SizedBox(width: 10),
],
),
),
),
),
),
);
}
}

Resources