Giter Site home page Giter Site logo

furkansarihan / firestore_collection Goto Github PK

View Code? Open in Web Editor NEW
9.0 9.0 5.0 593 KB

Firestore extension with cache-first pagination and stream builder support.

License: MIT License

Dart 91.33% Kotlin 0.56% Ruby 6.11% Swift 1.82% Objective-C 0.17%

firestore_collection's People

Contributors

azazadev avatar furkansarihan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

firestore_collection's Issues

collectionListener when multi query feature enable

Hi @furkansarihan

in case of live data enable and multi query feature enable the Listener will start for query instead of queryList

should we loop on queryList and create multiple Listener ? Like :

 if (queryList?.isEmpty ?? true) {
      collectionListener(query);
      return;
    }
    for (var q in queryList) {
     collectionListener(q);
    }

Thanks

displayCompare not work as expected

Hi @furkansarihan

I'm using firestore_collection on some views with queryOrder based on timestamp and it's work as expected
Now I'm trying to extend this package to other view, this new view contain the posts order by likeCount ( most liked posts should be on the top of List ), but this is not work as expected, I have try to override displayCompare and compare post timestamp if likeCount field is the same for 2 documents

FirestoreCollection fireCollection = FirestoreCollection(
  collection: FirebaseFirestore.instance.collection('posts'),
  initializeOnStart: true,
  // first page will fetched immediately
  offset: 15,
  // page size
  serverOnly: true,
  // cache first
  live: true,
  // notifies to newest documents
  query: FirebaseFirestore.instance.collection('posts'),
  queryOrder:
      QueryOrder(orderField: 'likeCount', displayCompare: comparePosts),
);

How to reproduce :

  1. import the main file attached
  2. add some posts ( LikeCount = 0 for all posts added ) --> new posts added
  3. restart the app
  4. add new posts ---> nothing happened --> the new post is not added

Can you please check why new documents are not added

NOTE : I'm using the last version 0.0.4

main file to reproduce :


import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firestore_collection/firestore_collection.dart';
import 'package:flutter/cupertino.dart';
import "package:flutter/material.dart";
import 'package:flutter_icons/flutter_icons.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(),
      title: 'My Flutter App',
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _HomeState();
  }
}

class _HomeState extends State<Home> {
  int _currentIndex = 0;
  final List<Widget> _children = [HomePage(), SearchPage(), ProfilePage()];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _children[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        onTap: onTabTapped,
        currentIndex: _currentIndex,
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Home'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            title: Text('Search'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            title: Text('Profile'),
          ),
        ],
      ),
    );
  }

  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
}

class HomePage extends StatelessWidget {
  HomePage();

  @override
  Widget build(BuildContext context) {
    FirestoreCollection fireCollection = FirestoreCollection(
      collection: FirebaseFirestore.instance.collection('posts'),
      initializeOnStart: true,
      // first page will fetched immediately
      offset: 15,
      // page size
      serverOnly: true,
      // cache first
      live: true,
      // notifies to newest documents
      query: FirebaseFirestore.instance.collection('posts'),
      queryOrder:
          QueryOrder(orderField: 'likeCount', displayCompare: comparePosts),
    );

    int count = 0;
    return Scaffold(
      backgroundColor: Colors.white,
      // No appbar provided to the Scaffold, only a body with a
      // CustomScrollView.
      body: CustomScrollView(
        physics: const BouncingScrollPhysics(
            parent: AlwaysScrollableScrollPhysics()),
        slivers: <Widget>[
          // Add the app bar to the CustomScrollView.
          SliverAppBar(
            actions: <Widget>[
              IconButton(
                iconSize: 30.0,
                icon: const Icon(CupertinoIcons.plus),
                onPressed: () async {
                  count++;
                  await FirebaseFirestore.instance.collection('posts').add({
                    'fullName': 'user' + count.toString(),
                    'likeCount': 0,
                    'userPhotoUrl':
                        'https://static.thenounproject.com/png/15724-200.png',
                    'timestamp': Timestamp.now()
                  });
                },
              ),
            ],
            // Provide a standard title.
            expandedHeight: 100.0,
            floating: true,
          ),
          StreamBuilder(
            stream: fireCollection.stream,
            builder: (BuildContext context,
                AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
              return SliverList(
                delegate: SliverChildBuilderDelegate(
                  (context, index) {
                    return ListTile(
                        leading: InkWell(
                          onTap: () => {print('tap...')},
                          child: Ink(
                            height: 50,
                            width: 50,
                            child: CachedNetworkImage(
                              imageUrl:
                                  snapshot.data[index].data()['userPhotoUrl'],
                              imageBuilder: (context, imageProvider) =>
                                  Container(
                                width: 50,
                                height: 50,
                                decoration: BoxDecoration(
                                  shape: BoxShape.circle,
                                  image: DecorationImage(
                                      image: imageProvider, fit: BoxFit.cover),
                                ),
                              ),
                              placeholder: (context, url) =>
                                  CircularProgressIndicator(),
                              errorWidget: (context, url, error) => Icon(
                                FontAwesome5.user,
                                color: Colors.black12,
                              ),
                            ),
                          ),
                        ),
                        title: Text(snapshot.data[index].data()['fullName']));
                  },
                  childCount: snapshot.hasData ? snapshot.data.length : 0,
                ),
              );
            },
          ),
        ],
      ),
    );
  }

