How to use a async function inside a ListView.builder? - flutter

Is there anyway to get a future when displaying a list?
I have list with two user id's ( one of them is the userlogged in, the other one is the user to chat with ).
my goal is to get and display the other users name in the chat.
the issue I am running into, is that you cant do async functions within the list
how can i fix this?
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
var otherUserName = await getOtherUsersName(job.userIdsArr);
;
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
}
}
I tried the following code as suggested but did not work::
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../../services/auth/auth_service.dart';
import '../../services/cloud/cloud_chat.dart';
import '../../services/cloud/cloud_storage_constants.dart';
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
}}

The simple and short answer is to use FutureBuilder which take future as named parameter and give you the result in builders parameters generally know as snapshot.
First of all wrap your list view with future builder :
FutureBuilder(
future: "you future funtion here",
builder: (context, snapshot) {
return ListView.builder(itemBuilder: itemBuilder);
}
)
now you can give future funtion , in your case it is
FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
And remember to use snapshot if conditions for loading and empty data
complete code
import 'package:flutter/material.dart';
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
}}
HopeFully It will help you.

Related

Flutter Isar stops working after hot restart

I started learning flutter isar yesterday and I couldn't love it more. I created a demo app with it and for some reason, it is not working as expected.
The app has two sections: Original(This contain the dummyData) and the Database(this contains data in the isar database).
When an item is starred in the original, it is added in the database and the icon is changed to filled_star. When the item is unstarred in the original section, it is expected to be removed from the database section and the icon is expected to change to star_outline. This is works fine.
However, when the app is hot-restarted, I am unable to unstar the items. Check the GIF below.
main.dart
import 'package:flutter/material.dart';
import 'package:isardemo/isar_files/course.dart';
import 'package:isardemo/isar_files/isar.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.blueGrey,
),
home: const MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final dummyData = [
Course()
..title = 'MTH 212'
..courseId = '1ab',
Course()
..title = 'STS 432'
..courseId = '2bc',
Course()
..title = 'SHS 555'
..courseId = '3de',
Course()
..title = 'HMM 999'
..courseId = '4fg',
Course()
..title = 'EEE 666'
..courseId = '5hi',
];
Future<void> onFavTap(IsarService courseData, Course course) async {
if (await courseData.isItemDuplicate(course)) {
await courseData.deleteCourse(course);
setState(() {});
debugPrint('${course.courseId} deleted');
} else {
await courseData.addCourse(course);
setState(() {});
debugPrint('${course.courseId} added');
}
}
final courseData = IsarService();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Isar'),
),
body: ListView(
padding: const EdgeInsets.all(20),
children: [
Center(
child: FutureBuilder(
initialData: courseData,
future: courseData.favoritesCount(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Text(
snapshot.data.toString(),
style:
const TextStyle(fontSize: 25, color: Colors.lightGreen),
);
} else {
return const LinearProgressIndicator();
}
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
courseData.cleanDb();
setState(() {});
},
child: const Text('Destroy Database')),
),
const Text('Original',
style: TextStyle(fontSize: 30, color: Colors.green)),
ListView.separated(
shrinkWrap: true,
separatorBuilder: (context, index) => const SizedBox(height: 5),
itemCount: dummyData.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
tileColor: Colors.blueGrey,
title: Text(dummyData[index].title),
trailing: IconButton(
icon: FutureBuilder(
// initialData: courseData.isItemDuplicate(dummyData[index]),
future: courseData.isItemDuplicate(dummyData[index]),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data) {
return const Icon(Icons.star);
} else {
return const Icon(Icons.star_border_outlined);
}
}
return const Icon(Icons.g_mobiledata,
color: Colors.green);
},
),
onPressed: () => onFavTap(courseData, dummyData[index])),
);
},
),
const SizedBox(height: 20),
const Text(
'database',
style: TextStyle(fontSize: 30, color: Colors.green),
),
FutureBuilder(
future: courseData.getAllCourses(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data![index].title),
trailing: InkWell(
onTap: () async {
await courseData
.deleteCourse(snapshot.data![index]);
setState(() {});
},
child: const Icon(Icons.star)),
);
},
);
} else {
return const Center(
child: LinearProgressIndicator(),
);
}
}),
],
),
);
}
}
course.dart
import 'package:isar/isar.dart';
part 'course.g.dart';
#Collection()
class Course {
Id id = Isar.autoIncrement;
late String courseId;
late String title;
late bool isFavorite = false; // new property
}
isar.dart
import 'package:path_provider/path_provider.dart';
import 'course.dart';
class IsarService {
late Future<Isar> _db;
IsarService() {
_db = openIsar();
}
Future<Isar> openIsar() async {
if (Isar.instanceNames.isEmpty) {
final directory = await getApplicationDocumentsDirectory();
return await Isar.open([CourseSchema],
inspector: true, directory: directory.path);
} else {
return await Future.value(Isar.getInstance());
}
}
Future<void> addCourse(Course course) async {
final isar = await _db;
await isar.writeTxn(() async {
await isar.courses.put(course);
});
}
Future<bool> isItemDuplicate(Course course) async {
final isar = await _db;
final count =
await isar.courses.filter().courseIdContains(course.courseId).count();
return count > 0;
}
Future<List<Course>> getAllCourses() async {
final isar = await _db;
return isar.courses.where().findAll();
}
Future<void> deleteCourse(Course course) async {
final isar = await _db;
await isar.writeTxn(() async {
await isar.courses.delete(course.id);
});
}
Future<String> favoritesCount() async {
final isar = await _db;
final count = await isar.courses.count();
return count.toString();
}
Future<void> cleanDb() async {
final isar = await _db;
await isar.writeTxn(() => isar.clear());
}
}
I tried downgrading the isar version but it didn't work.
I fixed it! Instead of auto-incrementing the id, I used the Course's id instead. But Id expects an integer so I had to convert the Course's id into an integer using the fastHash.
Learn more
course.dart
#Collection()
class Course {
late String id;
Id get courseId => fastHash(id);
late String title;
}
int fastHash(String string) {
var hash = 0xcbf29ce484222325;
var i = 0;
while (i < string.length) {
final codeUnit = string.codeUnitAt(i++);
hash ^= codeUnit >> 8;
hash *= 0x100000001b3;
hash ^= codeUnit & 0xFF;
hash *= 0x100000001b3;
}
return hash;
}

