firestore_ui 1.7.2

firestore_ui #

pub package

This project started as a Pull Request to the official cloud_firestore plugin, but unfortunately they are still polishing the main features and this had to be postponed; it's based on firebase_database's version.

But fear not, my fellow Cloud Firestore users, this is a package that extracted the main code from that PR and now it's available to use!

How to use #

All the examples below are from the actual example folder, please run that to see how it behaves!

List #

Just set it up as you would with a ListView.builder:

FirestoreAnimatedList(
    query: query,
    itemBuilder: (
        BuildContext context,
        DocumentSnapshot snapshot,
        Animation<double> animation,
        int index,
    ) => FadeTransition(
            opacity: animation,
            child: MessageListTile(
            index: index,
            document: snapshot,
            onTap: _removeMessage,
        ),
    ),
);

Grid #

Just set it up as you would with a GridView.count, alongside the necessary crossAxisCount, all the other parameters from the SliverGridDelegateWithFixedCrossAxisCount are also available:

FirestoreAnimatedGrid(
    query: query,
    crossAxisCount: 2,
    mainAxisSpacing: 4.0,
    childAspectRatio: 1.0,
    crossAxisSpacing: 4.0,
    itemBuilder: (
        BuildContext context,
        DocumentSnapshot snapshot,
        Animation<double> animation,
        int index,
    ) => FadeTransition(
        opacity: animation,
        child: MessageGridTile(
            index: index,
            document: snapshot,
            onTap: _removeMessage,
        ),
    ),
);

Staggered #

Just set it up as you would with a StaggeredGridView.countBuilder, alongside the necessary crossAxisCount and the staggeredTileBuilder:

FirestoreAnimatedStaggered(
    query: query,
    staggeredTileBuilder: (int index, DocumentSnapshot snapshot) => StaggeredTile.count(2, index.isEven ? 2 : 1),
    crossAxisCount: 4,
    mainAxisSpacing: 4.0,
    crossAxisSpacing: 4.0,
    itemBuilder: (
        BuildContext context,
        DocumentSnapshot snapshot,
        Animation<double> animation,
        int index,
    ) => FadeTransition(
        opacity: animation,
        child: MessageGridTile(
            index: index,
            document: snapshot,
            onTap: _removeMessage,
        ),
    ),
);

Special thanks to @letsar for the flutter_staggered_grid_view package! Without it, this part wouldn't be available; please check out the library for more info on how it works!

[1.7.2] - 2019-09-05

  • Added FirestoreAnimatedGrid and FirestoreAnimatedStaggered!
  • Updated firebase_core to 0.4.0+9
  • Updated cloud_firestore to 0.12.9+3
  • Added flutter_staggered_grid_view on 0.3.0
  • Updated StaggeredTileBuilder to also have an instance of the referenced DocumentSnapshot
  • Minor changes to README.md!

[1.6.0] - 2019-06-04

  • Updates to the filter mechanism, it would hide items due to an index mismanagement
  • Updated cloud_firestore to 0.12.2

[1.5.0] - 2019-05-09

  • Added filter parameter that takes out data if it returns true for that DocumentSnapshot
  • Updated cloud_firestore to 0.12.0

[1.4.0] - 2019-05-09

  • Changed dependency requirements

[1.3.0] - 2019-04-30

  • Added onLoaded method for when you need to interact directly with the QuerySnapshot that came from the stream
  • Bump cloud_firestore dependency version to 0.10.0

[1.2.0] - 2019-02-08

  • Bump cloud_firestore dependency version to 0.9.0

[1.1.1] - 2019-01-14

  • Updated setState calls, should be faster to show values

[1.1.0] - 2019-01-03

  • Added onLoaded callback to FirestoreList
  • Fixed flashing of emptyChild when setted
  • Minor general fixes, better debugging if debug is set true

[1.0.1] - 2018-10-09

  • Fixed some errors on the README and package description

[1.0.0] - 2018-10-09

example/lib/main.dart

// Copyright 2017, the Chromium project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';

import 'package:firebase_core/firebase_core.dart'
    show FirebaseApp, FirebaseOptions;
import 'package:firestore_ui/firestore_ui.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

final String title = 'firestore_ui example';

Future<void> main() async {
  final FirebaseApp app = await FirebaseApp.configure(
    name: 'test',
    options: const FirebaseOptions(
      googleAppID: '1:79601577497:ios:5f2bcc6ba8cecddd',
      gcmSenderID: '79601577497',
      apiKey: 'AIzaSyArgmRGfB5kiQT6CunAOmKRVKEsxKmy6YI-G72PVU',
      projectID: 'flutter-firestore',
    ),
  );
  final Firestore firestore = Firestore(app: app);

  runApp(MaterialApp(title: title, home: MyHomePage(firestore: firestore)));
}