  int comparePosts(DocumentSnapshot a, DocumentSnapshot b) {
    dynamic fieldA = a?.data()["likeCount"];
    dynamic fieldB = b?.data()["likeCount"];
    if (fieldA == null) {
      return 1;
    }
    if (fieldB == null) {
      return -1;
    }
    int res = fieldB.compareTo(fieldA);
    print('compare likes res : ' + res.toString());
    if (res == 0) {
      dynamic fieldA = a?.data()["timestamp"];
      dynamic fieldB = b?.data()["timestamp"];

      if (fieldA == null) {
        return 1;
      }
      if (fieldB == null) {
        return -1;
      }
      int res = fieldB.compareTo(fieldA);
      print('compare timestamp res : ' + res.toString());
      return res;
    } else {
      // Descending compare
      return res;
    }
  }
}

class SearchPage extends StatelessWidget {
  SearchPage();

  @override
  Widget build(BuildContext context) {
    int count = 0;
    return Scaffold(
      backgroundColor: Colors.white,
      // No appbar provided to the Scaffold, only a body with a
      // CustomScrollView.
      body: Container(),
    );
  }
}

class ProfilePage extends StatelessWidget {
  ProfilePage();

  @override
  Widget build(BuildContext context) {
    int count = 0;
    return Scaffold(
      backgroundColor: Colors.white,
      // No appbar provided to the Scaffold, only a body with a
      // CustomScrollView.
      body: Container(),
    );
  }
}

Latest Dependencies - Cloud Firestore

This seems like a great package! Is there any chance firestore_collection will be updated to support the latest big update of Cloud Firestore 1.X.X (which at the moment is 1.0.4)? As you may know, this update of Cloud Firestore was substantial and so to use this package, one must downgrade and use the previous nomenclature and design patterns which will break much functionality in other parts of people's projects for the future. And related, is there a possibility that this package will be migrated to null safety? Thank you for this wonderful addition to the Flutter ecosystem and please let me know if these upgrades/migrations will occur anytime soon as I really would like to incorporate this into a project!

query order descending

Hi @furkansarihan

do you know why Ascending order is for TODO ? any reason ?

class QueryOrder {
  QueryOrder({
    required this.orderField,
    this.lastValue,
    // TODO: Ascending query support
    // this.descending = true,
    this.displayCompare,
  });

  final String orderField;
  final dynamic lastValue;
  final bool descending = true;
  final int Function(DocumentSnapshot, DocumentSnapshot)? displayCompare;
}

Docs are not removed from stream

Hi,

Thanks a lot for making this package, it's awesome. It is working as expected for my Firestore collection StreamBuilder in terms of pagination and adding new docs. However, when I remove a document, the stream doesn't trigger and don't update the StreamBuilder. I have two pages: one is the list of docs where I am using the StreamBuilder, and the second page is the doc detail screen where I can remove it, by using a button. Any idea how can I trigger the StreamBuilder update on docs removal? I also checked it with just a traditional Stream QuerySnapshot, and it is working as expected, but cannot get it working with the FirestoreCollection package. Appreciate your help on this. Thanks.

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.