forked from beerstorm-net/GeoFlutterFire2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
upgraded dependencies aligned with Flutter2, added Null Safety, publi…
…shed cloned package
- Loading branch information
0 parents
commit b404942
Showing
120 changed files
with
4,817 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Miscellaneous | ||
*.class | ||
*.log | ||
*.pyc | ||
*.swp | ||
.DS_Store | ||
.atom/ | ||
.buildlog/ | ||
.history | ||
.svn/ | ||
|
||
# IntelliJ related | ||
*.iml | ||
*.ipr | ||
*.iws | ||
.idea/ | ||
|
||
# The .vscode folder contains launch configuration and tasks you configure in | ||
# VS Code which you may wish to be included in version control, so this line | ||
# is commented out by default. | ||
#.vscode/ | ||
|
||
# Flutter/Dart/Pub related | ||
**/doc/api/ | ||
.dart_tool/ | ||
.flutter-plugins | ||
.flutter-plugins-dependencies | ||
.packages | ||
.pub-cache/ | ||
.pub/ | ||
build/ | ||
|
||
# Android related | ||
**/android/**/gradle-wrapper.jar | ||
**/android/.gradle | ||
**/android/captures/ | ||
**/android/gradlew | ||
**/android/gradlew.bat | ||
**/android/local.properties | ||
**/android/**/GeneratedPluginRegistrant.java | ||
|
||
# iOS/XCode related | ||
**/ios/**/*.mode1v3 | ||
**/ios/**/*.mode2v3 | ||
**/ios/**/*.moved-aside | ||
**/ios/**/*.pbxuser | ||
**/ios/**/*.perspectivev3 | ||
**/ios/**/*sync/ | ||
**/ios/**/.sconsign.dblite | ||
**/ios/**/.tags* | ||
**/ios/**/.vagrant/ | ||
**/ios/**/DerivedData/ | ||
**/ios/**/Icon? | ||
**/ios/**/Pods/ | ||
**/ios/**/.symlinks/ | ||
**/ios/**/profile | ||
**/ios/**/xcuserdata | ||
**/ios/.generated/ | ||
**/ios/Flutter/App.framework | ||
**/ios/Flutter/Flutter.framework | ||
**/ios/Flutter/Flutter.podspec | ||
**/ios/Flutter/Generated.xcconfig | ||
**/ios/Flutter/app.flx | ||
**/ios/Flutter/app.zip | ||
**/ios/Flutter/flutter_assets/ | ||
**/ios/Flutter/flutter_export_environment.sh | ||
**/ios/ServiceDefinitions.json | ||
**/ios/Runner/GeneratedPluginRegistrant.* | ||
|
||
# Exceptions to above rules. | ||
!**/ios/**/default.mode1v3 | ||
!**/ios/**/default.mode2v3 | ||
!**/ios/**/default.pbxuser | ||
!**/ios/**/default.perspectivev3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# This file tracks properties of this Flutter project. | ||
# Used by Flutter tool to assess capabilities and perform upgrades etc. | ||
# | ||
# This file should be version controlled and should not be manually edited. | ||
|
||
version: | ||
revision: 60bd88df915880d23877bfc1602e8ddcf4c4dd2a | ||
channel: beta | ||
|
||
project_type: package |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
## 2.2.2 | ||
* upgraded dependencies aligned with Flutter2 | ||
* added Null safety | ||
* publish new package from forked project | ||
|
||
## 2.1.0 | ||
* fixed breaking changes | ||
* would not be able to access data using `doc.data['distance']` anymore | ||
|
||
## 2.0.3+8 | ||
* upgraded dependencies | ||
* fix for iOS build errors | ||
* fixes for breaking changes from 2.0.3 for stream builders | ||
* added a bug-fix for supporting stream builders | ||
|
||
## 2.0.2 | ||
* added support for filtering documents strictly/easily with respect to radius | ||
|
||
## 2.0.1+1 | ||
* bumped up the versions of kotlin-plugin and gradle. | ||
* Support for GeoPoints nested inside the firestore document | ||
|
||
## 2.0.0 | ||
* **Breaking change**. Migrate from the deprecated original Android Support | ||
Library to AndroidX. This shouldn't result in any functional changes, but it | ||
requires any Android apps using this plugin to [also | ||
migrate](https://developer.android.com/jetpack/androidx/migrate) if they're | ||
using the original support library. | ||
* reverted to flutter stable channel from master. | ||
|
||
## 1.0.2 | ||
* Refactored code to adhere to best practices(again) | ||
|
||
## 1.0.1 | ||
* Refactored code to adhere to best practices | ||
|
||
## 1.0.0 | ||
* Initial Release | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2020 Beerstorm | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
# GeoFlutterFire2 :earth_africa: | ||
|
||
**NB! `GeoFlutterFire2` is a revisited and updated version of [GeoFlutterFire](https://github.com/DarshanGowda0/GeoFlutterFire)** | ||
|
||
GeoFlutterFire is an open-source library that allows you to store and query a set of keys based on their geographic location. At its heart, GeoFlutterFire simply stores locations with string keys. Its main benefit, however, is the possibility of retrieving only those keys within a given geographic area - all in realtime. | ||
|
||
GeoFlutterFire uses the Firebase Firestore Database for data storage, allowing query results to be updated in realtime as they change. GeoFlutterFire selectively loads only the data near certain locations, keeping your applications light and responsive, even with extremely large datasets. | ||
|
||
GeoFlutterFire is designed as a lightweight add-on to cloud_firestore plugin. To keep things simple, GeoFlutterFire stores data in its own format within your Firestore database. This allows your existing data format and Security Rules to remain unchanged while still providing you with an easy solution for geo queries. | ||
|
||
Heavily influenced by [GeoFireX](https://github.com/codediodeio/geofirex) :fire::fire: from [Jeff Delaney](https://github.com/codediodeio) :sunglasses: | ||
|
||
:tv: Checkout this amazing tutorial on [fireship](https://fireship.io/lessons/flutter-realtime-geolocation-firebase/) by Jeff, featuring the plugin!! | ||
|
||
|
||
## Getting Started | ||
|
||
You should ensure that you add GeoFlutterFire as a dependency in your flutter project. | ||
|
||
```yaml | ||
dependencies: | ||
geoflutterfire: <latest-version> | ||
``` | ||
You can also reference the git repo directly if you want: | ||
```yaml | ||
dependencies: | ||
geoflutterfire: | ||
git: git://github.com/DarshanGowda0/GeoFlutterFire.git | ||
``` | ||
You should then run `flutter packages get` or update your packages in IntelliJ. | ||
|
||
## Example | ||
|
||
There is a detailed example project in the `example` folder. Check that out or keep reading! | ||
|
||
## Initialize | ||
|
||
You need a firebase project with [Firestore](https://pub.dartlang.org/packages/cloud_firestore) setup. | ||
|
||
```dart | ||
import 'package:geoflutterfire/geoflutterfire.dart'; | ||
import 'package:cloud_firestore/cloud_firestore.dart'; | ||
// Init firestore and geoFlutterFire | ||
final geo = Geoflutterfire(); | ||
final _firestore = FirebaseFirestore.instance; | ||
``` | ||
|
||
## Writing Geo data | ||
|
||
Add geo data to your firestore document using `GeoFirePoint` | ||
|
||
```dart | ||
GeoFirePoint myLocation = geo.point(latitude: 12.960632, longitude: 77.641603); | ||
``` | ||
|
||
Next, add the GeoFirePoint to you document using Firestore's add method | ||
|
||
```dart | ||
_firestore | ||
.collection('locations') | ||
.add({'name': 'random name', 'position': myLocation.data}); | ||
``` | ||
|
||
Calling `geoFirePoint.data` returns an object that contains a [geohash string](https://www.movable-type.co.uk/scripts/geohash.html) and a [Firestore GeoPoint](https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/GeoPoint). It should look like this in your database. You can name the object whatever you want and even save multiple points on a single document. | ||
|
||
![](https://firebasestorage.googleapis.com/v0/b/geo-test-c92e4.appspot.com/o/point1.png?alt=media&token=0c833700-3dbd-476a-99a9-41c1143dbe97) | ||
|
||
## Query Geo data | ||
|
||
To query a collection of documents with 50kms from a point | ||
|
||
```dart | ||
// Create a geoFirePoint | ||
GeoFirePoint center = geo.point(latitude: 12.960632, longitude: 77.641603); | ||
// get the collection reference or query | ||
var collectionReference = _firestore.collection('locations'); | ||
double radius = 50; | ||
String field = 'position'; | ||
Stream<List<DocumentSnapshot>> stream = geo.collection(collectionRef: collectionReference) | ||
.within(center: center, radius: radius, field: field); | ||
``` | ||
|
||
The within function returns a Stream of the list of DocumentSnapshot data, plus some useful metadata like distance from the centerpoint. | ||
|
||
```dart | ||
stream.listen((List<DocumentSnapshot> documentList) { | ||
// doSomething() | ||
}); | ||
``` | ||
|
||
You now have a realtime stream of data to visualize on a map. | ||
![](https://firebasestorage.googleapis.com/v0/b/geoflutterfire.appspot.com/o/geflutterfire.gif?alt=media&token=8dc3aa9c-ee68-4dfe-9093-c3c1c48979dc) | ||
|
||
## :notebook: API | ||
|
||
### `collection(collectionRef: CollectionReference)` | ||
|
||
Creates a GeoCollectionRef which can be used to make geo queries, alternatively can also be used to write data just like firestore's add / set functionality. | ||
|
||
Example: | ||
|
||
```dart | ||
// Collection ref | ||
// var collectionReference = _firestore.collection('locations').where('city', isEqualTo: 'bangalore'); | ||
var collectionReference = _firestore.collection('locations'); | ||
var geoRef = geo.collection(collectionRef: collectionReference); | ||
``` | ||
|
||
Note: collectionReference can be of type CollectionReference or Query | ||
|
||
#### Performing Geo-Queries | ||
|
||
`geoRef.within(center: GeoFirePoint, radius: double, field: String, {strictMode: bool})` | ||
|
||
Query the parent Firestore collection by geographic distance. It will return documents that exist within X kilometers of the center-point. | ||
`field` supports nested objects in the firestore document. | ||
|
||
**Note:** Use optional parameter `strictMode = true` to filter the documents strictly within the bound of given radius. | ||
|
||
Example: | ||
|
||
```dart | ||
// For GeoFirePoint stored at the root of the firestore document | ||
geoRef.within(center: centerGeoPoint, radius: 50, field: 'position', strictMode: true); | ||
// For GeoFirePoint nested in other objects of the firestore document | ||
geoRef.within(center: centerGeoPoint, radius: 50, field: 'address.location.position', strictMode: true); | ||
``` | ||
|
||
Each `documentSnapshot.data()` also contains `distance` calculated on the query. | ||
|
||
**Returns:** `Stream<List<DocumentSnapshot>>` | ||
|
||
#### Write Data | ||
|
||
Write data just like you would in Firestore | ||
|
||
`geoRef.add(data)` | ||
|
||
Or use one of the client's conveniece methods | ||
|
||
- `geoRef.setDoc(String id, var data, {bool merge})` - Set a document in the collection with an ID. | ||
- `geoRef.setPoint(String id, String field, double latitude, double longitude)`- Add a geohash to an existing doc | ||
|
||
#### Read Data | ||
|
||
In addition to Geo-Queries, you can also read the collection like you would normally in Firestore, but as an Observable | ||
|
||
- `geoRef.data()`- Stream of documentSnapshot | ||
- `geoRef.snapshot()`- Stream of Firestore QuerySnapshot | ||
|
||
### `point(latitude: double, longitude: double)` | ||
|
||
Returns a GeoFirePoint allowing you to create geohashes, format data, and calculate relative distance. | ||
|
||
Example: `var point = geo.point(38, -119)` | ||
|
||
#### Getters | ||
|
||
- `point.hash` Returns a geohash string at precision 9 | ||
- `point.geoPoint` Returns a Firestore GeoPoint | ||
- `point.data` Returns data object suitable for saving to the Firestore database | ||
|
||
#### Geo Calculations | ||
|
||
- `point.distance(latitude, longitude)` Haversine distance to a point | ||
|
||
## :zap: Tips | ||
|
||
### Scale to Massive Collections | ||
|
||
It's possible to build Firestore collections with billions of documents. One of the main motivations of this project was to make geoqueries possible on a queried subset of data. You can pass a Query instead of a CollectionReference into the collection(), then all geoqueries will be scoped with the constraints of that query. | ||
|
||
Note: This query requires a composite index, which you will be prompted to create with an error from Firestore on the first request. | ||
|
||
Example: | ||
|
||
```dart | ||
var queryRef = _firestore.collection('locations').where('city', isEqualTo: 'bangalore'); | ||
var stream = geo | ||
.collection(collectionRef: queryRef) | ||
.within(center: center, radius: rad, field: 'position'); | ||
``` | ||
|
||
### Usage of strictMode | ||
|
||
It's advisable to use `strictMode = false` for smaller radius to make use of documents from neighbouring hashes as well. | ||
|
||
As the radius increases to a large number, the neighbouring hash precisions fetch documents which would be considerably far from the radius bounds, hence its advisable to use `strictMode = true` for larger radius. | ||
|
||
**Note:** filtering for strictMode happens on client side, hence filtering at larger radius is at the expense of making unnecessary document reads. | ||
|
||
### Make Dynamic Queries the RxDart Way | ||
|
||
```dart | ||
var radius = BehaviorSubject<double>.seeded(1.0); | ||
var collectionReference = _firestore.collection('locations'); | ||
stream = radius.switchMap((rad) { | ||
return geo | ||
.collection(collectionRef: collectionReference) | ||
.within(center: center, radius: rad, field: 'position'); | ||
}); | ||
// Now update your query | ||
radius.add(25); | ||
``` | ||
|
||
### Limitations | ||
|
||
- range queries on multiple fields is not suppoerted by cloud_firestore at the moment, since this library already uses range query on `geohash` field, you cannot perform range queries with `GeoFireCollectionRef`. | ||
- `limit()` and `orderBy()` are not supported at the moment. `limit()` could be used to limit docs inside each hash individually which would result in running limit on all 9 hashes inside the specified radius. `orderBy()` is first run on `geohashes` in the library, hence appending `orderBy()` with another feild wouldn't produce expected results. Alternatively documents can be sorted on client side. | ||
|
||
### Acknowledgements | ||
**NB! `GeoFlutterFire2` is a revisited and updated version of [GeoFlutterFire](https://github.com/DarshanGowda0/GeoFlutterFire)** | ||
The work originates from [GeoFlutterFire](https://github.com/DarshanGowda0/GeoFlutterFire) by Darshan Narayanaswamy |
Oops, something went wrong.