class MessageListTile extends StatelessWidget {
  final int index;
  final DocumentSnapshot document;
  final Function(DocumentSnapshot) onTap;

  const MessageListTile({
    Key key,
    this.index,
    this.document,
    this.onTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(
          document != null ? "${document['message']}" : 'No message retrieved'),
      subtitle: Text('Message ${this.index + 1}'),
      onTap: () => onTap(this.document),
    );
  }
}

class MessageGridTile extends StatelessWidget {
  final int index;
  final DocumentSnapshot document;
  final Function(DocumentSnapshot) onTap;

  const MessageGridTile({
    Key key,
    this.index,
    this.document,
    this.onTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () => onTap?.call(document),
      child: Container(
        color: Colors.green,
        child: Center(
          child: CircleAvatar(
            backgroundColor: Colors.white,
            child: Text('${this.index + 1}'),
          ),
        ),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final Firestore firestore;

  MyHomePage({Key key, this.firestore}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _currentIndex = 1;

  CollectionReference get messages => widget.firestore.collection('messages');

  Future<void> _addMessage() async =>
      await messages.document().setData(<String, dynamic>{
        'message': 'Hello world!',
      });

  Future<void> _removeMessage(DocumentSnapshot snapshot) async =>
      await widget.firestore.runTransaction((transaction) async {
        await transaction.delete(snapshot.reference).catchError(
            (exception, stacktrace) =>
                print("Couldn't remove item: $exception"));
      });

  void _updateIndex(int value) {
    if (mounted) setState(() => _currentIndex = value);
  }

  Stream<QuerySnapshot> get query =>
      widget.firestore.collection('messages').snapshots();

  @override
  Widget build(BuildContext context) {
    Widget body;

    switch (_currentIndex) {
      case 0:
        body = FirestoreAnimatedList(
          key: ValueKey("list"),
          query: query,
          onLoaded: (snapshot) =>
              print("Received on list: ${snapshot.documents.length}"),
          itemBuilder: (
            BuildContext context,
            DocumentSnapshot snapshot,
            Animation<double> animation,
            int index,
          ) =>
              FadeTransition(
            opacity: animation,
            child: MessageListTile(
              index: index,
              document: snapshot,
              onTap: _removeMessage,
            ),
          ),
        );
        break;
      case 1:
        body = FirestoreAnimatedGrid(
          key: ValueKey("grid"),
          query: query,
          onLoaded: (snapshot) =>
              print("Received on grid: ${snapshot.documents.length}"),
          crossAxisCount: 2,
          itemBuilder: (
            BuildContext context,
            DocumentSnapshot snapshot,
            Animation<double> animation,
            int index,
          ) {
            return FadeTransition(
              opacity: animation,
              child: MessageGridTile(
                index: index,
                document: snapshot,
                onTap: _removeMessage,
              ),
            );
          },
        );
        break;
      case 2:
        body = FirestoreAnimatedStaggered(
          key: ValueKey("staggered"),
          onLoaded: (snapshot) =>
              print("Received on staggered: ${snapshot.documents.length}"),
          staggeredTileBuilder: (int index, DocumentSnapshot snapshot) =>
              StaggeredTile.count(2, index.isEven ? 2 : 1),
          crossAxisCount: 4,
          query: query,
          itemBuilder: (
            BuildContext context,
            DocumentSnapshot snapshot,
            Animation<double> animation,
            int index,
          ) {
            return FadeTransition(
              opacity: animation,
              child: MessageGridTile(
                index: index,
                document: snapshot,
                onTap: _removeMessage,
              ),
            );
          },
        );
        break;
    }

    return Scaffold(
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: _updateIndex,
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.filter_1),
            title: Text("List"),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.filter_2),
            title: Text("Grid"),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.filter_3),
            title: Text("Staggered"),
          ),
        ],
      ),
      appBar: AppBar(
        title: Text(title),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addMessage,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
      body: body,
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  firestore_ui: ^1.7.2

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:firestore_ui/firestore_ui.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
94
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
95
Learn more about scoring.

We analyzed this package on Sep 20, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.5.0
  • pana: 0.12.21
  • Flutter: 1.9.1+hotfix.2

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Maintenance suggestions

The package description is too short. (-10 points)

Add more detail to the description field of pubspec.yaml. Use 60 to 180 characters to describe the package, what it does, and its target use case.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0-dev.68.0 <3.0.0
cloud_firestore ^0.12.9+3 0.12.9+4
firebase_core ^0.4.0+9 0.4.0+9
flutter 0.0.0
flutter_staggered_grid_view ^0.3.0 0.3.0
meta ^1.1.6 1.1.7
Transitive dependencies
collection 1.14.11 1.14.12
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test