Giter VIP home page Giter VIP logo

Comments (21)

demchenkoalex avatar demchenkoalex commented on August 18, 2024 6

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.

UsamaKarim avatar UsamaKarim commented on August 18, 2024 3

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.

holy-dev avatar holy-dev commented on August 18, 2024 2

I found this one! https://pub.dev/packages/paginate_firestore I think it could help.

from flutter_firebase_chat_core.

what2003 avatar what2003 commented on August 18, 2024 2

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.

demchenkoalex avatar demchenkoalex commented on August 18, 2024 1

@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.

demchenkoalex avatar demchenkoalex commented on August 18, 2024 1

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.

what2003 avatar what2003 commented on August 18, 2024 1

@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.

demchenkoalex avatar demchenkoalex commented on August 18, 2024

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.

SalahAdDin avatar SalahAdDin commented on August 18, 2024

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.

demchenkoalex avatar demchenkoalex commented on August 18, 2024

@SalahAdDin Chat UI - yes, Firebase - no, feel free to add.

from flutter_firebase_chat_core.

azazadev avatar azazadev commented on August 18, 2024

@demchenkoalex any news to support pagination to Firebase ?

from flutter_firebase_chat_core.

what2003 avatar what2003 commented on August 18, 2024

@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.
截屏2021-10-12 上午9 40 57

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.

SalahAdDin avatar SalahAdDin commented on August 18, 2024

@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. 截屏2021-10-12 上午9 40 57

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.

what2003 avatar what2003 commented on August 18, 2024

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.

azazadev avatar azazadev commented on August 18, 2024

@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. 截屏2021-10-12 上午9 40 57

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.

SalahAdDin avatar SalahAdDin commented on August 18, 2024

Thanks @SalahAdDin , can you please give complete example ?

@azazadev You have to ask to @what2003, he did it.

from flutter_firebase_chat_core.

azazadev avatar azazadev commented on August 18, 2024

Thanks @SalahAdDin , can you please give complete example ?

@azazadev You have to ask to @what2003, he did it.

sorry, question to @what2003 any chance to have complete example ?

from flutter_firebase_chat_core.

what2003 avatar what2003 commented on August 18, 2024

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.

alexrabin avatar alexrabin commented on August 18, 2024

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.

akshays-repo avatar akshays-repo commented on August 18, 2024

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.

SalahAdDin avatar SalahAdDin commented on August 18, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.