Giter VIP home page Giter VIP logo

kosukesaigusa / geoflutterfire_plus Goto Github PK

View Code? Open in Web Editor NEW
55.0 55.0 4.0 444 KB

๐ŸŒ๐Ÿ’™๐Ÿ”ฅ geoflutterfire_plus allows your flutter apps to query geographic data saved in Cloud Firestore. This package is fork from GeoFlutterFire, and tried to be constantly maintained to work with latest Flutter SDK, Dart SDK, and other dependency packages.

Home Page: https://pub.dev/packages/geoflutterfire_plus

License: MIT License

Dart 97.41% Kotlin 0.11% Ruby 1.71% Swift 0.73% Objective-C 0.04%
cloudfirestore dart firebase firestore flutter flutterfire geopoint geoquery

geoflutterfire_plus's People

Contributors

dai10512 avatar dependabot[bot] avatar iabdousd avatar king-kazu39 avatar kokorinosoba avatar kosukesaigusa avatar kurczaak avatar naokiwakata avatar shvn-iwa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

geoflutterfire_plus's Issues

How many documents are queried?

In the documentation:

๐Ÿšจ Limitation: currently limit and orderBy queries are not supported because of the geo hash query algorithm and Cloud Firestore query limitations. Alternatively documents can be sorted on client side after getting the data (documents).

I would like to ask, how many documents are queried maximum?

OrderBy not working

Really cool what you're doing with this package. Unfortunately for Flutter, this is such a fragmented space and no packages appear to have got it right so far for Firestore GeoPoint Queries.

My big issue is being able to use the "OrderBy" feature. I switched to your package because you had a QueryBuilder, but once I try to do an OrderBy there, it hangs up again and nothing shows.

'isCacheFirst' not working

Hi,
in my previous PR I've implemented the isCacheFirst functionality, however it's not working as expected. I haven't tested the implementation well enough. This time I did some tests with debugging and it seems to work correct. Let me know what you think, here's my PR:
#203

PS.
Sorry for the inconvenience, I promise to test my code better next time

queryBuilder ใฎ orderBy ใŒๆฉŸ่ƒฝใ—ใชใ„

ใŠ็–ฒใ‚Œๆง˜ใงใ™๏ผ

cloud firestore ใฎ่ค‡ๅˆใ‚ฏใ‚จใƒชใŒ่ค‡ๆ•ฐใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ๅฏพๅฟœใ—ใฆ่‡ช็”ฑๅบฆ้ซ˜ใใชใฃใŸใฎใง
orderBy ใ‚‚่ฟฝๅŠ ใงๅ…ฅใ‚Œใ‚‰ใ‚Œใ‚‹ใจๆ€ใฃใŸใฎใงใ™ใŒใ€็ขบ่ชใ—ใฆใ„ใŸใ ใ„ใฆ
ใงใใใ†ใงใ—ใŸใ‚‰ๅฏพๅฟœใ—ใฆใ‚‚ใ‚‰ใˆใ‚‹ใจๅฌ‰ใ—ใ„ใงใ™mm

่ค‡ๆ•ฐใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซๅฏพๅฟœใ—ใŸ่ค‡ๅˆใ‚ฏใ‚จใƒชใฎใ‚ขใƒƒใƒ—ใƒ‡ใƒผใƒˆ่ฉณ็ดฐ

https://firebase.google.com/docs/firestore/query-data/multiple-range-fields

Please update to rxdart ^0.28.0!!!

Because no versions of geoflutterfire_plus match >0.0.24 <0.1.0 and geoflutterfire_plus 0.0.24 depends on rxdart ^0.27.1, geoflutterfire_plus ^0.0.24 requires rxdart ^0.27.1.
And because flutter_google_places_hoc081098 >=2.0.0 depends on rxdart ^0.28.0, geoflutterfire_plus ^0.0.24 is incompatible with flutter_google_places_hoc081098 >=2.0.0.
So, because gather depends on both flutter_google_places_hoc081098 ^2.0.0 and geoflutterfire_plus ^0.0.24, version solving failed.
exit code 1

One time query as Future

Hi,
I saw a post that you can use fetchWithin method to fetch geo locations as Future.
When my app starts I would like to query initially Firestore for objects in a certain distance. But only once and not as a stream. Is there an example?
Thanks

Version incompatibility

