Comments (21)
So the pagination was added to the chat UI package, if there are volunteers to add pagination to Firebase we will be more than happy to accept a PR :)
from flutter_firebase_chat_core.
I tried to create pagination with firestore while taking inspiration from FilledStack's video about Flutter and Firestore real-time Pagination. The approach is not perfect but it's working fine for me.
"I tried it only with single-page chat room."
class MessagesService with ChangeNotifier {
late int currentIndex;
MessagesService();
final databaseService = sl.get<DatabaseService>();
///constants
static const _serverTime = 'metadata.createdAt';
// static const _createdAt = 'createdAt';
static const _resultLimit = 10;
bool _hasMoreItems = true;
bool _isLoading = false;
bool get hasMoreItems => _hasMoreItems;
bool get isLoading => _isLoading;
void _setLoading(bool value) {
_isLoading = value;
// notifyListeners();
}
///
DocumentSnapshot? _lastDocument;
final List<List<types.Message>> _allMessage = [];
final _streamController = StreamController<List<types.Message>>.broadcast();
Stream<List<types.Message>> messageStream() {
requestData();
return _streamController.stream;
}
void requestData() {
if (_isLoading) return;
_setLoading(true);
Query<types.Message> query;
/// First Query to get `_resultLimit` messages
query = databaseService
.messages()
// .where(_serverTime, isGreaterThanOrEqualTo: timeStamp)
.orderBy(_serverTime, descending: true)
.limit(_resultLimit);
currentIndex = _allMessage.length;
/// If User scrolls to upwards
if (_lastDocument != null) {
if (_hasMoreItems) {
query = query.startAfterDocument(_lastDocument!);
query.snapshots().listen((snapshot) => _createList(snapshot, false));
return;
}
}
query.snapshots().listen((snapshot) => _createList(snapshot, true));
}
void _createList(QuerySnapshot<types.Message> snapshot, bool isNewMessage) {
_setLoading(true);
if (isNewMessage) {
// I'm using a hack here, this hack fixes a problem when user scroll upwards and a new mesasge came, the message doesn't appear.
currentIndex = 0;
}
print('Current Index $currentIndex');
print('All Message Length ${_allMessage.length}');
final tempList = snapshot.docs.map((e) => e.data()).toList();
final pageExists = currentIndex < _allMessage.length;
if (pageExists) {
_allMessage[currentIndex] = tempList;
} else {
_allMessage.add(tempList);
}
final foldedList = _allMessage.fold<List<types.Message>>(<types.Message>[],
(initialValue, element) => initialValue..addAll(element));
_streamController.add(foldedList);
if (currentIndex == _allMessage.length - 1) {
_lastDocument = snapshot.docs.last;
}
// Determine if there's more Messages to request
_hasMoreItems = tempList.length == _resultLimit;
_setLoading(false);
}
@override
void dispose() {
super.dispose();
_streamController.close();
}
}
from flutter_firebase_chat_core.
I found this one! https://pub.dev/packages/paginate_firestore I think it could help.
from flutter_firebase_chat_core.
It is my pleasure to contribute a little, example, made some changes base on @demchenkoalex flutter_firebase_chat_core example, hope it helps. My google-services.json is in it, so it can be directly built on android(not IOS), please ignore some Chinese characters in chat room and custom messages which appears as blank in this example. @azazadev
from flutter_firebase_chat_core.
@azazadev this is the lowest priority we have, unless someone else do it, don't expect it this year. This package was designed as an option to quickly build an MVP and not a full-blown fully-featured chat backend.
from flutter_firebase_chat_core.
Hey @what2003 thanks for the kind words and an update that this is actually not that hard as I assume it would :D Definitely share an example if you will have a chance, in the meantime I will try to follow you leads to see if I could make it work too.
from flutter_firebase_chat_core.
@akshays-repo @SalahAdDin My example included my firebase account info which is no longer in use, so please refer to my code snippet, else in my example just insignificant.
from flutter_firebase_chat_core.
Hi @mibrah42. Right now we are working on animations and pagination in the chat UI, but as of right now we don't have plans to add pagination to Firebase's messages stream. We are always open to PRs though :)
from flutter_firebase_chat_core.
So the pagination was added to the chat UI package, if there are volunteers to add pagination to Firebase we will be more than happy to accept a PR :)
Does the documentation includes this new feature?
from flutter_firebase_chat_core.
@SalahAdDin Chat UI - yes, Firebase - no, feel free to add.
from flutter_firebase_chat_core.
@demchenkoalex any news to support pagination to Firebase ?
from flutter_firebase_chat_core.
@demchenkoalex First thank you for the wonderful work!
I try to add this feature in my project, reference official document and video.
Here is my solution , you have done the most part of work in this, the rest is is easy piece in your package, big difference for the reads number which relate to the cost in real online project.
Thank you again, excuse my bluntness and poor drawing skill.
Stream part
Stream<List<types.Message>> messages(types.Room room, [doc]) {
return FirebaseFirestore.instance
.collection('${config.roomsCollectionName}/${room.id}/messages')
.orderBy('createdAt', descending: true)
.endBeforeDocument(doc)
.snapshots()
page part
Future fetchMessages(types.Room room,
{var docWhere, int pageSize = 5}) async {
List<QueryDocumentSnapshot<Map<String, dynamic>>>? quary;
if (docWhere == null) {
//first bunch of messages, page1
await FirebaseFirestore.instance
.collection('${config.roomsCollectionName}/${room.id}/messages')
.orderBy('createdAt', descending: true)
.limit(pageSize)
.get();
} else {
//next page messages
await FirebaseFirestore.instance
.collection('${config.roomsCollectionName}/${room.id}/messages')
.orderBy('createdAt', descending: true)
.startAfterDocument(docWhere)
.limit(pageSize)
.get();
}
return quary;
}
from flutter_firebase_chat_core.
@demchenkoalex First thank you for the wonderful work! I try to add this feature in my project, reference official document and video. Here is my solution , you have done the most part of work in this, the rest is is easy piece in your package, big difference for the reads number which relate to the cost in real online project. Thank you again, excuse my bluntness and poor drawing skill.
Stream part
Stream<List<types.Message>> messages(types.Room room, [doc]) { return FirebaseFirestore.instance .collection('${config.roomsCollectionName}/${room.id}/messages') .orderBy('createdAt', descending: true) .endBeforeDocument(doc) .snapshots()
page part
Future fetchMessages(types.Room room, {var docWhere, int pageSize = 5}) async { List<QueryDocumentSnapshot<Map<String, dynamic>>>? quary; if (docWhere == null) { //first bunch of messages, page1 await FirebaseFirestore.instance .collection('${config.roomsCollectionName}/${room.id}/messages') .orderBy('createdAt', descending: true) .limit(pageSize) .get(); } else { //next page messages await FirebaseFirestore.instance .collection('${config.roomsCollectionName}/${room.id}/messages') .orderBy('createdAt', descending: true) .startAfterDocument(docWhere) .limit(pageSize) .get(); } return quary; }
What is docWhere
for?
from flutter_firebase_chat_core.
docWhere is just a name I made for my project, it is a doc which located at the last of List docs in page1, use it to tell firestore where next bunch of docs start.
from flutter_firebase_chat_core.
@demchenkoalex First thank you for the wonderful work! I try to add this feature in my project, reference official document and video. Here is my solution , you have done the most part of work in this, the rest is is easy piece in your package, big difference for the reads number which relate to the cost in real online project. Thank you again, excuse my bluntness and poor drawing skill.
Stream part
Stream<List<types.Message>> messages(types.Room room, [doc]) { return FirebaseFirestore.instance .collection('${config.roomsCollectionName}/${room.id}/messages') .orderBy('createdAt', descending: true) .endBeforeDocument(doc) .snapshots()
page part
Future fetchMessages(types.Room room, {var docWhere, int pageSize = 5}) async { List<QueryDocumentSnapshot<Map<String, dynamic>>>? quary; if (docWhere == null) { //first bunch of messages, page1 await FirebaseFirestore.instance .collection('${config.roomsCollectionName}/${room.id}/messages') .orderBy('createdAt', descending: true) .limit(pageSize) .get(); } else { //next page messages await FirebaseFirestore.instance .collection('${config.roomsCollectionName}/${room.id}/messages') .orderBy('createdAt', descending: true) .startAfterDocument(docWhere) .limit(pageSize) .get(); } return quary; }
Thanks @SalahAdDin , can you please give complete example ?
from flutter_firebase_chat_core.
Thanks @SalahAdDin , can you please give complete example ?
@azazadev You have to ask to @what2003, he did it.
from flutter_firebase_chat_core.
Thanks @SalahAdDin , can you please give complete example ?
sorry, question to @what2003 any chance to have complete example ?
from flutter_firebase_chat_core.
My project with a lot custom feather is too complex to show, maybe later when I finish my project and organize my code to set an example. Of course the best way is waiting for @demchenkoalex to update. Again I shall express my gratitude for the brilliant work @demchenkoalex team did!
from flutter_firebase_chat_core.
I got pagination to work on my end by using FirestoreQueryBuilder from flutter fire ui package.
So I have this:
FirestoreQueryBuilder(
query: FirebaseFirestore.instance
.collection('rooms/${widget.room.id}/messages')
.orderBy('createdAt', descending: true),
builder: (context, snapshot, c) {
if (snapshot.isFetching) {
return const CircularProgressIndicator();
}
...
return Chat(
onEndReached: () {
snapshot.fetchMore();
return Future.value();
},
messages: snapshot.docs.map((e) {
final data = e.data();
if (data != null) {
var map = data as Map<dynamic, dynamic>;
var castedMap = map.cast<String, dynamic>();
final author = widget.room.users.firstWhere(
(u) => u.id == castedMap['authorId'],
orElse: () =>
types.User(id: castedMap['authorId'] as String),
);
data['author'] = author.toJson();
data['createdAt'] =
data['createdAt']?.millisecondsSinceEpoch;
data['id'] = e.id;
data['updatedAt'] =
data['updatedAt']?.millisecondsSinceEpoch;
return types.Message.fromJson(castedMap);
}
return types.Message.fromJson({});
}).toList(),
....
);
}
from flutter_firebase_chat_core.
It is my pleasure to contribute a little, example, made some changes base on @demchenkoalex flutter_firebase_chat_core example, hope it helps. My google-services.json is in it, so it can be directly built on android(not IOS), please ignore some Chinese characters in chat room and custom messages which appears as blank in this example. @azazadev
hey. your example is private I think
from flutter_firebase_chat_core.
It is my pleasure to contribute a little, example, made some changes base on @demchenkoalex flutter_firebase_chat_core example, hope it helps. My google-services.json is in it, so it can be directly built on android(not IOS), please ignore some Chinese characters in chat room and custom messages which appears as blank in this example. @azazadev
hey. your example is private I think
Or it was deleted.
from flutter_firebase_chat_core.
Related Issues (20)
- Chat application hangs once we continuously send messages HOT 2
- Only call createRoom when user sends message? HOT 3
- Store message count in room data for easy filtering in Firestore HOT 1
- How can I test the example by making several users? HOT 1
- Block or Unblock a user HOT 1
- Show all room from a specific user id
- testing on a firebase emulator?
- Limit first initial messages then append new messages
- Process for creating group room and allowing others to join unclear. HOT 2
- Add a firebase extension for the rules and cloud functions
- Add option to mixin the chat user to an existing user class HOT 1
- Start new chat messages at the top of the screen? HOT 2
- Set custom location for Firebase Storage so We can setup our own security rules. HOT 2
- How to send SystemMessage? HOT 2
- How to create room for a specific user without using ```FirebaseChatCore.instance.users()``` and ```StreamBuilder()``` HOT 6
- createGroupRoom with specific metadata HOT 1
- [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value. HOT 5
- Rooms list. How is it supposed to look?
- any documentation on how to create the structure the firebase database ? HOT 3
- Where to define App Name HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flutter_firebase_chat_core.