Skip to content

Commit 1654254

Browse files
committed
Initial Public Release
0 parents  commit 1654254

18 files changed

+1283
-0
lines changed

.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.buildlog/
9+
.history
10+
.svn/
11+
migrate_working_dir/
12+
13+
# IntelliJ related
14+
*.iml
15+
*.ipr
16+
*.iws
17+
.idea/
18+
19+
# The .vscode folder contains launch configuration and tasks you configure in
20+
# VS Code which you may wish to be included in version control, so this line
21+
# is commented out by default.
22+
#.vscode/
23+
24+
# Flutter/Dart/Pub related
25+
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
26+
/pubspec.lock
27+
**/doc/api/
28+
.dart_tool/
29+
.packages
30+
build/
31+
.flutter-plugins*

.metadata

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: cd41fdd495f6944ecd3506c21e94c6567b073278
8+
channel: stable
9+
10+
project_type: package

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## [1.0.0] 2022-07-08
2+
3+
- Initial Public Release
4+
- Supports `Firestore` and `Realtime Database` pagination.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 OutdatedGuy
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Firebase Pagination
2+
3+
A simple and effective way to **Paginate** Firebase related data.
4+
5+
[![pub package](https://img.shields.io/pub/v/firebase_pagination.svg?color=blueviolet)](https://pub.dev/packages/firebase_pagination)
6+
[![GitHub](https://img.shields.io/github/license/OutdatedGuy/firebase_pagination.svg?color=purple)](https://pub.dev/packages/firebase_pagination/license)
7+
[![style: very good analysis](https://img.shields.io/badge/style-very_good_analysis-B22C89.svg)](https://pub.dev/packages/very_good_analysis)
8+
9+
[![GitHub issues](https://img.shields.io/github/issues/OutdatedGuy/firebase_pagination.svg)](https://github.com/OutdatedGuy/firebase_pagination/issues)
10+
[![GitHub issues](https://img.shields.io/github/issues-pr/OutdatedGuy/firebase_pagination.svg)](https://github.com/OutdatedGuy/firebase_pagination/pulls)
11+
12+
<hr />
13+
14+
[Video Demo](https://user-images.githubusercontent.com/74326345/178007676-fe049a56-0b0b-4f58-bc2e-f21851e89e32.mp4)
15+
16+
## Features
17+
18+
- `FirestorePagination` to simplify paginating firestore collections.
19+
- `RealtimeDBPagination` to simplify paginating realtime database nodes.
20+
- Get live updates when new data is added using `isLive` property.
21+
- Get realtime changes on already loaded data.
22+
23+
## Getting started
24+
25+
#### Add to Dependencies
26+
27+
```yaml
28+
firebase_pagination: ^1.0.0
29+
```
30+
31+
#### Import the package
32+
33+
```dart
34+
import 'package:firebase_pagination/firebase_pagination.dart';
35+
```
36+
37+
## Usage
38+
39+
#### Simplest Firestore Pagination
40+
41+
```dart
42+
FirestorePagination(
43+
query: FirebaseFirestore.instance.collection('scores').orderBy('score'),
44+
itemBuilder: (context, documentSnapshot, index) {
45+
final data = documentSnapshot.data() as Map<String, dynamic>;
46+
47+
// Do something cool with the data
48+
},
49+
),
50+
```
51+
52+
#### Simplest Firebase Realtime Database Pagination
53+
54+
```dart
55+
RealtimeDBPagination(
56+
query: FirebaseDatabase.instance.ref().child('scores').orderByChild('score'),
57+
itemBuilder: (context, dataSnapshot, index) {
58+
final data = dataSnapshot.value as Map<String, dynamic>;
59+
60+
// Do something cool with the data
61+
},
62+
),
63+
```
64+
65+
> For more examples, see the [examples](https://pub.dev/packages/firebase_pagination/example) section.
66+
67+
## How it Works
68+
69+
- A _data listener_ is added to the query with the given limit.
70+
- Every time the user scrolls to the bottom of the list, the limit is increased.
71+
- If there are any changes for the loaded data, it will be automatically updated.
72+
- If `isLive` is true, a _live listener_ is added to fetch data before the first load. (i.e. Newly added data will be automatically loaded)
73+
- When new data is added, the _data listener_ will be removed and a new _data listener_ will be added with the new limit.
74+
- Also the _live listener_ will be removed and a new _live listener_ will be added.
75+
76+
## Efficiency & Performance
77+
78+
- Both `FirestorePagination` and `RealtimeDBPagination` uses maximum of two `stream listeners` to fetch data.
79+
- Hence it is **performant** and uses **minimum amount of resources**.
80+
- The listeners are automatically removed when the widget is removed from the widget tree.
81+
- For fetching data, the widgets uses [this hack](https://stackoverflow.com/a/70645473) to minimize the number of reads from the database.
82+
83+
## Description
84+
85+
| Property | Description | Type | Default |
86+
| :----------------: | :--------------------------------------------------------------------: | :------------------: | :-----------------------------: |
87+
| `query` | **The query to use to fetch data from Firestore / Realtime Database.** | _Query_ | - |
88+
| `itemBuilder` | **The builder to use to build the items in the list.** | _Function_ | - |
89+
| `separatorBuilder` | **The builder to use to render the separator.** | _Function_ | `separatorBuilder (package fn)` |
90+
| `limit` | **The number of items to fetch from Database at once.** | _int_ | `10` |
91+
| `viewType` | **The type of view to use for the list.** | _ViewType_ | `ViewType.list` |
92+
| `isLive` | **Whether to fetch newly added items as they are added to Database.** | _bool_ | `false` |
93+
| `gridDelegate` | **The delegate to use for the GridView.** | _SliverGridDelegate_ | `crossAxisCount: 2` |
94+
| `wrapOptions` | **The Wrap widget properties to use.** | _WrapOptions_ | `WrapOptions()` |
95+
| `onEmpty` | **The widget to use when data is empty.** | _Widget_ | `EmptyScreen()` |
96+
| `bottomLoader` | **The widget to use when more data is loading.** | _Widget_ | `BottomLoader()` |
97+
| `initialLoader` | **The widget to use when data is loading initially.** | _Widget_ | `InitialLoader()` |
98+
| `scrollDirection` | **The scrolling direction of the ScrollView.** | _Axis_ | `false` |
99+
| `reverse` | **Whether the ScrollView scrolls in the reading direction.** | _bool_ | `false` |
100+
| `shrinkWrap` | **Should the ScrollView be shrink-wrapped.** | _bool_ | `false` |
101+
| `physics` | **The scroll behavior to use for the ScrollView.** | _ScrollPhysics_ | - |
102+
| `padding` | **The padding to use for the ScrollView.** | _EdgeInsetsGeometry_ | - |

analysis_options.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
include: package:very_good_analysis/analysis_options.yaml
2+
3+
# Additional information about this file can be found at
4+
# https://dart.dev/guides/language/analysis-options
5+
6+
linter:
7+
rules:
8+
directives_ordering: false
9+
sort_pub_dependencies: false
10+
unawaited_futures: false
11+
always_use_package_imports: false

example/example.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
## Examples / Usages
2+
3+
> **Note**: This file only contains examples for Firestore Database.
4+
> But all of this can be implemented for Firebase Realtime Database using the
5+
> RealtimeDBPagination widget with only the `query` and `itemBuilder` params
6+
> differing from FirestorePagination.
7+
8+
#### For a simple list view pagination (with a custom bottom loader)
9+
10+
```dart
11+
FirestorePagination(
12+
limit: 420, // Defaults to 10.
13+
viewType: ViewType.list,
14+
bottomLoader: const Center(
15+
child: CircularProgressIndicator(
16+
strokeWidth: 3,
17+
color: Colors.blue,
18+
),
19+
),
20+
query: FirebaseFirestore.instance
21+
.collection('scores')
22+
.orderBy('score', descending: true),
23+
itemBuilder: (context, documentSnapshot, index) {
24+
final data = documentSnapshot.data() as Map<String, dynamic>?;
25+
if (data == null) return Container();
26+
27+
return Container(
28+
child: RecordTile(
29+
name: data['name'],
30+
score: data['score'],
31+
),
32+
);
33+
},
34+
),
35+
```
36+
37+
<hr />
38+
39+
#### For live chat-like application with pagination (with separator between messages)
40+
41+
```dart
42+
FirestorePagination(
43+
limit: 69, // Defaults to 10.
44+
isLive: true, // Defaults to false.
45+
viewType: ViewType.list,
46+
reverse: true,
47+
query: FirebaseFirestore.instance
48+
.collection('chats')
49+
.orderBy('createdAt', descending: true),
50+
itemBuilder: (context, documentSnapshot, index) {
51+
final data = documentSnapshot.data() as Map<String, dynamic>?;
52+
if (data == null) return Container();
53+
54+
return MessageTile(
55+
senderName: data['senderName'],
56+
senderImageUrl: data['senderImageUrl'],
57+
message: data['message'],
58+
createdAt: data['createdAt'],
59+
);
60+
},
61+
separatorBuilder: (context, index) {
62+
return const Divider(
63+
height: 5,
64+
thickness: 1,
65+
);
66+
},
67+
),
68+
```
69+
70+
<hr />
71+
72+
#### For grid view with pagination (with custom no data view)
73+
74+
```dart
75+
FirestorePagination(
76+
limit: 14, // Defaults to 10.
77+
viewType: ViewType.grid,
78+
onEmpty: const Center(
79+
child: Text('Cart is empty'),
80+
),
81+
query: FirebaseFirestore.instance
82+
.collection('cart')
83+
.orderBy('price'),
84+
itemBuilder: (context, documentSnapshot, index) {
85+
final data = documentSnapshot.data() as Map<String, dynamic>?;
86+
if (data == null) return Container();
87+
88+
return GridTile(
89+
itemName: data['itemName'],
90+
itemImageUrl: data['itemImageUrl'],
91+
price: data['price'],
92+
);
93+
},
94+
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
95+
crossAxisCount: 3,
96+
mainAxisSpacing: 8.0,
97+
crossAxisSpacing: 8.0,
98+
),
99+
),
100+
```
101+
102+
<hr />
103+
104+
#### For Scrollable Wrap with pagination (with custom scrollDirection)
105+
106+
```dart
107+
FirestorePagination(
108+
limit: 12, // Defaults to 10.
109+
viewType: ViewType.wrap,
110+
scrollDirection: Axis.horizontal, // Defaults to Axis.vertical.
111+
query: FirebaseFirestore.instance
112+
.collection('categories')
113+
.orderBy('popularity', descending: true),
114+
itemBuilder: (context, documentSnapshot, index) {
115+
final data = documentSnapshot.data() as Map<String, dynamic>?;
116+
if (data == null) return Container();
117+
118+
return Container(
119+
constraints: const BoxConstraints(maxWidth: 169),
120+
child: CategoryTile(
121+
categoryName: data['categoryName'],
122+
categoryImageUrl: data['categoryImageUrl'],
123+
),
124+
);
125+
},
126+
wrapOptions: const WrapOptions(
127+
alignment: WrapAlignment.start,
128+
direction: Axis.vertical,
129+
runSpacing: 10.0,
130+
),
131+
),
132+
```

lib/firebase_pagination.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// A package to paginate your firebase related data with realtime updates.
2+
///
3+
/// It can be used for `Firestore` and `Firebase Realtime Database`.
4+
///
5+
/// Data can be shown in `list`, `grid` and `scrollable wrap` view.
6+
library firebase_pagination;
7+
8+
// Widgets
9+
export 'src/realtime_db_pagination.dart';
10+
export 'src/firestore_pagination.dart';
11+
12+
// Data Models
13+
export 'src/models/view_type.dart';
14+
export 'src/models/wrap_options.dart';

0 commit comments

Comments
 (0)