How do I get data from my firestore document as a variable and use that to direct the path my stream builder uses in flutter

The code below is what I am trying now. The page works does everything I need but now I need this database reference to use the loanuid, clientuid, and companyName to get to the right directory.
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('prosperitybank')
.doc('OHViYK8Zz6XfKGJsSXRL')
.collection('Project Information')
.snapshots()```
I need it from my collection.(userCreationRef).doc(loggedinuid) as shown in the picture. I can not figure out how to do this without the stream builders interfering any help would be greatly appreciated. I have tried to using this to help but it did not How can you nest StreamBuilders in Flutter?. I also tried looking at the documentation here https://firebase.flutter.dev/docs/firestore/usage/.
Picture of Document I need data fields from
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:photoloanupdated/screens/mains/viewproperties.dart';
import 'package:provider/provider.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
final FirebaseAuth auth = FirebaseAuth.instance;
final user = auth.currentUser;
final uid = user?.uid;
var users = FirebaseFirestore.instance.collection('userCreationRequests');
var companyname = "";
return Scaffold(
appBar: AppBar(
title: Text(companyname),
),
body:
FutureBuilder<DocumentSnapshot>(
future: users.doc(uid).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {
return Text("Document does not exist");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text("Full Name: ${data['companyName']} ${data['last_name']}");
}
return Text("loading");
},
);
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('prosperitybank')
.doc('OHViYK8Zz6XfKGJsSXRL')
.collection('Project Information')
.snapshots(), //key spot fV or email fix
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data?.docs.length,
itemBuilder: (BuildContext context, int index) {
QueryDocumentSnapshot<Object?>? documentSnapshot =
snapshot.data?.docs[index];
//for date/time DateTime mydateTime = documentSnapshot['created'].toDate();
return InkWell(
onTap: () {
Navigator.of(context)
.push(
MaterialPageRoute(
builder: (context) => ViewProperties(documentSnapshot,
snapshot.data?.docs[index].reference)),
)
.then((value) {
setState(() {});
});
},
child: Card(
child: Container(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${documentSnapshot!['address']}",
style: TextStyle(
fontSize: 24.0,
fontFamily: "lato",
fontWeight: FontWeight.bold,
color: Colors.black),
),
Container(
alignment: Alignment.centerRight,
child: Text(
"${documentSnapshot!['projectcomplete'].toString() + "% Complete"}",
// for mydateTime.toString(),
style: TextStyle(
fontSize: 17.0,
fontFamily: "lato",
color: Colors.black87),
),
)
],
),
),
),
),
);
},
);
} else {
return Center(
child: Text("Loading..."),
);
}
},
),
);
}
}
String uuid;
Future<List<Map<String, dynamic>>> _onQuery() {
Future<List<Map<String, dynamic>>> res;
if (uuid != null) {
res = future.get().then((v) => v.docs
.map((e) => e.data())
.where((e) =>
e['uuid'].toLowerCase().contains(uuid))
.toList());
} else {
res = future.get().then((v) => v.docs.map((e) => e.data()).toList());
}
setState(() {});
return res;
}
now you can use _onQuery as stream.

Need help retrieving authorized user information Flutter Firestore

I have implemented in my flutter application Authentication via Firebase by login and password.
I also connected to a Firestore table with user data.
I only need to show the authenticated user's data by their ID, which are assigned to the other data tables.
How to link e.g. Users id: 1 with Tasks User id:1 ?
home_page.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:loginui/read_data/get_user_name.dart';
class MyTaskPage extends StatefulWidget {
const MyTaskPage({Key? key}) : super(key: key);
#override
State<MyTaskPage> createState() => _MyTaskPageState();
}
class _MyTaskPageState extends State<MyTaskPage> {
final user = FirebaseAuth.instance.currentUser!;
// document IDs
List<String> docIDs = [];
// get docIDs
Future getDocId() async {
await FirebaseFirestore.instance
.collection('tasks')
.orderBy('name', descending: true)
// .where('age', isGreaterThan: 44)
.get()
.then((snapshot) => snapshot.docs.forEach((document) {
print(document.reference);
docIDs.add(document.id);
}));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple[200],
centerTitle: true,
actions: [
GestureDetector(
onTap: () {
setState(() {
FirebaseAuth.instance.signOut();
});
},
child: Icon(Icons.logout),
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: FutureBuilder(
future: getDocId(),
builder: (context, snapshot) {
return ListView.builder(
itemCount: docIDs.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListTile(
title: GetUserName(documentId: docIDs[index]),
tileColor: Colors.grey[200],
),
);
},
);
},
),
),
],
),
),
);
}
}
get_user_name.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName({required this.documentId});
#override
Widget build(BuildContext context) {
// get the collection
CollectionReference users = FirebaseFirestore.instance.collection('tasks');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text(
'${data['name']}',
overflow: TextOverflow.ellipsis,
softWrap: true,
);
}
return Text('Loading...');
}),
);
}
}
final _auth = FirebaseAuth.instance;
final _firestore = FirebaseFirestore.instance;
if (_auth.currentUser != null) {
// user is signed in
final uid = _auth.currentUser!.uid;
final userData = await _firestore.collection('users').doc(uid).get();
final taskData = await _firestore.collection('tasks').doc(uid).get();
// handle the data
}

Flutter fetch nested future

I have a method that fetches a PatientLog from SQLite.However, This PatientLog table mapped to an object with a class named PatientLog. Inside this PatientLog class, several other objects such as Speciality, AttendingPhysician, Course, etc. I need to map these PatienLog records to a local object. However, I have to use nested Futures. I need to retrieve the data from this nested Future. Think of Future of Future.
This is my fetch method
Future<List<Future<PatientLog>>> getForms() async {
Database db = await instance.getDatabase;
List<Map<String, dynamic>> forms =
await db.query(_tablePatientLog, orderBy: 'id DESC');
Institute? institute;
AttendingPhysician? attendingPhysician;
Speciality? speciality;
Course? course;
List<Future<PatientLog>> list = forms.map((myMap) async {
int? courseId = myMap['course_id'] as int?;
int? specialityId = myMap['speciality_id'] as int?;
int? attendingId = myMap['attending_id'] as int?;
int? instituteId = myMap['institute_id'] as int?;
if (courseId != null) {
await getCourse(courseId).then((value) => course=value);
}
if (attendingId != null) {
await getAttending(attendingId).then((value) => attendingPhysician=value);
}
if (specialityId != null) {
await getSpeciality(specialityId).then((value) => speciality=value);
}
if (instituteId != null) {
await getInstitute(instituteId).then((value) => institute=value);
}
return PatientLog.fromMap(
myMap, institute, course, attendingPhysician, speciality);
}).toList();
return list;
}
I need to display that information on a screen. I get an error type 'List<Future<PatientLog>>' is not a subtype of type 'Future<Object?>?'
class _DraftsState extends State<Drafts> {
final SQFLiteHelper _helper = SQFLiteHelper.instance;
#override
void initState() {
super.initState();
_refresh();
}
late List<Future<PatientLog>> fromDatabase;
Future<dynamic> _refresh() async {
await _helper.getForms().then((value) async{
setState(() {
fromDatabase = value;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _helper.getForms(),
builder: (BuildContext context,
AsyncSnapshot snapshot) {
if (snapshot.hasData && snapshot.data!.isEmpty) {
return Center(
child: Text(
"Henüz kaydedilmiş taslak bulunmamaktadır.",
textAlign: TextAlign.center,
style: TEXT_STYLE,
));
}
if (snapshot.hasError) {
return Center(
child: Text(
'Sanırım bir şeyler ters gitti.',
style: TEXT_STYLE,
));
}
if (snapshot.connectionState == ConnectionState.done) {
return RefreshIndicator(
backgroundColor: Colors.grey[700],
color: LIGHT_BUTTON_COLOR,
onRefresh: _refresh,
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics(),
),
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return FutureBuilder(
future: snapshot.data,
builder: (context,innerSnap) {
return Text(innerSnap.toString());/*CustomListTile(
formData: innerSnap.data[index],
index: index,
routeTo: 1,
isDeletable: true,
);*/
}
);
},
),
),
);
}
return const Center(
child: Text("Nothing")//spinkit,
);
}),
);
}
}

Null check operator used on null value

I need to grab a list of all messages in the database where the level is less than or equal to the user's current level. To do this I am attempting to use a nested streambuilder. First one pulls the user info, then I use the user level to make the second query. My problem is I get an error.
Null check operator used on null value
I do not understand this error. I checked firestore to see that there is data in the collection, and I also made sure to put the proper rules in place. I've tried several variations of this code and this is the only one so far that at least doesn't give me an error in the emulator. My emulator shows the appbar and the body is blank.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../screens/welcome_screen.dart';
class MessagesScreen extends StatefulWidget {
static const String id = 'messages_screen';
#override
_MessagesScreenState createState() => _MessagesScreenState();
}
class _MessagesScreenState extends State<MessagesScreen> {
final _firestore = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance;
User loggedInUser;
int _userCurrentLevel;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() {
try {
final user = _auth.currentUser;
if (user != null) {
loggedInUser = user;
}
} catch (e) {
print(e);
}
}
getMessages(AsyncSnapshot<QuerySnapshot> snapshot2) {
return snapshot2.data.docs
.map((doc) => new ListTile(title: Text(doc['from']), subtitle: Text(doc['text'])))
.toList();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Darker Slate'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.chat),
tooltip: 'Messages',
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.exit_to_app),
tooltip: 'Log Out',
onPressed: () {
_auth.signOut();
Navigator.pushNamed(context, WelcomeScreen.id);
},
),
],
),
body: StreamBuilder<DocumentSnapshot>(
stream: _firestore.collection('users')
.doc(_auth.currentUser.uid)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red[900],
),
);
}
_userCurrentLevel = snapshot.data['userlevel'];
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('messages')
.where('level', isLessThanOrEqualTo: _userCurrentLevel).snapshots(),
builder: (context, snapshot2) {
if (!snapshot2.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red[900],
),
);
}
return Column(
children: [
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot2.data.docs.length,
itemBuilder: (_, index) {
return new ListView(children: getMessages(snapshot2));
}),
],
);
}
);
}),
);
}
}