Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sort autocomplete results #153

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 57 additions & 4 deletions lib/src/autocomplete_search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:google_maps_place_picker/src/components/rounded_frame.dart';
import 'package:google_maps_place_picker/src/controllers/autocomplete_search_controller.dart';
import 'package:google_maps_webservice/places.dart';
import 'package:provider/provider.dart';
import 'dart:math';

class AutoCompleteSearch extends StatefulWidget {
const AutoCompleteSearch(
Expand All @@ -32,7 +33,8 @@ class AutoCompleteSearch extends StatefulWidget {
this.region,
this.initialSearchString,
this.searchForInitialValue,
this.autocompleteOnTrailingWhitespace})
this.autocompleteOnTrailingWhitespace,
this.autocompleteSortByDistance})
: assert(searchBarController != null),
super(key: key);

Expand All @@ -56,6 +58,7 @@ class AutoCompleteSearch extends StatefulWidget {
final String? initialSearchString;
final bool? searchForInitialValue;
final bool? autocompleteOnTrailingWhitespace;
final bool? autocompleteSortByDistance;

@override
AutoCompleteSearchState createState() => AutoCompleteSearchState();
Expand Down Expand Up @@ -257,9 +260,39 @@ class AutoCompleteSearchState extends State<AutoCompleteSearch> {
);
}

Widget _buildPredictionOverlay(List<Prediction> predictions) {
Future<Widget> _buildPredictionOverlay(List<Prediction> predictions) async {
PlaceProvider placeProvider = PlaceProvider.of(context, listen: false);
var map = <Prediction, num>{};
var sortedPredictions = <Prediction>[];

if (placeProvider.currentPosition != null &&
widget.autocompleteSortByDistance == true) {
for (var i = 0; i < predictions.length; i++) {
var data = await placeProvider.places.getDetailsByPlaceId(
predictions[i].placeId!,
sessionToken: placeProvider.sessionToken,
);

map.addAll({
predictions[i]: computeDistance(
placeProvider.currentPosition!.latitude,
placeProvider.currentPosition!.longitude,
data.result.geometry!.location.lat,
data.result.geometry!.location.lng,
)
});
}

var sortedMapEntries = map.entries.toList()
..sort((a, b) => a.value.compareTo(b.value));

sortedMapEntries.forEach((element) {
sortedPredictions.add(element.key);
});
}

return ListBody(
children: predictions
children: (sortedPredictions.isNotEmpty ? sortedPredictions : predictions)
.map(
(p) => PredictionTile(
prediction: p,
Expand Down Expand Up @@ -297,7 +330,7 @@ class AutoCompleteSearchState extends State<AutoCompleteSearch> {
return;
}

_displayOverlay(_buildPredictionOverlay(response.predictions));
_displayOverlay(await _buildPredictionOverlay(response.predictions));
}
}

Expand All @@ -314,4 +347,24 @@ class AutoCompleteSearchState extends State<AutoCompleteSearch> {
clearOverlay() {
_clearOverlay();
}

num computeDistance(
num lat1,
num lng1,
num lat2,
num lng2,
) {
var x = pi / 180;

lat1 *= x;
lng1 *= x;
lat2 *= x;
lng2 *= x;

var distance = 2 *
asin(sqrt(pow(sin((lat1 - lat2) / 2), 2) +
cos(lat1) * cos(lat2) * pow(sin((lng1 - lng2) / 2), 2)));

return distance * 6378137;
}
}
15 changes: 14 additions & 1 deletion lib/src/place_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class PlacePicker extends StatefulWidget {
this.autocompleteLanguage,
this.autocompleteComponents,
this.autocompleteTypes,
this.autocompleteSortByDistance = false,
this.strictbounds,
this.region,
this.selectInitialPosition = false,
Expand Down Expand Up @@ -93,6 +94,16 @@ class PlacePicker extends StatefulWidget {
final num? autocompleteRadius;
final String? autocompleteLanguage;
final List<String>? autocompleteTypes;

/// If true, the autocomplete will fetch the geolocation details.
///
/// Be careful in using this because on every autocomplete result, it will query one request to the Google Maps server.
///
/// If you see no changes with the results, it is possible that it is already sorted.
///
/// If you have any problems, for example expecting other results or any inquiries: please contact https://github.com/kirkcharlesniv/
final bool autocompleteSortByDistance;

final List<Component>? autocompleteComponents;
final bool? strictbounds;
final String? region;
Expand Down Expand Up @@ -306,7 +317,9 @@ class _PlacePickerState extends State<PlacePicker> {
region: widget.region,
initialSearchString: widget.initialSearchString,
searchForInitialValue: widget.searchForInitialValue,
autocompleteOnTrailingWhitespace: widget.autocompleteOnTrailingWhitespace),
autocompleteOnTrailingWhitespace:
widget.autocompleteOnTrailingWhitespace,
autocompleteSortByDistance: widget.autocompleteSortByDistance),
),
SizedBox(width: 5),
],
Expand Down