diff --git a/flutter_google_places_sdk_platform_interface/CHANGELOG.md b/flutter_google_places_sdk_platform_interface/CHANGELOG.md index e58eb4c..1a2b206 100644 --- a/flutter_google_places_sdk_platform_interface/CHANGELOG.md +++ b/flutter_google_places_sdk_platform_interface/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.3.0 + +* feat: Added support for Google Places (new) which can be enabled through `initialize` function. +* feat: Added `searchByText` and `searchNearby` function for Places (new). +* feat: Added `nameLanguageCode` and `reviews` to Place object. + ## 0.2.7 * Now receiving an already converted string list for typesFilter in `findAutocompletePredictions` diff --git a/flutter_google_places_sdk_platform_interface/lib/flutter_google_places_sdk_platform.dart b/flutter_google_places_sdk_platform_interface/lib/flutter_google_places_sdk_platform.dart index 5160c05..4f70b38 100644 --- a/flutter_google_places_sdk_platform_interface/lib/flutter_google_places_sdk_platform.dart +++ b/flutter_google_places_sdk_platform_interface/lib/flutter_google_places_sdk_platform.dart @@ -40,13 +40,13 @@ abstract class FlutterGooglePlacesSdkPlatform extends PlatformInterface { throw UnimplementedError('deinitialize() has not been implemented.'); } - /// Initializes Places for the given application context with the given API key. + /// Initializes Places for the given application context with the given API key. Use [useNewApi] to enable the Places API (New) in the SDK /// /// All Places API responses are localized using the device's locale. /// This method should only be called once prior to using the Places API. /// You may call this method again to update the API key used; /// if so, all widgets and instances of PlacesClient will now use this new key. - Future initialize(String apiKey, {Locale? locale}) { + Future initialize(String apiKey, {Locale? locale, bool? useNewApi}) { throw UnimplementedError('initialize() has not been implemented.'); } @@ -56,7 +56,7 @@ abstract class FlutterGooglePlacesSdkPlatform extends PlatformInterface { } /// Updates the settings of the places client with the given API key and locale. - Future updateSettings(String apiKey, {Locale? locale}) { + Future updateSettings(String apiKey, {Locale? locale, bool? useNewApi}) { throw UnimplementedError('initialize() has not been implemented.'); } @@ -117,4 +117,53 @@ abstract class FlutterGooglePlacesSdkPlatform extends PlatformInterface { }) { throw UnimplementedError('fetchPlacePhoto() has not been implemented.'); } + + /// Fetches places based on an ambiguous text query. + /// + /// Only the requested [fields] will be returned. If none specified, + /// all fields will be returned. + /// + /// Note that different fields can incur different billing. + /// + /// For more info about billing: https://developers.google.com/maps/documentation/places/android-sdk/usage-and-billing#pricing-new + /// + /// For more info on text search: https://developers.google.com/maps/documentation/places/android-sdk/text-search + Future searchByText( + String textQuery, { + required List fields, + String? includedType, + int? maxResultCount, + LatLngBounds? locationBias, + LatLngBounds? locationRestriction, + double? minRating, + bool? openNow, + List? priceLevels, + TextSearchRankPreference? rankPreference, + String? regionCode, + bool? strictTypeFiltering, + }) { + throw UnimplementedError('fetchPlacePhoto() has not been implemented.'); + } + + /// Search for place(s) of interest using a location. + /// + /// Only the requested [fields] will be returned. If none specified, + /// all fields will be returned. + /// + /// Note that different fields can incur different billing. + /// + /// For more info on nearby search: https://developers.google.com/maps/documentation/places/android-sdk/nearby-search + Future searchNearby({ + required List fields, + required CircularBounds locationRestriction, + List? includedTypes, + List? includedPrimaryTypes, + List? excludedTypes, + List? excludedPrimaryTypes, + NearbySearchRankPreference? rankPreference, + String? regionCode, + int? maxResultCount, + }) { + throw UnimplementedError('searchNearby() has not been implemented.'); + } } diff --git a/flutter_google_places_sdk_platform_interface/lib/method_channel_flutter_google_places_sdk.dart b/flutter_google_places_sdk_platform_interface/lib/method_channel_flutter_google_places_sdk.dart index bcdce40..92d5a75 100644 --- a/flutter_google_places_sdk_platform_interface/lib/method_channel_flutter_google_places_sdk.dart +++ b/flutter_google_places_sdk_platform_interface/lib/method_channel_flutter_google_places_sdk.dart @@ -19,8 +19,8 @@ class FlutterGooglePlacesSdkMethodChannel } @override - Future initialize(String apiKey, {Locale? locale}) { - return _invokeForSettings('initialize', apiKey, locale); + Future initialize(String apiKey, {Locale? locale, bool? useNewApi}) { + return _invokeForSettings('initialize', apiKey, locale, useNewApi); } @override @@ -29,19 +29,25 @@ class FlutterGooglePlacesSdkMethodChannel } @override - Future updateSettings(String apiKey, {Locale? locale}) { - return _invokeForSettings('updateSettings', apiKey, locale); + Future updateSettings(String apiKey, {Locale? locale, bool? useNewApi}) { + return _invokeForSettings('updateSettings', apiKey, locale, useNewApi); } - Future _invokeForSettings(String methodName, String apiKey, Locale? locale) { + Future _invokeForSettings( + String methodName, + String apiKey, + Locale? locale, + bool? useNewApi, + ) { return _channel.invokeMethod(methodName, { 'apiKey': apiKey, + 'useNewApi': useNewApi ?? false, 'locale': locale == null ? null : { - 'country': locale.countryCode, - 'language': locale.languageCode, - }, + 'country': locale.countryCode, + 'language': locale.languageCode, + }, }); } @@ -143,4 +149,83 @@ class FlutterGooglePlacesSdkMethodChannel details: 'Response: $value', ); } + + @override + Future searchByText( + String textQuery, { + required List fields, + String? includedType, + int? maxResultCount, + LatLngBounds? locationBias, + LatLngBounds? locationRestriction, + double? minRating, + bool? openNow, + List? priceLevels, + TextSearchRankPreference? rankPreference, + String? regionCode, + bool? strictTypeFiltering, + }) { + if (textQuery.isEmpty) { + throw ArgumentError('Argument query can not be empty'); + } + return _channel.invokeListMethod>( + 'searchByText', + { + 'textQuery': textQuery, + 'fields': fields.map((e) => e.value).toList(), + 'includedType': includedType, + 'maxResultCount': maxResultCount, + 'locationBias': locationBias?.toJson(), + 'locationRestriction': locationRestriction?.toJson(), + 'minRating': minRating, + 'openNow': openNow, + 'priceLevels': priceLevels, + 'rankPreference': rankPreference?.value, + 'regionCode': regionCode, + 'strictTypeFiltering': strictTypeFiltering, + }, + ).then(_responseFromTextSearch); + } + + SearchByTextResponse _responseFromTextSearch(List>? value) { + final items = + value?.map((item) => item.cast()).map((map) => Place.fromJson(map)).toList(growable: false) ?? + []; + return SearchByTextResponse(items); + } + + @override + Future searchNearby({ + required List fields, + required CircularBounds locationRestriction, + List? includedTypes, + List? includedPrimaryTypes, + List? excludedTypes, + List? excludedPrimaryTypes, + NearbySearchRankPreference? rankPreference, + String? regionCode, + int? maxResultCount, + }) { + return _channel.invokeListMethod>( + 'searchNearby', + { + 'fields': fields.map((e) => e.value).toList(), + 'locationRestriction': locationRestriction.toJson(), + 'includedTypes': includedTypes, + 'includedPrimaryTypes': includedPrimaryTypes, + 'excludedTypes': excludedTypes, + 'excludedPrimaryTypes': excludedPrimaryTypes, + 'rankPreference': rankPreference?.value, + 'regionCode': regionCode, + 'maxResultCount': maxResultCount, + }, + ).then(_responseFromNearbySearch); + } + + SearchNearbyResponse _responseFromNearbySearch(List>? value) { + final items = + value?.map((item) => item.cast()).map((map) => Place.fromJson(map)).toList(growable: false) ?? + []; + return SearchNearbyResponse(items); + } } diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/author_attribution.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/author_attribution.dart new file mode 100644 index 0000000..be85ef6 --- /dev/null +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/author_attribution.dart @@ -0,0 +1,24 @@ + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'author_attribution.freezed.dart'; +part 'author_attribution.g.dart'; + +@Freezed() +class AuthorAttribution with _$AuthorAttribution { + /// Constructs a [AuthorAttribution] object. + const factory AuthorAttribution({ + /// The name of the author. + required String name, + + /// The profile photo URI of the author. + required String photoUri, + + /// The URI of the author. + required String uri, + }) = _AuthorAttribution; + + /// Parse an [AuthorAttribution] from json. + factory AuthorAttribution.fromJson(Map json) => + _$AuthorAttributionFromJson(json); +} diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/circular_bounds.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/circular_bounds.dart new file mode 100644 index 0000000..a6d615e --- /dev/null +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/circular_bounds.dart @@ -0,0 +1,19 @@ +import 'package:flutter_google_places_sdk_platform_interface/src/types/lat_lng.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'circular_bounds.freezed.dart'; +part 'circular_bounds.g.dart'; + +/// An immutable class representing a latitude/longitude aligned circle, with a defined radius. +@Freezed() +class CircularBounds with _$CircularBounds { + /// constructs a [CircularBounds] object. + const factory CircularBounds({ + required LatLng center, + required double radius, + }) = _CircularBounds; + + /// Parse an [CircularBounds] from json. + factory CircularBounds.fromJson(Map json) => + _$CircularBoundsFromJson(json); +} diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/place.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/place.dart index f1e3215..7ec6b2d 100644 --- a/flutter_google_places_sdk_platform_interface/lib/src/types/place.dart +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/place.dart @@ -6,6 +6,7 @@ import 'package:flutter_google_places_sdk_platform_interface/src/types/opening_h import 'package:flutter_google_places_sdk_platform_interface/src/types/photo_metadata.dart'; import 'package:flutter_google_places_sdk_platform_interface/src/types/place_type.dart'; import 'package:flutter_google_places_sdk_platform_interface/src/types/plus_code.dart'; +import 'package:flutter_google_places_sdk_platform_interface/src/types/review.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'place.freezed.dart'; @@ -28,6 +29,7 @@ class Place with _$Place { required List? attributions, required LatLng? latLng, required String? name, + required String? nameLanguageCode, required OpeningHours? openingHours, required String? phoneNumber, required List? photoMetadatas, @@ -39,6 +41,7 @@ class Place with _$Place { required int? utcOffsetMinutes, required LatLngBounds? viewport, required Uri? websiteUri, + required List? reviews, }) = _Place; /// Parse an [Place] from json. diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/place_field.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/place_field.dart index 798d942..04fa87b 100644 --- a/flutter_google_places_sdk_platform_interface/lib/src/types/place_field.dart +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/place_field.dart @@ -23,8 +23,28 @@ enum PlaceField { UserRatingsTotal, @JsonValue('UTC_OFFSET') UTCOffset, Viewport, - WebsiteUri - ; + WebsiteUri, + + /// Places (new) API + CurbsidePickup, + CurrentOpeningHours, + Delivery, + DineIn, + EditorialSummary, + IconBackgroundColor, + IconUrl, + Reservable, + Reviews, + SecondaryOpeningHours, + ServesBeer, + ServesBreakfast, + ServesBrunch, + ServesDinner, + ServesLunch, + ServesVegetarianFood, + ServesWine, + Takeout, + WheelchairAccessibleEntrance; factory PlaceField.fromJson(String name) { name = name.toLowerCase(); @@ -39,4 +59,4 @@ enum PlaceField { extension PlaceFieldValue on PlaceField { String get value => _$PlaceFieldEnumMap[this]!; -} \ No newline at end of file +} diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/place_type.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/place_type.dart index c7f41cb..1d1a8ea 100644 --- a/flutter_google_places_sdk_platform_interface/lib/src/types/place_type.dart +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/place_type.dart @@ -143,8 +143,103 @@ enum PlaceType { TRAVEL_AGENCY, UNIVERSITY, VETERINARY_CARE, - ZOO - ; + ZOO, + /// Places (new) types + AMERICAN_RESTAURANT, + DISCOUNT_STORE, + ICE_CREAM_SHOP, + SANDWICH_SHOP, + AMUSEMENT_CENTER, + DOG_PARK, + INDIAN_RESTAURANT, + SCHOOL_DISTRICT, + ATHLETIC_FIELD, + ELECTRIC_VEHICLE_CHARGING_STATION, + INDONESIAN_RESTAURANT, + SEAFOOD_RESTAURANT, + AUTO_PARTS_STORE, + EVENT_VENUE, + ITALIAN_RESTAURANT, + SKI_RESORT, + BANQUET_HALL, + EXTENDED_STAY_HOTEL, + JAPANESE_RESTAURANT, + SPANISH_RESTAURANT, + BARBECUE_RESTAURANT, + FARM, + KOREAN_RESTAURANT, + SPORTING_GOODS_STORE, + BARBER_SHOP, + FARMSTAY, + LEBANESE_RESTAURANT, + SPORTS_CLUB, + BED_AND_BREAKFAST, + FAST_FOOD_RESTAURANT, + MARINA, + SPORTS_COMPLEX, + BRAZILIAN_RESTAURANT, + FERRY_TERMINAL, + MARKET, + STEAK_HOUSE, + BREAKFAST_RESTAURANT, + FITNESS_CENTER, + MEDICAL_LAB, + SUSHI_RESTAURANT, + BRUNCH_RESTAURANT, + FRENCH_RESTAURANT, + MEDITERRANEAN_RESTAURANT, + SWIMMING_POOL, + BUS_STOP, + GIFT_SHOP, + MEXICAN_RESTAURANT, + TAILOR, + CAMPING_CABIN, + GOLF_COURSE, + MIDDLE_EASTERN_RESTAURANT, + TELECOMMUNICATIONS_SERVICE_PROVIDER, + CELL_PHONE_STORE, + GREEK_RESTAURANT, + MOTEL, + THAI_RESTAURANT, + CHILD_CARE_AGENCY, + GROCERY_STORE, + NATIONAL_PARK, + TRANSIT_DEPOT, + CHINESE_RESTAURANT, + GUEST_HOUSE, + PARK_AND_RIDE, + TRUCK_STOP, + COFFEE_SHOP, + HAIR_SALON, + PERFORMING_ARTS_THEATER, + TURKISH_RESTAURANT, + COMMUNITY_CENTER, + HAMBURGER_RESTAURANT, + PIZZA_RESTAURANT, + VEGAN_RESTAURANT, + CONSULTANT, + HELIPORT, + PLAYGROUND, + VEGETARIAN_RESTAURANT, + CONVENTION_CENTER, + HIKING_AREA, + PRESCHOOL, + VIETNAMESE_RESTAURANT, + COTTAGE, + HISTORICAL_LANDMARK, + PRIVATE_GUEST_ROOM, + VISITOR_CENTER, + COURIER_SERVICE, + HOME_IMPROVEMENT_STORE, + RAMEN_RESTAURANT, + WEDDING_VENUE, + CULTURAL_CENTER, + HOSTEL, + RESORT_HOTEL, + WHOLESALER, + DENTAL_CLINIC, + HOTEL, + REST_STOP; factory PlaceType.fromJson(String name) { name = name.toLowerCase(); @@ -157,10 +252,7 @@ enum PlaceType { } } -final placeTypeValuesMap = { - for (final placeType in PlaceType.values) - placeType.name: placeType -}; +final placeTypeValuesMap = {for (final placeType in PlaceType.values) placeType.name: placeType}; extension PlaceTypeDescriptor on PlaceType { String get value => toString(); diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/place_type_filter.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/place_type_filter.dart index 598deba..4ff3261 100644 --- a/flutter_google_places_sdk_platform_interface/lib/src/types/place_type_filter.dart +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/place_type_filter.dart @@ -28,8 +28,7 @@ enum PlaceTypeFilter { /// COUNTRY /// ADMINISTRATIVE_AREA_LEVEL_1 /// ADMINISTRATIVE_AREA_LEVEL_2 - REGIONS - ; + REGIONS; factory PlaceTypeFilter.fromJson(String name) { name = name.toLowerCase(); diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/rank_preference.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/rank_preference.dart new file mode 100644 index 0000000..85c86a6 --- /dev/null +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/rank_preference.dart @@ -0,0 +1,43 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'rank_preference.g.dart'; + +@JsonEnum(fieldRename: FieldRename.screamingSnake, alwaysCreate: true) +enum TextSearchRankPreference { + Distance, + Relevance; + + factory TextSearchRankPreference.fromJson(String name) { + name = name.toLowerCase(); + for (final value in values) { + if (value.name.toLowerCase() == name) { + return value; + } + } + throw ArgumentError.value(name, 'name', 'No enum value with that name'); + } +} + +extension TextSearchRankPreferenceValue on TextSearchRankPreference { + String get value => _$TextSearchRankPreferenceEnumMap[this]!; +} + +@JsonEnum(fieldRename: FieldRename.screamingSnake, alwaysCreate: true) +enum NearbySearchRankPreference { + Distance, + Popularity; + + factory NearbySearchRankPreference.fromJson(String name) { + name = name.toLowerCase(); + for (final value in values) { + if (value.name.toLowerCase() == name) { + return value; + } + } + throw ArgumentError.value(name, 'name', 'No enum value with that name'); + } +} + +extension NearbySearchRankPreferenceValue on NearbySearchRankPreference { + String get value => _$NearbySearchRankPreferenceEnumMap[this]!; +} diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/review.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/review.dart new file mode 100644 index 0000000..23efe0a --- /dev/null +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/review.dart @@ -0,0 +1,41 @@ +import 'package:flutter_google_places_sdk_platform_interface/src/types/author_attribution.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'review.freezed.dart'; +part 'review.g.dart'; + +@Freezed() +class Review with _$Review { + /// Constructs a [Review] object. + const factory Review({ + /// The attribution that must be shown to the user if this review is displayed. + required String attribution, + + /// This review's AuthorAttribution. + required AuthorAttribution authorAttribution, + + /// A whole number between 1.0 and 5.0 (inclusive), meaning the number of stars. + required double rating, + + /// The publish time for the review, expressed in "yyyy-MM-dd HH:mm:ss" format of UTC timezone. + required String publishTime, + + /// A human-readable description of the relative publish time of a review, such as "a month ago", or "in the last week", based on the time elapsed. + required String relativePublishTimeDescription, + + /// The text of the review in its original language. + String? originalText, + + /// The language code of the original text of the review. + String? originalTextLanguageCode, + + /// The text of the review. + String? text, + + /// The language code of the text of the review. + String? textLanguageCode, + }) = _Review; + + /// Parse a [Review] from json. + factory Review.fromJson(Map json) => _$ReviewFromJson(json); +} diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/search_by_text_response.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/search_by_text_response.dart new file mode 100644 index 0000000..f3be118 --- /dev/null +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/search_by_text_response.dart @@ -0,0 +1,14 @@ +import 'package:flutter_google_places_sdk_platform_interface/flutter_google_places_sdk_platform_interface.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'search_by_text_response.freezed.dart'; + +/// The response for a [FlutterGooglePlacesSdkPlatform.searchByText] request +@Freezed() +class SearchByTextResponse with _$SearchByTextResponse { + /// constructs a [SearchByTextResponse] object. + const factory SearchByTextResponse( + /// the Place list returned by the response. + List places, + ) = _SearchByTextResponse; +} diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/search_nearby_response.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/search_nearby_response.dart new file mode 100644 index 0000000..883760e --- /dev/null +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/search_nearby_response.dart @@ -0,0 +1,14 @@ +import 'package:flutter_google_places_sdk_platform_interface/flutter_google_places_sdk_platform_interface.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'search_nearby_response.freezed.dart'; + +/// The response for a [FlutterGooglePlacesSdkPlatform.searchNearby] request +@Freezed() +class SearchNearbyResponse with _$SearchNearbyResponse { + /// constructs a [SearchNearbyResponse] object. + const factory SearchNearbyResponse( + /// the Place list returned by the response. + List places, + ) = _SearchNearbyResponse; +} diff --git a/flutter_google_places_sdk_platform_interface/lib/src/types/types.dart b/flutter_google_places_sdk_platform_interface/lib/src/types/types.dart index 18c4a19..4248de5 100644 --- a/flutter_google_places_sdk_platform_interface/lib/src/types/types.dart +++ b/flutter_google_places_sdk_platform_interface/lib/src/types/types.dart @@ -1,6 +1,8 @@ export 'address_component.dart'; +export 'author_attribution.dart'; export 'autocomplete_predictions.dart'; export 'business_status.dart'; +export 'circular_bounds.dart'; export 'day_of_week.dart'; export 'fetch_photo_response.dart'; export 'fetch_place_response.dart'; @@ -16,4 +18,8 @@ export 'place_local_time.dart'; export 'place_type.dart'; export 'place_type_filter.dart'; export 'plus_code.dart'; +export 'rank_preference.dart'; +export 'review.dart'; +export 'search_by_text_response.dart'; +export 'search_nearby_response.dart'; export 'time_of_week.dart'; diff --git a/flutter_google_places_sdk_platform_interface/pubspec.yaml b/flutter_google_places_sdk_platform_interface/pubspec.yaml index 204e833..c1e4620 100644 --- a/flutter_google_places_sdk_platform_interface/pubspec.yaml +++ b/flutter_google_places_sdk_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_google_places_sdk_platform_interface description: A common platform interface for accessing google maps native sdk on various platforms -version: 0.2.7 +version: 0.3.0 homepage: https://github.com/matanshukry/flutter_google_places_sdk/tree/master/flutter_google_places_sdk_platform_interface environment: diff --git a/flutter_google_places_sdk_platform_interface/test/method_channel_flutter_google_places_sdk_test.dart b/flutter_google_places_sdk_platform_interface/test/method_channel_flutter_google_places_sdk_test.dart index 963843d..6fd4a7e 100644 --- a/flutter_google_places_sdk_platform_interface/test/method_channel_flutter_google_places_sdk_test.dart +++ b/flutter_google_places_sdk_platform_interface/test/method_channel_flutter_google_places_sdk_test.dart @@ -15,17 +15,19 @@ void main() { const channel = MethodChannel('plugins.msh.com/flutter_google_places_sdk'); final List log = []; - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(channel, (MethodCall methodCall) async { - log.add(methodCall); - for (final callback in handlers) { - final result = callback(methodCall); - if (result != null) { - return result; + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( + channel, + (MethodCall methodCall) async { + log.add(methodCall); + for (final callback in handlers) { + final result = callback(methodCall); + if (result != null) { + return result; + } } - } - return null; - }); + return null; + }, + ); final places = FlutterGooglePlacesSdkMethodChannel(); @@ -41,6 +43,7 @@ void main() { [ isMethodCall('initialize', arguments: { 'apiKey': testKey, + 'useNewApi': false, 'locale': { 'country': null, 'language': 'en', @@ -71,12 +74,10 @@ void main() { const testCountries = ['c1', 'c2']; const newSessionToken = true; const origin = LatLng(lat: 325.21, lng: -952.52); - const locationBias = LatLngBounds( - southwest: LatLng(lat: 125.43, lng: 38.32), - northeast: LatLng(lat: -38.271, lng: 312.53)); - const locationRestriction = LatLngBounds( - southwest: LatLng(lat: 49.28, lng: 3921.38), - northeast: LatLng(lat: 38.64, lng: 23.32)); + const locationBias = + LatLngBounds(southwest: LatLng(lat: 125.43, lng: 38.32), northeast: LatLng(lat: -38.271, lng: 312.53)); + const locationRestriction = + LatLngBounds(southwest: LatLng(lat: 49.28, lng: 3921.38), northeast: LatLng(lat: 38.64, lng: 23.32)); await places.findAutocompletePredictions(testQuery, countries: testCountries, placeTypesFilter: ['(cities)'], @@ -87,16 +88,15 @@ void main() { expect( log, [ - isMethodCall('findAutocompletePredictions', - arguments: { - 'query': testQuery, - 'countries': testCountries, - 'typesFilter': ['(cities)'], - 'newSessionToken': newSessionToken, - 'origin': origin.toJson(), - 'locationBias': locationBias.toJson(), - 'locationRestriction': locationRestriction.toJson(), - }) + isMethodCall('findAutocompletePredictions', arguments: { + 'query': testQuery, + 'countries': testCountries, + 'typesFilter': ['(cities)'], + 'newSessionToken': newSessionToken, + 'origin': origin.toJson(), + 'locationBias': locationBias.toJson(), + 'locationRestriction': locationRestriction.toJson(), + }) ], ); }); @@ -137,11 +137,7 @@ void main() { test('fetchPlacePhoto', () async { const photoRef = 'http://google.com/photo/ref/1'; - const photoMetadata = PhotoMetadata( - photoReference: photoRef, - width: 100, - height: 100, - attributions: 'attr'); + const photoMetadata = PhotoMetadata(photoReference: photoRef, width: 100, height: 100, attributions: 'attr'); const maxWidth = 50; // Mock @@ -156,8 +152,7 @@ void main() { handlers.add(handler); try { // call - await places.fetchPlacePhoto(photoMetadata, - maxWidth: maxWidth, maxHeight: null); + await places.fetchPlacePhoto(photoMetadata, maxWidth: maxWidth, maxHeight: null); expect( log, @@ -177,6 +172,88 @@ void main() { handlers.remove(handler); } }); + + test('searchByText', () async { + const testQuery = 'my-test-query'; + const locationBias = + LatLngBounds(southwest: LatLng(lat: 125.43, lng: 38.32), northeast: LatLng(lat: -38.271, lng: 312.53)); + const locationRestriction = + LatLngBounds(southwest: LatLng(lat: 49.28, lng: 3921.38), northeast: LatLng(lat: 38.64, lng: 23.32)); + await places.searchByText( + testQuery, + fields: [PlaceField.Id, PlaceField.Name], + openNow: true, + regionCode: 'eu', + rankPreference: TextSearchRankPreference.Distance, + minRating: 1.0, + maxResultCount: 9, + locationBias: locationBias, + locationRestriction: locationRestriction, + priceLevels: [1, 2, 3], + strictTypeFiltering: false, + includedType: 'test', + ); + expect( + log, + [ + isMethodCall( + 'searchByText', + arguments: { + 'textQuery': testQuery, + 'fields': ['ID', 'NAME'], + 'includedType': 'test', + 'maxResultCount': 9, + 'locationBias': locationBias.toJson(), + 'locationRestriction': locationRestriction.toJson(), + 'minRating': 1.0, + 'openNow': true, + 'priceLevels': [1, 2, 3], + 'rankPreference': 'DISTANCE', + 'regionCode': 'eu', + 'strictTypeFiltering': false, + }, + ) + ], + ); + }); + + test('searchNearby', () async { + const types = ['test1', 'test2']; + const locationRestriction = CircularBounds( + center: LatLng(lat: 125.43, lng: 38.32), + radius: 1000, + ); + await places.searchNearby( + fields: [PlaceField.Id, PlaceField.Name], + locationRestriction: locationRestriction, + includedTypes: types, + includedPrimaryTypes: types, + excludedTypes: types, + excludedPrimaryTypes: types, + rankPreference: NearbySearchRankPreference.Popularity, + maxResultCount: 3, + regionCode: 'us'); + + expect( + log, + [ + isMethodCall( + 'searchNearby', + arguments: { + 'fields': ['ID', 'NAME'], + 'locationRestriction': locationRestriction.toJson(), + 'includedTypes': types, + 'includedPrimaryTypes': types, + 'excludedTypes': types, + 'excludedPrimaryTypes': types, + 'rankPreference': 'POPULARITY', + 'regionCode': 'us', + 'maxResultCount': 3, + }, + ) + ], + ); + }); }); }