getDataInArea<T> function

Stream<List<T>> getDataInArea <T>({@required Area area, @required CollectionReference collection, @required DocumentMapper<T> mapper, @required String locationFieldNameInDB, LocationAccessor<T> locationAccessor, List<ItemFilter<T>> clientSitefilters, DistanceMapper<T> distanceMapper, DistanceAccessor<T> distanceAccessor, bool sortDecending: false })

Provides as Stream of lists of data items of type T that have a location field in a specified area sorted by the distance of to the areas center. area : The area that constraints the query collection : The source FireStore document collection mapper : mapping function that gets applied to every document in the query. Typically used to deserialize the Map returned from FireStore locationFieldInDb : The name of the data field in your FireStore document. Need to make the location based search on the server side locationAccessor : As this is a generic function it cannot know where your location is stored in you generic type. optional if you don't use distanceMapper and don't want to sort by distance Therefore pass a function that returns a valur from the location field inside your generic type. distanceMapper : optional mapper that gets the distance to the center of the area passed to give you the chance to save this inside your item if you use a distanceMapper you HAVE to pass locationAccessor clientSideFilters : optional list of filter functions that execute a .where() on the result on the client side distanceAccessor : if you have stored the distance using a distanceMapper passing this accessor function will prevent additional distance computing for sorting. sortDecending : if the resulting list should be sorted descending by the distance to the area's center. If you don't provide loacationAccessor or distanceAccessor no sorting is done

Implementation

Stream<List<T>> getDataInArea<T>(
    {@required Area area,
    @required CollectionReference collection,
    @required DocumentMapper<T> mapper,
    @required String locationFieldNameInDB,
    LocationAccessor<T> locationAccessor,
    List<ItemFilter<T>> clientSitefilters,
    DistanceMapper<T> distanceMapper,
    DistanceAccessor<T> distanceAccessor,
    bool sortDecending = false}) {
  assert((distanceAccessor == null) || (distanceMapper != null && distanceAccessor != null),);

  var query = buildQuery(
      collection: collection, constraints: getLocationsConstraint(locationFieldNameInDB, area));
  return getDataFromQuery<T>(
      query: query,
      mapper: (docSnapshot) {
        // get a real objects from FireStore
        var item = mapper(docSnapshot);
        double distance;
        if (locationAccessor != null)
        {
           distance = area.distanceToCenter(locationAccessor(item));
        }
        if (distance != null) {
          // We might get places outside the target circle at the corners of the surrounding square
          if (distance > area.radiusInKilometers)
          {
            return null;
          }
          if (distanceMapper != null)
          {
            return distanceMapper(item, distance);
          }
        }
          return item;
      },
      clientSitefilters: clientSitefilters != null ? ()=>clientSitefilters..insert(0,(item) => item != null) : [(item) => item != null],
      orderComparer:
          distanceAccessor != null // i this case we don't have to calculate the distance again
              ? (item1, item2) => sortDecending
                  ? distanceAccessor(item1).compareTo(distanceAccessor(item2))
                  : distanceAccessor(item2).compareTo(distanceAccessor(item1))
              : locationAccessor != null
                  ? (item1, item2) => sortDecending
                      ? area
                          .distanceToCenter(locationAccessor(item1))
                          .compareTo(area.distanceToCenter(locationAccessor(item2)))
                      : area
                          .distanceToCenter(locationAccessor(item2))
                          .compareTo(area.distanceToCenter(locationAccessor(item1)))
                  : null);
}