I need to update the components of my application but the error below is occurring. Do you have any predictions on when it will be compatible?

Resolving dependencies...
Because geoflutterfire_plus >=0.0.21 depends on cloud_firestore ^4.17.0 and dochealth_core depends on cloud_firestore ^5.0.1, geoflutterfire_plus >=0.0.21 is forbidden.
So, because dochealth_core depends on geoflutterfire_plus ^0.0.21, version solving failed.

[Error report not reproducible] filters support a maximum of 30 elements in the value [Iterable].

I am not using any firestore query along with the fetchWithin function still getting below error.

'package:cloud_firestore/src/query.dart': Failed assertion: line 741 pos 11: '(operator != 'in' && operator != 'array-contains-any') ||
I/flutter (15285): (value as Iterable).length <= 30': 'in' filters support a maximum of 30 elements in the value [Iterable].

My code:-

Future<void> findNearbyLocations() async {
    Future.delayed(Duration.zero);

    try {
      // Query for "Akota Garden" location
      QuerySnapshot querySnapshot = await fireStore
          .collection('locations')
          .where('place_name', isEqualTo: 'Akota Garden')
          .get();

      // Get the first document from the query result
      DocumentSnapshot documentSnapshot = querySnapshot.docs.first;

      // Get the coordinates of "Akota Garden"
      GeoPoint akotaGardenLocation = documentSnapshot['coordinates'];

      // Create a GeoFirePoint for "Akota Garden"
      GeoFirePoint center = GeoFirePoint(akotaGardenLocation);

      // Reference to locations collection.
      final CollectionReference<Map<String, dynamic>> locationCollectionRef =
          fireStore.collection('locations');

      final result =
          await GeoCollectionReference(locationCollectionRef).fetchWithin(
        center: center,
        radiusInKm: 6,
        field: 'geo',
        strictMode: true,
        geopointFrom: geopointFrom,
      );

      for (var value in result) {
        String placeName = value['place_name'];
        final distance =
            center.distanceBetweenInKm(geopoint: value['coordinates']);

        print(placeName);
        print("Distance : $distance");
      }
    } catch (e) {
      print("ERROR IN LOCATION : $e");
    }
  }

Using queryBuilder negates the values and returns empty

If I pass a querybuilder to filter out values from the collection, the returns values are empty.
If I remove the query, values are returned. I need to return values based on the query:

var collectionReference =
     FirebaseFirestore.instance.collection(Str.BODA_REGISTRATION_COLLECTION);
 // .where(Str.UID, isNotEqualTo: FirebaseAuth.instance.currentUser!.uid); (this is not allowed, should be made to be allowed

 double radiusInKm = 10;
 String field = Str.GEOFIREPOINT_DATA;

 GeoPoint geopointFrom(Map<String, dynamic> data) =>
     (data[field] as Map<String, dynamic>)['geopoint'] as GeoPoint;

 final Stream<List<DocumentSnapshot<Map<String, dynamic>>>> stream =
     GeoCollectionReference<Map<String, dynamic>>(collectionReference)
         .subscribeWithin(
   center: center,
   radiusInKm: radiusInKm,
   field: field,
   geopointFrom: geopointFrom,
//with the commented lines below, when uncommented, the list is empty, when commented, there are values. The data in firebase is to return all except for the one with a filter as shown. 
   // queryBuilder: (query) {
   //   return query
   //       .where(Str.UID,
   //           isNotEqualTo: FirebaseAuth.instance.currentUser!.uid)
   //       .orderBy(Str.UID)
   //       .orderBy(field);
   // },
 );
 
 await for (List<DocumentSnapshot<Map<String, dynamic>>> bodaList
     in stream) {
   final distances = bodaList.map((boda) {
     final bodaLocation = geopointFrom(boda.data()!);
     final double distance =
         center.distanceBetweenInKm(geopoint: bodaLocation);

     return distance * 1000;
   }).toList();

Possibly, have an updated documentation on how query filters work with GeoFlutterFire_plus with examples based on the approach I have up there. Or modify the package to include use of QuerySnapShot and show examples

QueryBuilder not returning any results

geoflutterfire_plus: ^0.0.21

When trying to inject additional query, I am not getting any results. When removing queryBuilder, I am getting all results.

Code:

var res =
      await GeoCollectionReference<Map<String, dynamic>>(collectionReference)
          .subscribeWithin(
            center: center,
            radiusInKm: radiusInKm,
            field: field,
            geopointFrom: geopointFrom,
            queryBuilder: (query) => query.where('archived', isEqualTo: false),
          )
          .first;

  final obj =
      res.map((docSnapshot) => Post.fromDocumentSnapshot(docSnapshot)).toList();

  return obj;

nor with fetchWithin

var res =
      await GeoCollectionReference<Map<String, dynamic>>(collectionReference)
          .fetchWithin(
    center: center,
    radiusInKm: radiusInKm,
    field: field,
    geopointFrom: geopointFrom,
    queryBuilder: (query) => query.where('archived', isEqualTo: false),
  );

i've tested it further because i thought it is something with my query, but passing null to query doesn't also work(I saw an example proj where null should get all values as well).

var res =
      await GeoCollectionReference<Map<String, dynamic>>(collectionReference)
          .fetchWithin(
    center: center,
    radiusInKm: radiusInKm,
    field: field,
    geopointFrom: geopointFrom,
    queryBuilder: (query) => null,
  );

hello I can't see the markers

hello, I just copy paste your examples and other files and just changed geo points, but I can't see any marker in my map I also checked with zoom out but still there's not thing show. I checked the connection with my firebase by adding new location and it worked well. Can you help me to see the markers?

Thank you, and your project is so amazing this is the exact project what I was looking for!!

screen capture of ios
screen capture of firebase

park_map.dart

import 'package:cloud_firestore/cloud_firestore.dart';
//import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:geoflutterfire_plus/geoflutterfire_plus.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:rxdart/rxdart.dart';

import '../locations/add_location.dart';
//import '../firebase_options.dart';
import '../locations/set_or_delete_location.dart';

/// Tokyo Station location for demo.
const _tokyoStation = LatLng(48.573405, 7.752111);

/// Reference to the collection where the location data is stored.
/// `withConverter` is available to type-safely define [CollectionReference].
final _collectionReference = FirebaseFirestore.instance.collection('locations');

/// Geo query geoQueryCondition.
class _GeoQueryCondition {
  _GeoQueryCondition({
    required this.radiusInKm,
    required this.cameraPosition,
  });

  final double radiusInKm;
  final CameraPosition cameraPosition;
}

class ParkMap extends StatefulWidget {
  const ParkMap({super.key});

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

/// Example page using [GoogleMap].
class ParkMapState extends State<ParkMap> {
  /// [Marker]s on Google Maps.
  Set<Marker> _markers = {};

  /// [BehaviorSubject] of currently geo query radius and camera position.
  final _geoQueryCondition = BehaviorSubject<_GeoQueryCondition>.seeded(
    _GeoQueryCondition(
      radiusInKm: _initialRadiusInKm,
      cameraPosition: _initialCameraPosition,
    ),
  );

  /// [Stream] of geo query result.
  late final Stream<List<DocumentSnapshot<Map<String, dynamic>>>> _stream =
      _geoQueryCondition.switchMap(
    (geoQueryCondition) =>
        GeoCollectionReference(_collectionReference).subscribeWithin(
      center: GeoFirePoint(
        GeoPoint(
          _cameraPosition.target.latitude,
          _cameraPosition.target.longitude,
        ),
      ),
      radiusInKm: geoQueryCondition.radiusInKm,
      field: 'geo',
      geopointFrom: (data) =>
          (data['geo'] as Map<String, dynamic>)['geopoint'] as GeoPoint,
      strictMode: true,
    ),
  );

  /// Updates [_markers] by fetched geo [DocumentSnapshot]s.
  void _updateMarkersByDocumentSnapshots(
    List<DocumentSnapshot<Map<String, dynamic>>> documentSnapshots,
  ) {
    final markers = <Marker>{};
    for (final ds in documentSnapshots) {
      final id = ds.id;
      final data = ds.data();
      if (data == null) {
        continue;
      }
      final name = data['name'] as String;
      final geoPoint =
          (data['geo'] as Map<String, dynamic>)['geopoint'] as GeoPoint;
      markers.add(_createMarker(id: id, name: name, geoPoint: geoPoint));
    }
    debugPrint('๐Ÿ“ markers count: ${markers.length}');
    setState(() {
      _markers = markers;
    });
  }

  /// Creates a [Marker] by fetched geo location.
  Marker _createMarker({
    required String id,
    required String name,
    required GeoPoint geoPoint,
  }) =>
      Marker(
        markerId: MarkerId('(${geoPoint.latitude}, ${geoPoint.longitude})'),
        position: LatLng(geoPoint.latitude, geoPoint.longitude),
        infoWindow: InfoWindow(title: name),
        onTap: () => showDialog<void>(
          context: context,
          builder: (context) => SetOrDeleteLocationDialog(
            id: id,
            name: name,
            geoFirePoint: GeoFirePoint(
              GeoPoint(geoPoint.latitude, geoPoint.longitude),
            ),
          ),
        ),
      );

  /// Current detecting radius in kilometers.
  double get _radiusInKm => _geoQueryCondition.value.radiusInKm;

  /// Current camera position on Google Maps.
  CameraPosition get _cameraPosition => _geoQueryCondition.value.cameraPosition;

  /// Initial geo query detection radius in km.
  static const double _initialRadiusInKm = 10;

  /// Google Maps initial camera zoom level.
  static const double _initialZoom = 10;

  /// Google Maps initial target position.
  static final LatLng _initialTarget = LatLng(
    _tokyoStation.latitude,
    _tokyoStation.longitude,
  );

  /// Google Maps initial camera position.
  static final _initialCameraPosition = CameraPosition(
    target: _initialTarget,
    zoom: _initialZoom,
  );

  @override
  void dispose() {
    _geoQueryCondition.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          GoogleMap(
            zoomControlsEnabled: false,
            myLocationButtonEnabled: false,
            initialCameraPosition: _initialCameraPosition,
            onMapCreated: (_) =>
                _stream.listen(_updateMarkersByDocumentSnapshots),
            markers: _markers,
            circles: {
              Circle(
                circleId: const CircleId('value'),
                center: LatLng(
                  _cameraPosition.target.latitude,
                  _cameraPosition.target.longitude,
                ),
                // multiple 1000 to convert from kilometers to meters.
                radius: _radiusInKm * 1000,
                fillColor: Colors.black12,
                strokeWidth: 0,
              ),
            },
            onCameraMove: (cameraPosition) {
              debugPrint('๐Ÿ“ท lat: ${cameraPosition.target.latitude}, '
                  'lng: ${cameraPosition.target.latitude}');
              _geoQueryCondition.add(
                _GeoQueryCondition(
                  radiusInKm: _radiusInKm,
                  cameraPosition: cameraPosition,
                ),
              );
            },
            onLongPress: (latLng) => showDialog<void>(
              context: context,
              builder: (context) => AddLocationDialog(latLng: latLng),
            ),
          ),
          Container(
            width: double.infinity,
            margin: const EdgeInsets.only(top: 64, left: 16, right: 16),
            padding: const EdgeInsets.all(16),
            decoration: const BoxDecoration(
              color: Colors.black38,
              borderRadius: BorderRadius.all(Radius.circular(8)),
            ),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                const Text(
                  'Debug window',
                  style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                const SizedBox(height: 8),
                Text(
                  'Currently detected count: '
                  '${_markers.length}',
                  style: const TextStyle(color: Colors.white),
                ),
                const SizedBox(height: 8),
                Text(
                  'Current radius: '
                  '${_radiusInKm.toStringAsFixed(1)} (km)',
                  style: const TextStyle(color: Colors.white),
                ),
                const SizedBox(height: 8),
                Slider(
                  value: _radiusInKm,
                  min: 1,
                  max: 100,
                  divisions: 99,
                  label: _radiusInKm.toStringAsFixed(1),
                  onChanged: (value) => _geoQueryCondition.add(
                    _GeoQueryCondition(
                      radiusInKm: value,
                      cameraPosition: _cameraPosition,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => showDialog<void>(
          context: context,
          builder: (context) => const AddLocationDialog(),
        ),
        child: const Icon(Icons.add),
      ),
    );
  }
} 

main.dart

import 'firebase_options.dart';
import 'package:flutter/material.dart';
import 'bottom_nav_bar/bottom_nav_bar.dart';
import 'package:firebase_core/firebase_core.dart';
//import 'package:flutter/foundation.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await dotenv.load(fileName: ".env");
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Trotti Park',
      theme: ThemeData(
        primarySwatch: Colors.indigo,
      ),
      home: const MyBottomNavBar(),
    );
  }
}

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.