diff --git a/CHANGELOG.md b/CHANGELOG.md index e5cf6fc..aa6ed6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# [4.0.0-beta.1] - 25 April 2023 +## Breaking Changes +- PlaceSearch and ReverseGeoCoding classes are now merged into one class called GeoCoding with two methods `getPlaces` and `getAddress` since both of them are using the same API. + +## New Features +- MapBox's new [SearchBox API](https://docs.mapbox.com/api/search/search-box/) is added to the package. +- Overal code refactoring + # [3.2.0] - 21 April 2023 - Added BBox in Forward Geododing API (As per MapBox API we can use BBox to get the results in a specific area) @@ -17,7 +25,7 @@ - Homepage URL fixed ## [3.0.1] - 14 Sep 2021 -- Added [Places type]((https://docs.mapbox.com/api/search/geocoding/#data-types)) to filter Search [PR #48] +- Added [Places type](https://docs.mapbox.com/api/search/geocoding/#data-types) to filter Search [PR #48] ## [3.0.0-nullsafety.0] - 07 Mar 2021 - Migrate to null safety [Pull Request #43] diff --git a/README.md b/README.md index 2b405dd..0abfca3 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,14 @@ [![Pub](https://img.shields.io/pub/v/mapbox_search)](https://pub.dev/packages/mapbox_search) # About +## Note: Breaking Changes in 4.x.x + +- PlaceSearch and ReverseGeoCoding classes are now merged into one class called GeoCoding with two methods `getPlaces` and `getAddress` since both of them are using the same API. +- MapBox's new [SearchBox API](https://docs.mapbox.com/api/search/search-box/) is added to the package. + This package provides easy api calls to MapBox Search API. -Also, it contains an static map image generator 😆. +Also, it contains an static map image generator. [Maki Icons](https://labs.mapbox.com/maki-icons/) can be used now in marker icon @@ -26,9 +31,36 @@ Then, add the following to your `pubspec.yaml` file: # Examples +### SearchBox API +```dart +SearchBoxAPI search = SearchBoxAPI( + apiKey: MAPBOX_KEY, + limit: 6, +); +``` + ##### Get Suggestions + ```dart + SuggestionResponse searchPlace = await search.getSuggestions( + "central", + ); + ``` + + ##### Get mapbox_id + - From SuggestionResponse + ```dart + String mapboxId = searchPlace.suggestions[0].mapboxId; + ``` + + ##### Get Place Details + ```dart + RetrieveResonse searchPlace = await search.getPlace(mapboxId); + ``` + + + ### Reverse GeoCoding ```dart -var reverseGeoCoding = ReverseGeoCoding( +var reverseGeoCoding = GeoCoding( apiKey: 'API Key', limit: 5, ); @@ -38,16 +70,24 @@ Future> geAddress() => Location(lat: 72.0, lng: 76.00), ); ``` - -### Places Seach + +### Forward GeoCoding Seach ```dart -var placesSearch = PlacesSearch( +var geocoding = GeoCoding( apiKey: 'API Key', + country: "BR", limit: 5, + types: [PlaceType.address, PlaceType.place], ); Future> getPlaces() => - placesSearch.getPlaces("New York"); + geocoding.getPlaces( + "central park", + proximity: Location( + lat: -19.984634, + lng: -43.9502958, + ), + ); ``` ### Static Image @@ -108,8 +148,3 @@ String getStaticImageWithoutMarker() => staticImage.getStaticUrlWithoutMarker( Static Map Image -## Search Widget - -Demo - -Demo diff --git a/Screenshots/search1.png b/Screenshots/search1.png deleted file mode 100644 index 114672c..0000000 Binary files a/Screenshots/search1.png and /dev/null differ diff --git a/Screenshots/search2.png b/Screenshots/search2.png deleted file mode 100644 index 8467fa2..0000000 Binary files a/Screenshots/search2.png and /dev/null differ diff --git a/example/main.dart b/example/main.dart index d59446f..4bf2748 100644 --- a/example/main.dart +++ b/example/main.dart @@ -1,10 +1,12 @@ +import 'dart:core'; + import 'package:mapbox_search/mapbox_search.dart'; // import 'credentials.dart'; final MAPBOX_KEY = ''; Future main() async { - String apiKey = MAPBOX_KEY; //Set up a test api key before running + final apiKey = MAPBOX_KEY; //Set up a test api key before running await geoCoding(apiKey).catchError(print); await placesSearch(apiKey).catchError(print); @@ -12,7 +14,7 @@ Future main() async { ///Reverse GeoCoding sample call Future geoCoding(String apiKey) async { - var geoCodingService = ReverseGeoCoding( + var geoCodingService = GeoCoding( apiKey: apiKey, country: "BR", limit: 5, @@ -28,7 +30,7 @@ Future geoCoding(String apiKey) async { ///Places search sample call Future placesSearch(String apiKey) async { - var placesService = PlacesSearch( + var placesService = GeoCoding( apiKey: apiKey, country: "BR", limit: 5, @@ -36,7 +38,7 @@ Future placesSearch(String apiKey) async { var places = await placesService.getPlaces( "patio", - location: Location( + proximity: Location( lat: -19.984634, lng: -43.9502958, ), diff --git a/example/pubspec.lock b/example/pubspec.lock new file mode 100644 index 0000000..d5d68f8 --- /dev/null +++ b/example/pubspec.lock @@ -0,0 +1,108 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + http: + dependency: transitive + description: + name: http + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" + source: hosted + version: "0.13.5" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + mapbox_search: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "3.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + uuid: + dependency: transitive + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" +sdks: + dart: ">=2.18.0 <3.0.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml new file mode 100644 index 0000000..6c175b8 --- /dev/null +++ b/example/pubspec.yaml @@ -0,0 +1,13 @@ +name: example +description: A Flutter package for place search using MapBox Api and for Static map image +version: 1.0.0 +publish_to: "none" # Remove this line if you wish to publish to pub.dev + +homepage: https://github.com/ketanchoyal/mapbox_search + +environment: + sdk: ">=2.17.0 <3.0.0" + +dependencies: + mapbox_search: + path: ../ diff --git a/lib/colors/cielab_color.dart b/lib/colors/cielab_color.dart index 47489a9..8ddfe9c 100644 --- a/lib/colors/cielab_color.dart +++ b/lib/colors/cielab_color.dart @@ -1,5 +1,6 @@ part of color; +/// A color in the CIELAB color space. class CielabColor extends Color { final num l; final num a; @@ -12,10 +13,13 @@ class CielabColor extends Color { return xyz.toRgbColor(); } + /// Converts the color to HSL color space. HslColor toHslColor() => this.toRgbColor().toHslColor(); + /// Converts the color to HSV color space. HsvColor toHsvColor() => this.toRgbColor().toHsvColor(); + /// Converts the color to XYZ color space. XyzColor toXyzColor() { Map xyz = { 'x': a / 500 + (l + 16) / 116, @@ -36,6 +40,7 @@ class CielabColor extends Color { return XyzColor(xyz['x']!, xyz['y']!, xyz['z']!); } + // Returns a CielabColor with the same color values as this Color. CielabColor toCielabColor() => this; String toString() => "l: $l, a: $a, b: $b"; diff --git a/lib/colors/color.dart b/lib/colors/color.dart index b4e8fb4..4e1c6f5 100644 --- a/lib/colors/color.dart +++ b/lib/colors/color.dart @@ -50,7 +50,8 @@ abstract class Color { return 256 * 256 * rgb.r.toInt() + 256 * rgb.g.toInt() + rgb.b.toInt(); } - operator ==(Object other) => other is Color && this.hashCode == other.hashCode; + operator ==(Object other) => + other is Color && this.hashCode == other.hashCode; operator [](String key) => this.toMap()[key]; diff --git a/lib/colors/color_filter.dart b/lib/colors/color_filter.dart index f2998c3..f82de11 100644 --- a/lib/colors/color_filter.dart +++ b/lib/colors/color_filter.dart @@ -11,10 +11,11 @@ class ColorFilter { /** * Makes the color lighter by the percentage specified in the first argument, or by 10% if no percentage is specified. Percentages should be specified as a float, e.g. an argument of 0.25 will result in a color 25% lighter than the original. The lightening conversion is performed by adjusting the y component of the color in XYZ color space. */ - static ColorFilter lighten = new ColorFilter((Color inputColor, [List? args]) { + static ColorFilter lighten = + new ColorFilter((Color inputColor, [List? args]) { CielabColor color = inputColor.toCielabColor(); num percent = 0.1; - if (args is List && args.length > 0 && args[0] is num) { + if (args is List && args.isNotEmpty && args[0] is num) { percent = args[0]; } return new CielabColor(color.l * (1 + percent), color.a, color.b); @@ -37,15 +38,21 @@ class ColorFilter { */ static ColorFilter sepia = new ColorFilter((Color baseColor, [List? args]) { RgbColor color = baseColor.toRgbColor(); - return new RgbColor(min(RgbColor.rMax, (color.r * 0.393 + color.g * 0.769 + color.b * 0.189)), - min(RgbColor.gMax, (color.r * 0.349 + color.g * 0.686 + color.b * 0.168)), - min(RgbColor.bMax, (color.r * 0.272 + color.g * 0.534 + color.b * 0.131))).toCielabColor(); + return new RgbColor( + min(RgbColor.rMax, + (color.r * 0.393 + color.g * 0.769 + color.b * 0.189)), + min(RgbColor.gMax, + (color.r * 0.349 + color.g * 0.686 + color.b * 0.168)), + min(RgbColor.bMax, + (color.r * 0.272 + color.g * 0.534 + color.b * 0.131))) + .toCielabColor(); }, RgbColor); /** * Creates a greyscale color with the same perceived luminance as the source color (as given by the L* value of the color in the CieLAB color space). */ - static ColorFilter greyscale = new ColorFilter((Color inputColor, [List? args]) { + static ColorFilter greyscale = + new ColorFilter((Color inputColor, [List? args]) { CielabColor color = inputColor.toCielabColor(); num rgbLevel = color.l * 255 / 100; return new RgbColor(rgbLevel, rgbLevel, rgbLevel).toCielabColor(); diff --git a/lib/colors/color_parser.dart b/lib/colors/color_parser.dart index 19724cf..ab02b5e 100644 --- a/lib/colors/color_parser.dart +++ b/lib/colors/color_parser.dart @@ -1,18 +1,35 @@ part of color; class ColorParser { - static final RegExp _beginsHash = new RegExp("^#"); static final RegExp _hexColorRegExp = new RegExp("^#?([\\da-fA-F]{6})\$"); - static final RegExp _hexColorAbbreviatedRegExp = new RegExp("^#?([\\da-fA-F]{3})\$"); - static final RegExp _rgbColorImplicitRegExp = new RegExp("^(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\$"); - static final RegExp _rgbColorExplicitRegExp = new RegExp("^rgb\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*\\)\$"); - static final RegExp _hslColorRegExp = new RegExp("^hsl\\(\\s*(\\d{1,3})\\s*,\\s*(\\d+(\\.\\d*)?|\\.\\d+)%\\s*,\\s*(\\d+(\\.\\d*)?|\\.\\d+)%\\s*\\)\$"); - - - Color? parse(String toParse, { Color orElse()? }) { + static final RegExp _hexColorAbbreviatedRegExp = + new RegExp("^#?([\\da-fA-F]{3})\$"); + static final RegExp _rgbColorImplicitRegExp = + new RegExp("^(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\$"); + static final RegExp _rgbColorExplicitRegExp = new RegExp( + "^rgb\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*\\)\$"); + static final RegExp _hslColorRegExp = new RegExp( + "^hsl\\(\\s*(\\d{1,3})\\s*,\\s*(\\d+(\\.\\d*)?|\\.\\d+)%\\s*,\\s*(\\d+(\\.\\d*)?|\\.\\d+)%\\s*\\)\$"); + + ///* The code above does the following: + ///1. Trim the string to parse + ///2. If it starts with #, it is a hex color + ///3. If it matches the hex color regexp, it is a hex color + ///4. If it matches the abbreviated hex color regexp, it is a hex color + ///5. If it matches the rgb regexp, it is an rgb color + ///6. If it matches the rgb regexp, it is an rgb color + ///7. If it matches the hsl regexp, it is an hsl color + ///8. If it matches the named regexp, it is a named color + ///9. If none of the above are true, return null or the fallback color */ + Color? parse(String toParse, {Color orElse()?}) { toParse = toParse.trim(); - return _parseRgb(toParse) ?? _parseHex(toParse) ?? _parseHsl(toParse) ?? _parseNamed(toParse) ?? orElse?.call() ?? null; + return _parseRgb(toParse) ?? + _parseHex(toParse) ?? + _parseHsl(toParse) ?? + _parseNamed(toParse) ?? + orElse?.call() ?? + null; } Color? _parseHex(String toParse) { @@ -21,7 +38,11 @@ class ColorParser { } if (_hexColorAbbreviatedRegExp.hasMatch(toParse)) { - String _unAbbreviated = new String.fromCharCodes(toParse.replaceFirst(_beginsHash, "").codeUnits.map((c) => [c, c]).expand((c) => c)); + String _unAbbreviated = new String.fromCharCodes(toParse + .replaceFirst(_beginsHash, "") + .codeUnits + .map((c) => [c, c]) + .expand((c) => c)); return new HexColor(_unAbbreviated); } @@ -29,7 +50,6 @@ class ColorParser { } Color? _parseHsl(String toParse) { - if (_hslColorRegExp.hasMatch(toParse)) { Match match = _hslColorRegExp.allMatches(toParse).first; return new HslColor( @@ -42,15 +62,16 @@ class ColorParser { } Color? _parseRgb(String toParse) { - if (_rgbColorImplicitRegExp.hasMatch(toParse)) { Match match = _rgbColorImplicitRegExp.allMatches(toParse).first; - return new RgbColor(int.parse(match.group(1)!), int.parse(match.group(2)!), int.parse(match.group(3)!)); + return new RgbColor(int.parse(match.group(1)!), + int.parse(match.group(2)!), int.parse(match.group(3)!)); } if (_rgbColorExplicitRegExp.hasMatch(toParse)) { Match match = _rgbColorExplicitRegExp.allMatches(toParse).first; - return new RgbColor(int.parse(match.group(1)!), int.parse(match.group(2)!), int.parse(match.group(3)!)); + return new RgbColor(int.parse(match.group(1)!), + int.parse(match.group(2)!), int.parse(match.group(3)!)); } return null; @@ -63,5 +84,4 @@ class ColorParser { return null; } } - -} \ No newline at end of file +} diff --git a/lib/colors/css_color_space.dart b/lib/colors/css_color_space.dart index 1d31097..d2f1cde 100644 --- a/lib/colors/css_color_space.dart +++ b/lib/colors/css_color_space.dart @@ -1,7 +1,5 @@ part of color; abstract class CssColorSpace { - String toCssString(); - } diff --git a/lib/colors/hex_color.dart b/lib/colors/hex_color.dart index ec9f044..fe5b4ba 100644 --- a/lib/colors/hex_color.dart +++ b/lib/colors/hex_color.dart @@ -1,7 +1,6 @@ part of color; class HexColor extends RgbColor implements CssColorSpace { - /** * Creates a [HexColor] using a [String] describing its RGB value in hex. * diff --git a/lib/generated_enums/poi_category.dart b/lib/generated_enums/poi_category.dart new file mode 100644 index 0000000..321ea90 --- /dev/null +++ b/lib/generated_enums/poi_category.dart @@ -0,0 +1,445 @@ +/// This file is auto-generated. Do not modify it manually. + +enum POICategory { + advertisingAgency('advertising_agency'), + africanRestaurant('african_restaurant'), + airport('airport'), + airportGate('airport_gate'), + airportTerminal('airport_terminal'), + alternativeHealthcare('alternative_healthcare'), + americanRestaurant('american_restaurant'), + animalShelter('animal_shelter'), + antiqueShop('antique_shop'), + aquarium('aquarium'), + arcade('arcade'), + art('art'), + artGallery('art_gallery'), + artsAndCraftStore('arts_and_craft_store'), + artsCenter('arts_center'), + asianRestaurant('asian_restaurant'), + assistedLivingFacility('assisted_living_facility'), + atm('atm'), + autoRepair('auto_repair'), + babyGoodsShop('baby_goods_shop'), + bagelShop('bagel_shop'), + baggageClaim('baggage_claim'), + bakery('bakery'), + bank('bank'), + bar('bar'), + barbequeRestaurant('barbeque_restaurant'), + baseballField('baseball_field'), + baseballStadium('baseball_stadium'), + basketballCourt('basketball_court'), + basketballStadium('basketball_stadium'), + beach('beach'), + beachBar('beach_bar'), + beautyStore('beauty_store'), + bedAndBreakfast('bed_and_breakfast'), + beerBar('beer_bar'), + bicycleShop('bicycle_shop'), + biergarten('biergarten'), + bikeRental('bike_rental'), + billiards('billiards'), + boatRental('boat_rental'), + bookStore('book_store'), + bookmaker('bookmaker'), + boutique('boutique'), + bowlingAlley('bowling_alley'), + boxingGym('boxing_gym'), + brazilianRestaurant('brazilian_restaurant'), + breakfastRestaurant('breakfast_restaurant'), + brewery('brewery'), + bridalShop('bridal_shop'), + bridge('bridge'), + brunchRestaurant('brunch_restaurant'), + bubbleTea('bubble_tea'), + buffetRestaurant('buffet_restaurant'), + burgerRestaurant('burger_restaurant'), + busStation('bus_station'), + busStop('bus_stop'), + butcherShop('butcher_shop'), + cafe('cafe'), + cameraShop('camera_shop'), + campground('campground'), + canal('canal'), + cannabisDispensary('cannabis_dispensary'), + carDealership('car_dealership'), + carRental('car_rental'), + carWash('car_wash'), + careServices('care_services'), + carpetCleaner('carpet_cleaner'), + carpetStore('carpet_store'), + carribeanRestaurant('carribean_restaurant'), + casino('casino'), + cave('cave'), + cemetery('cemetery'), + chairlift('chairlift'), + champagneBar('champagne_bar'), + chargingStation('charging_station'), + charity('charity'), + checkCashing('check_cashing'), + cheeseShop('cheese_shop'), + childcare('childcare'), + chineseRestaurant('chinese_restaurant'), + chiropractor('chiropractor'), + chocolateShop('chocolate_shop'), + church('church'), + cinema('cinema'), + climbing('climbing'), + climbingGym('climbing_gym'), + clothing('clothing'), + clothingStore('clothing_store'), + cobbler('cobbler'), + cocktailBar('cocktail_bar'), + coffee('coffee'), + coffeeRoaster('coffee_roaster'), + coffeeShop('coffee_shop'), + college('college'), + communityCenter('community_center'), + communityCollege('community_college'), + concertHall('concert_hall'), + conferenceCenter('conference_center'), + convenienceStore('convenience_store'), + copyshop('copyshop'), + counselling('counselling'), + courthouse('courthouse'), + coworkingSpace('coworking_space'), + creoleRestaurant('creole_restaurant'), + cricketClub('cricket_club'), + cruise('cruise'), + cubanRestaurant('cuban_restaurant'), + currencyExchange('currency_exchange'), + danceStudio('dance_studio'), + deli('deli'), + dentist('dentist'), + departmentStore('department_store'), + designStudio('design_studio'), + dessertShop('dessert_shop'), + dialysisCenter('dialysis_center'), + dinerRestaurant('diner_restaurant'), + discGolfCourse('disc_golf_course'), + discountStore('discount_store'), + distillery('distillery'), + diveBar('dive_bar'), + doctorsOffice('doctors_office'), + dogPark('dog_park'), + donutShop('donut_shop'), + dormitory('dormitory'), + drivingRange('driving_range'), + drivingSchool('driving_school'), + dryCleaners('dry_cleaners'), + dutyFreeShop('duty_free_shop'), + education('education'), + electronicsShop('electronics_shop'), + elementarySchool('elementary_school'), + embassy('embassy'), + emergencyRoom('emergency_room'), + employmentAgency('employment_agency'), + englishRestaurant('english_restaurant'), + entertainment('entertainment'), + equipmentRental('equipment_rental'), + eventPlanner('event_planner'), + eventSpace('event_space'), + exhibit('exhibit'), + fabricStore('fabric_store'), + factory('factory'), + fairGrounds('fair_grounds'), + farm('farm'), + fashionAccessoryShop('fashion_accessory_shop'), + fastFood('fast_food'), + field('field'), + filipinoRestaurant('filipino_restaurant'), + financialServices('financial_services'), + fireStation('fire_station'), + fireworksStore('fireworks_store'), + fishAndChipsRestaurant('fish_and_chips_restaurant'), + fishing('fishing'), + fishingStore('fishing_store'), + fishmonger('fishmonger'), + fitnessCenter('fitness_center'), + florist('florist'), + food('food'), + foodAndDrink('food_and_drink'), + foodCourt('food_court'), + foodTruck('food_truck'), + footballStadium('football_stadium'), + forest('forest'), + fountain('fountain'), + frameStore('frame_store'), + frenchRestaurant('french_restaurant'), + frozenYogurtShop('frozen_yogurt_shop'), + funeralHome('funeral_home'), + furnitureMaker('furniture_maker'), + furnitureStore('furniture_store'), + garden('garden'), + gardenStore('garden_store'), + gasStation('gas_station'), + gastropub('gastropub'), + gayBar('gay_bar'), + germanRestaurant('german_restaurant'), + giftShop('gift_shop'), + goKartRacing('go_kart_racing'), + golfCourse('golf_course'), + government('government'), + governmentOffices('government_offices'), + greekRestaurant('greek_restaurant'), + grocery('grocery'), + gunStore('gun_store'), + gymnastics('gymnastics'), + hairdresser('hairdresser'), + hardwareStore('hardware_store'), + hawaiianRestaurant('hawaiian_restaurant'), + healthFoodStore('health_food_store'), + healthServices('health_services'), + herbalist('herbalist'), + highSchool('high_school'), + historicSite('historic_site'), + hobbyShop('hobby_shop'), + hockeyStadium('hockey_stadium'), + homeRepair('home_repair'), + hookahLounge('hookah_lounge'), + hospital('hospital'), + hostel('hostel'), + hotDogStand('hot_dog_stand'), + hotel('hotel'), + hotelBar('hotel_bar'), + huntingStore('hunting_store'), + iceCream('ice_cream'), + iceRink('ice_rink'), + indianRestaurant('indian_restaurant'), + indonesianRestaurant('indonesian_restaurant'), + indoorCycling('indoor_cycling'), + informationTechnologyCompany('information_technology_company'), + insuranceBroker('insurance_broker'), + internetCafe('internet_cafe'), + island('island'), + italianRestaurant('italian_restaurant'), + japaneseRestaurant('japanese_restaurant'), + jewelryStore('jewelry_store'), + juiceBar('juice_bar'), + karaokeBar('karaoke_bar'), + kindergarten('kindergarten'), + kitchenStore('kitchen_store'), + koreanBarbequeRestaurant('korean_barbeque_restaurant'), + koreanRestaurant('korean_restaurant'), + laboratory('laboratory'), + lake('lake'), + landscaping('landscaping'), + languageSchool('language_school'), + laserTag('laser_tag'), + latinAmericanRestaurant('latin_american_restaurant'), + laundry('laundry'), + lawyer('lawyer'), + leatherGoods('leather_goods'), + library('library'), + lighthouse('lighthouse'), + lightingStore('lighting_store'), + liquorStore('liquor_store'), + locksmith('locksmith'), + lodging('lodging'), + lounge('lounge'), + luggageStore('luggage_store'), + marina('marina'), + market('market'), + martialArtsStudio('martial_arts_studio'), + massageShop('massage_shop'), + mattressStore('mattress_store'), + medicalClinic('medical_clinic'), + medicalLaboratory('medical_laboratory'), + medicalPractice('medical_practice'), + medicalSupplyStore('medical_supply_store'), + mediterraneanRestaurant('mediterranean_restaurant'), + mexicanRestaurant('mexican_restaurant'), + middleEasternRestaurant('middle_eastern_restaurant'), + militaryBase('military_base'), + miniatureGolf('miniature_golf'), + monument('monument'), + mosque('mosque'), + motel('motel'), + motorcycleDealer('motorcycle_dealer'), + motorsportsStore('motorsports_store'), + mountain('mountain'), + museum('museum'), + musicSchool('music_school'), + musicShop('music_shop'), + musicVenue('music_venue'), + nailSalon('nail_salon'), + natureReserve('nature_reserve'), + newsKiosk('news_kiosk'), + nightclub('nightclub'), + nightlife('nightlife'), + nongovernmentalOrganization('nongovernmental_organization'), + noodleRestaurant('noodle_restaurant'), + notary('notary'), + observatory('observatory'), + office('office'), + optician('optician'), + optometrist('optometrist'), + outdoors('outdoors'), + outdoorsStore('outdoors_store'), + outletStore('outlet_store'), + paperGoodsStore('paper_goods_store'), + park('park'), + parkingLot('parking_lot'), + partyStore('party_store'), + pawnshop('pawnshop'), + peruvianRestaurant('peruvian_restaurant'), + petStore('pet_store'), + pharmacy('pharmacy'), + phoneStore('phone_store'), + photoLab('photo_lab'), + photoStore('photo_store'), + photographer('photographer'), + physiotherapist('physiotherapist'), + pier('pier'), + pilatesStudio('pilates_studio'), + pizzaRestaurant('pizza_restaurant'), + placeOfWorship('place_of_worship'), + planetarium('planetarium'), + playground('playground'), + plaza('plaza'), + policeStation('police_station'), + politicalPartyOffice('political_party_office'), + popUpShop('pop_up_shop'), + portugueseRestaurant('portuguese_restaurant'), + postOffice('post_office'), + prison('prison'), + psychic('psychic'), + psychologicalServices('psychological_services'), + psychotherapist('psychotherapist'), + pub('pub'), + publicArtwork('public_artwork'), + publicTransportationStation('public_transportation_station'), + racetrack('racetrack'), + radioStudio('radio_studio'), + railwayPlatform('railway_platform'), + railwayStation('railway_station'), + ramenRestaurant('ramen_restaurant'), + realEstateAgent('real_estate_agent'), + recordingStudio('recording_studio'), + recreationCenter('recreation_center'), + recyclingCenter('recycling_center'), + rehabilitationCenter('rehabilitation_center'), + repairShop('repair_shop'), + resort('resort'), + restArea('rest_area'), + restaurant('restaurant'), + river('river'), + sakeBar('sake_bar'), + saladBar('salad_bar'), + salon('salon'), + sandwichShop('sandwich_shop'), + school('school'), + scubaDivingShop('scuba_diving_shop'), + seafoodRestaurant('seafood_restaurant'), + services('services'), + sewingShop('sewing_shop'), + shippingStore('shipping_store'), + shoeRepair('shoe_repair'), + shoeStore('shoe_store'), + shopping('shopping'), + shoppingMall('shopping_mall'), + skatepark('skatepark'), + skiArea('ski_area'), + skiShop('ski_shop'), + snackBar('snack_bar'), + soccerField('soccer_field'), + socialClub('social_club'), + spa('spa'), + spanishRestaurant('spanish_restaurant'), + speakeasy('speakeasy'), + sports('sports'), + sportsBar('sports_bar'), + sportsCenter('sports_center'), + sportsClub('sports_club'), + sportsShop('sports_shop'), + stable('stable'), + stadium('stadium'), + steakhouse('steakhouse'), + storage('storage'), + stripclub('stripclub'), + studio('studio'), + summerCamp('summer_camp'), + supermarket('supermarket'), + surfSpot('surf_spot'), + surfboardStore('surfboard_store'), + sushiRestaurant('sushi_restaurant'), + swimmingPool('swimming_pool'), + synagogue('synagogue'), + tacoShop('taco_shop'), + tailor('tailor'), + tanningSalon('tanning_salon'), + tapasRestaurant('tapas_restaurant'), + tattooParlour('tattoo_parlour'), + taxAdvisor('tax_advisor'), + taxi('taxi'), + teahouse('teahouse'), + televisionStudio('television_studio'), + temple('temple'), + tennisCourts('tennis_courts'), + thaiRestaurant('thai_restaurant'), + theatre('theatre'), + themePark('theme_park'), + themeParkAttraction('theme_park_attraction'), + thriftShop('thrift_shop'), + tikiBar('tiki_bar'), + tobaccoShop('tobacco_shop'), + touristAttraction('tourist_attraction'), + touristInformation('tourist_information'), + tours('tours'), + townhall('townhall'), + toyStore('toy_store'), + track('track'), + tradeSchool('trade_school'), + trailhead('trailhead'), + transportation('transportation'), + travelAgency('travel agency'), + treecare('treecare'), + tunnel('tunnel'), + turkishCoffeehouse('turkish_coffeehouse'), + turkishRestaurant('turkish_restaurant'), + tutor('tutor'), + university('university'), + universityBookStore('university_book_store'), + universityBuilding('university_building'), + universityLaboratory('university_laboratory'), + vacationRental('vacation_rental'), + vapeShop('vape_shop'), + varietyStore('variety_store'), + veterinarian('veterinarian'), + videoGameStore('video_game_store'), + videoStore('video_store'), + vietnameseRestaurant('vietnamese_restaurant'), + viewpoint('viewpoint'), + vineyard('vineyard'), + warehouse('warehouse'), + wasteDisposal('waste_disposal'), + wasteTransferStation('waste_transfer_station'), + watchStore('watch_store'), + waterPark('water_park'), + waterfall('waterfall'), + whiskeyBar('whiskey_bar'), + wholesaleStore('wholesale_store'), + windmill('windmill'), + wineBar('wine_bar'), + winery('winery'), + wingsJoint('wings_joint'), + womensClothingStore('womens_clothing_store'), + yogaStudio('yoga_studio'), + zoo('zoo'), + zooExhibit('zoo_exhibit'); + + const POICategory(this.value); + final String value; +} + +extension POICategoryExtension on POICategory { + POICategory? fromString(String? value) { + if (value == null) return null; + try { + return POICategory.values.firstWhere((e) => e.value == value); + } catch (e) { + return null; + } + } +} diff --git a/lib/mapbox_search.dart b/lib/mapbox_search.dart index 5b29e97..9c52fd0 100644 --- a/lib/mapbox_search.dart +++ b/lib/mapbox_search.dart @@ -3,19 +3,19 @@ library mapbox_search; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:mapbox_search/colors/color.dart'; +import 'package:uuid/uuid.dart'; +import 'generated_enums/poi_category.dart'; -part 'src/location.dart'; - -part 'src/predictions.dart'; +part 'models/predictions.dart'; +part 'models/location_context.dart'; +part 'models/geometry.dart'; +part 'models/suggestion_response.dart'; +part 'models/retrieve_response.dart'; +part 'src/location.dart'; part 'src/bbox.dart'; - part 'src/static_image.dart'; - -part 'src/reverse_geocoding.dart'; - -part 'src/places_search.dart'; - +part 'src/search_box_api.dart'; +part 'src/geocoding_api.dart'; part "src/maki_icons.dart"; - -part 'src/types.dart'; +part 'src/place_types.dart'; diff --git a/lib/models/geometry.dart b/lib/models/geometry.dart new file mode 100644 index 0000000..c0b7e84 --- /dev/null +++ b/lib/models/geometry.dart @@ -0,0 +1,22 @@ +part of mapbox_search; + +class Geometry { + Geometry({ + required this.coordinates, + required this.type, + }); + + final List coordinates; + final String type; + + factory Geometry.fromJson(Map json) => Geometry( + coordinates: + List.from(json["coordinates"].map((x) => x?.toDouble())), + type: json["type"], + ); + + Map toJson() => { + "coordinates": List.from(coordinates.map((x) => x)), + "type": type, + }; +} diff --git a/lib/models/location_context.dart b/lib/models/location_context.dart new file mode 100644 index 0000000..bdf0709 --- /dev/null +++ b/lib/models/location_context.dart @@ -0,0 +1,139 @@ +part of mapbox_search; + +class Context { + Context({ + required this.country, + this.region, + required this.postcode, + this.district, + required this.place, + this.neighborhood, + this.street, + }); + + final Country country; + final Region? region; + final Place? postcode; + final Place? district; + final Place? place; + final Neighborhood? neighborhood; + final Neighborhood? street; + + factory Context.fromJson(Map json) => Context( + country: Country.fromJson(json["country"]), + region: json["region"] == null ? null : Region.fromJson(json["region"]), + postcode: + json["postcode"] == null ? null : Place.fromJson(json["postcode"]), + district: + json["district"] == null ? null : Place.fromJson(json["district"]), + place: json["place"] == null ? null : Place.fromJson(json["place"]), + neighborhood: json["neighborhood"] == null + ? null + : Neighborhood.fromJson(json["neighborhood"]), + street: json["street"] == null + ? null + : Neighborhood.fromJson(json["street"]), + ); + + Map toJson() => { + "country": country.toJson(), + "region": region?.toJson(), + "postcode": postcode?.toJson(), + "district": district?.toJson(), + "place": place?.toJson(), + "neighborhood": neighborhood?.toJson(), + "street": street?.toJson(), + }; +} + +class Country { + Country({ + required this.id, + required this.name, + required this.countryCode, + required this.countryCodeAlpha3, + }); + + final String? id; + final String name; + final String countryCode; + final String countryCodeAlpha3; + + factory Country.fromJson(Map json) => Country( + id: json["id"], + name: json["name"], + countryCode: json["country_code"], + countryCodeAlpha3: json["country_code_alpha_3"], + ); + + Map toJson() => { + "id": id, + "name": name, + "country_code": countryCode, + "country_code_alpha_3": countryCodeAlpha3, + }; +} + +class Region { + Region({ + required this.id, + required this.name, + required this.regionCode, + required this.regionCodeFull, + }); + + final String? id; + final String name; + final String regionCode; + final String regionCodeFull; + + factory Region.fromJson(Map json) => Region( + id: json["id"], + name: json["name"], + regionCode: json["region_code"], + regionCodeFull: json["region_code_full"], + ); + + Map toJson() => { + "id": id, + "name": name, + "region_code": regionCode, + "region_code_full": regionCodeFull, + }; +} + +class Neighborhood { + Neighborhood({ + required this.name, + }); + + final String name; + + factory Neighborhood.fromJson(Map json) => Neighborhood( + name: json["name"], + ); + + Map toJson() => { + "name": name, + }; +} + +class Place { + Place({ + this.id, + required this.name, + }); + + final String? id; + final String name; + + factory Place.fromJson(Map json) => Place( + id: json["id"], + name: json["name"], + ); + + Map toJson() => { + "id": id, + "name": name, + }; +} diff --git a/lib/src/predictions.dart b/lib/models/predictions.dart similarity index 61% rename from lib/src/predictions.dart rename to lib/models/predictions.dart index 3b60590..622bcc5 100644 --- a/lib/src/predictions.dart +++ b/lib/models/predictions.dart @@ -1,9 +1,9 @@ part of mapbox_search; class Predictions { - String? type; - List? query; - List? features; + final String? type; + final List? query; + final List? features; Predictions.prediction({ this.type, @@ -11,11 +11,11 @@ class Predictions { this.features, }); - Predictions.empty() { - this.type = ''; - this.features = []; - this.query = []; - } + factory Predictions.empty() => Predictions.prediction( + type: '', + query: [], + features: [], + ); factory Predictions.fromRawJson(String str) => Predictions.fromJson(json.decode(str)); @@ -38,26 +38,26 @@ class Predictions { } class MapBoxPlace { - String? id; - FeatureType? type; - List? placeType; + final String? id; + final FeatureType? type; + final List placeType; // dynamic relevance; - String? addressNumber; - Properties? properties; - String? text; - String? placeName; - List? bbox; - List? center; - Geometry? geometry; - List? context; - String? matchingText; - String? matchingPlaceName; + final String? addressNumber; + final Properties? properties; + final String? text; + final String? placeName; + final List? bbox; + final List? center; + final Geometry? geometry; + // final List? context; + final String? matchingText; + final String? matchingPlaceName; MapBoxPlace({ this.id, this.type, - this.placeType, + this.placeType = const [], // this.relevance, this.addressNumber, this.properties, @@ -66,7 +66,7 @@ class MapBoxPlace { this.bbox, this.center, this.geometry, - this.context, + // this.context, this.matchingText, this.matchingPlaceName, }); @@ -80,9 +80,9 @@ class MapBoxPlace { id: json["id"], type: json["type"] == null ? null : featureTypeValues.map[json["type"]], placeType: json["place_type"] == null - ? null + ? [] : List.from( - json["place_type"].map((x) => placeTypeValues.map[x])), + json["place_type"].map((x) => x.toString().placeType)), // relevance: json["relevance"] == null ? null : json["relevance"], addressNumber: json["address"], properties: json["properties"] == null @@ -99,10 +99,10 @@ class MapBoxPlace { geometry: json["geometry"] == null ? null : Geometry.fromJson(json["geometry"]), - context: json["context"] == null - ? null - : List.from( - json["context"].map((x) => Context.fromJson(x))), + // context: json["context"] == null + // ? null + // : List.from( + // json["context"].map((x) => Context.fromJson(x))), matchingText: json["matching_text"], matchingPlaceName: json["matching_place_name"], ); @@ -110,8 +110,7 @@ class MapBoxPlace { Map toJson() => { "id": id, "type": featureTypeValues.reverse![type!], - "place_type": List.from( - placeType!.map((x) => placeTypeValues.reverse![x])), + "place_type": List.from(placeType.map((x) => x?.value)), // "relevance": relevance, "address": addressNumber, "properties": properties!.toJson(), @@ -120,9 +119,9 @@ class MapBoxPlace { "bbox": List.from(bbox!.map((x) => x)), "center": List.from(center!.map((x) => x)), "geometry": geometry!.toJson(), - "context": context == null - ? null - : List.from(context!.map((x) => x.toJson())), + // "context": context == null + // ? null + // : List.from(context!.map((x) => x.toJson())), "matching_text": matchingText == null ? null : matchingText, "matching_place_name": matchingPlaceName == null ? null : matchingPlaceName, @@ -132,80 +131,42 @@ class MapBoxPlace { String toString() => text ?? placeName!; } -class Context { - String? id; - String? shortCode; - String? wikidata; - String? text; - - Context({ - this.id, - this.shortCode, - this.wikidata, - this.text, - }); - - factory Context.fromRawJson(String str) => Context.fromJson(json.decode(str)); - - String toRawJson() => json.encode(toJson()); - - factory Context.fromJson(Map json) => Context( - id: json["id"], - shortCode: json["short_code"], - wikidata: json["wikidata"], - text: json["text"], - ); - - Map toJson() => { - "id": id, - "short_code": shortCode, - "wikidata": wikidata, - "text": text, - }; -} - -class Geometry { - GeometryType? type; - List? coordinates; - - Geometry({ - this.type, - this.coordinates, - }); - - factory Geometry.fromRawJson(String str) => - Geometry.fromJson(json.decode(str)); - - String toRawJson() => json.encode(toJson()); - - factory Geometry.fromJson(Map json) => Geometry( - type: geometryTypeValues.map[json["type"]], - coordinates: - List.from(json["coordinates"].map((x) => x.toDouble())), - ); - - Map toJson() => { - "type": geometryTypeValues.reverse![type!], - "coordinates": List.from(coordinates!.map((x) => x)), - }; -} +// class Context { +// String? id; +// String? shortCode; +// String? wikidata; +// String? text; + +// Context({ +// this.id, +// this.shortCode, +// this.wikidata, +// this.text, +// }); + +// factory Context.fromRawJson(String str) => Context.fromJson(json.decode(str)); + +// String toRawJson() => json.encode(toJson()); + +// factory Context.fromJson(Map json) => Context( +// id: json["id"], +// shortCode: json["short_code"], +// wikidata: json["wikidata"], +// text: json["text"], +// ); + +// Map toJson() => { +// "id": id, +// "short_code": shortCode, +// "wikidata": wikidata, +// "text": text, +// }; +// } enum GeometryType { POINT } final geometryTypeValues = EnumValues({"Point": GeometryType.POINT}); -final placeTypeValues = EnumValues({ - "country": PlaceType.country, - "place": PlaceType.place, - "region": PlaceType.region, - "postcode": PlaceType.postcode, - "district": PlaceType.district, - "locality": PlaceType.locality, - "neighborhood": PlaceType.neighborhood, - "address": PlaceType.address, - "poi": PlaceType.poi, -}); - class Properties { String? shortCode; String? wikidata; diff --git a/lib/models/retrieve_response.dart b/lib/models/retrieve_response.dart new file mode 100644 index 0000000..1cae698 --- /dev/null +++ b/lib/models/retrieve_response.dart @@ -0,0 +1,145 @@ +part of mapbox_search; + +String retrieveResonseToJson(RetrieveResonse data) => + json.encode(data.toJson()); + +class RetrieveResonse { + RetrieveResonse({ + required this.type, + required this.features, + required this.attribution, + required this.url, + }); + + final String type; + final List features; + final String attribution; + final String? url; + + factory RetrieveResonse.fromJson(Map json) => + RetrieveResonse( + type: json["type"], + features: List.from( + json["features"].map((x) => Feature.fromJson(x))), + attribution: json["attribution"], + url: json["url"], + ); + factory RetrieveResonse.fromRawJson(String str) => + RetrieveResonse.fromJson(json.decode(str)); + + Map toJson() => { + "type": type, + "features": List.from(features.map((x) => x.toJson())), + "attribution": attribution, + "url": url, + }; +} + +class Feature { + Feature({ + required this.type, + required this.geometry, + required this.properties, + }); + + final String type; + final Geometry geometry; + final Properties properties; + + factory Feature.fromJson(Map json) => Feature( + type: json["type"], + geometry: Geometry.fromJson(json["geometry"]), + properties: Properties.fromJson(json["properties"]), + ); + + Map toJson() => { + "type": type, + "geometry": geometry.toJson(), + "properties": properties.toJson(), + }; +} + +class RetrieveProperties { + RetrieveProperties({ + required this.name, + required this.mapboxId, + required this.featureType, + required this.address, + required this.fullAddress, + required this.placeFormatted, + required this.context, + required this.coordinates, + required this.bbox, + required this.language, + required this.maki, + required this.externalIds, + required this.metadata, + }); + + final String name; + final String mapboxId; + final String featureType; + final String address; + final String fullAddress; + final String placeFormatted; + final Context context; + final Coordinates coordinates; + final List bbox; + final String language; + final String maki; + final ExternalIds externalIds; + final ExternalIds metadata; + + factory RetrieveProperties.fromJson(Map json) => + RetrieveProperties( + name: json["name"], + mapboxId: json["mapbox_id"], + featureType: json["feature_type"], + address: json["address"], + fullAddress: json["full_address"], + placeFormatted: json["place_formatted"], + context: Context.fromJson(json["context"]), + coordinates: Coordinates.fromJson(json["coordinates"]), + bbox: List.from(json["bbox"].map((x) => x?.toDouble())), + language: json["language"], + maki: json["maki"], + externalIds: ExternalIds.fromJson(json["external_ids"]), + metadata: ExternalIds.fromJson(json["metadata"]), + ); + + Map toJson() => { + "name": name, + "mapbox_id": mapboxId, + "feature_type": featureType, + "address": address, + "full_address": fullAddress, + "place_formatted": placeFormatted, + "context": context.toJson(), + "coordinates": coordinates.toJson(), + "bbox": List.from(bbox.map((x) => x)), + "language": language, + "maki": maki, + "external_ids": externalIds.toJson(), + "metadata": metadata.toJson(), + }; +} + +class Coordinates { + Coordinates({ + required this.latitude, + required this.longitude, + }); + + final double latitude; + final double longitude; + + factory Coordinates.fromJson(Map json) => Coordinates( + latitude: json["latitude"]?.toDouble(), + longitude: json["longitude"]?.toDouble(), + ); + + Map toJson() => { + "latitude": latitude, + "longitude": longitude, + }; +} diff --git a/lib/models/suggestion_response.dart b/lib/models/suggestion_response.dart new file mode 100644 index 0000000..f49a363 --- /dev/null +++ b/lib/models/suggestion_response.dart @@ -0,0 +1,135 @@ +part of mapbox_search; + +String suggestionResponseToJson(SuggestionResponse data) => + json.encode(data.toJson()); + +class SuggestionResponse { + SuggestionResponse({ + required this.suggestions, + required this.attribution, + required this.url, + }); + + final List suggestions; + final String attribution; + final String? url; + + factory SuggestionResponse.fromJson(Map json) => + SuggestionResponse( + suggestions: List.from( + json["suggestions"].map((x) => Suggestion.fromJson(x))), + attribution: json["attribution"], + url: json["url"], + ); + + factory SuggestionResponse.fromRawJson(String str) => + SuggestionResponse.fromJson(json.decode(str)); + + Map toJson() => { + "suggestions": List.from(suggestions.map((x) => x.toJson())), + "attribution": attribution, + "url": url, + }; +} + +class Suggestion { + Suggestion({ + required this.name, + this.namePreferred, + required this.mapboxId, + required this.featureType, + required this.address, + required this.fullAddress, + required this.placeFormatted, + required this.context, + required this.language, + required this.maki, + required this.externalIds, + this.poiCategory, + this.poiCategoryIds, + this.brand, + this.brandId, + }); + + final String name; + final String? namePreferred; + final String mapboxId; + final String featureType; + final String address; + final String fullAddress; + final String placeFormatted; + final Context context; + final String language; + final String maki; + final ExternalIds externalIds; + final List? poiCategory; + final List? poiCategoryIds; + final List? brand; + final String? brandId; + + factory Suggestion.fromJson(Map json) => Suggestion( + name: json["name"], + namePreferred: json["name_preferred"], + mapboxId: json["mapbox_id"], + featureType: json["feature_type"], + address: json["address"], + fullAddress: json["full_address"], + placeFormatted: json["place_formatted"], + context: Context.fromJson(json["context"]), + language: json["language"], + maki: json["maki"], + externalIds: ExternalIds.fromJson(json["external_ids"]), + poiCategory: json["poi_category"] == null + ? [] + : List.from(json["poi_category"]!.map((x) => x)), + poiCategoryIds: json["poi_category_ids"] == null + ? [] + : List.from(json["poi_category_ids"]!.map((x) => x)), + brand: json["brand"] == null + ? [] + : List.from(json["brand"]!.map((x) => x)), + brandId: json["brand_id"], + ); + + Map toJson() => { + "name": name, + "name_preferred": namePreferred, + "mapbox_id": mapboxId, + "feature_type": featureType, + "address": address, + "full_address": fullAddress, + "place_formatted": placeFormatted, + "context": context.toJson(), + "language": language, + "maki": maki, + "external_ids": externalIds.toJson(), + "poi_category": poiCategory == null + ? [] + : List.from(poiCategory!.map((x) => x)), + "poi_category_ids": poiCategoryIds == null + ? [] + : List.from(poiCategoryIds!.map((x) => x)), + "brand": brand == null ? [] : List.from(brand!.map((x) => x)), + "brand_id": brandId, + }; +} + +class ExternalIds { + ExternalIds({ + this.foursquare, + this.safegraph, + }); + + final String? foursquare; + final String? safegraph; + + factory ExternalIds.fromJson(Map json) => ExternalIds( + foursquare: json["foursquare"], + safegraph: json["safegraph"], + ); + + Map toJson() => { + "foursquare": foursquare, + "safegraph": safegraph, + }; +} diff --git a/lib/src/places_search.dart b/lib/src/geocoding_api.dart similarity index 74% rename from lib/src/places_search.dart rename to lib/src/geocoding_api.dart index eba954b..5522e31 100644 --- a/lib/src/places_search.dart +++ b/lib/src/geocoding_api.dart @@ -1,6 +1,10 @@ part of mapbox_search; -class PlacesSearch { +/// The MapBox Geocoding API lets you convert location text into geographic coordinates (1600 Pennsylvania Ave NW → -77.0366,38.8971) +/// and vice versa (reverse geocoding). +/// +/// https://docs.mapbox.com/api/search/geocoding/ +class GeoCoding { /// API Key of the MapBox. final String apiKey; @@ -25,17 +29,17 @@ class PlacesSearch { /// Multiple options can be comma-separated. /// /// For more information on the available types, see the [data types section](https://docs.mapbox.com/api/search/geocoding/#data-types). - final List? types; + final List types; final Uri _baseUri = Uri.parse('https://api.mapbox.com/geocoding/v5/mapbox.places/'); - PlacesSearch({ + GeoCoding({ required this.apiKey, this.country, this.limit, this.language, - this.types, + this.types = const [PlaceType.address], this.bbox, }); @@ -54,13 +58,14 @@ class PlacesSearch { if (country != null) 'country': country, if (limit != null) 'limit': limit.toString(), if (language != null) 'language': language, - if (types != null) 'types': types?.map((e) => e.value).join(','), + if (types.isNotEmpty) 'types': types.map((e) => e.value).join(','), if (bbox != null) 'bbox': bbox?.asString, }, ); return finalUri; } + /// Get the places for the given query text Future?> getPlaces( String queryText, { @Deprecated('Use `proximity` instead, if `proximity` value is passed then it will be used and this value will be ignored') @@ -80,7 +85,22 @@ class PlacesSearch { return Predictions.fromRawJson(response.body).features; } - PlacesSearch copyWith({ + /// Get the address of the given location coordinates + Future?> getAddress(Location location) async { + // Assert that if limit is not null then only one type is passed + assert(limit != null && (types.length == 1) || limit == null, + 'Limit is not null so you can only pass one type'); + Uri uri = _createUrl(location.asString); + final response = await http.get(uri); + + if (response.body.contains('message')) { + throw Exception(json.decode(response.body)['message']); + } + + return Predictions.fromRawJson(response.body).features; + } + + GeoCoding copyWith({ String? apiKey, String? language, String? country, @@ -88,7 +108,7 @@ class PlacesSearch { BBox? bbox, List? types, }) { - return PlacesSearch( + return GeoCoding( apiKey: apiKey ?? this.apiKey, language: language ?? this.language, country: country ?? this.country, diff --git a/lib/src/types.dart b/lib/src/place_types.dart similarity index 69% rename from lib/src/types.dart rename to lib/src/place_types.dart index bc1f8ff..c6b13e7 100644 --- a/lib/src/types.dart +++ b/lib/src/place_types.dart @@ -4,33 +4,60 @@ part of mapbox_search; ///The data types available in the geocoder, listed from the largest to the most granular, are: enum PlaceType { ///Generally recognized countries or, in some cases like Hong Kong, an area of quasi-national administrative status that has been given a designated country code under ISO 3166-1. - country, + country('country'), ///Top-level sub-national administrative features, such as states in the United States or provinces in Canada or China. - region, + region('region'), ///Postal codes used in country-specific national addressing systems. - postcode, + postcode('postcode'), ///Features that are smaller than top-level administrative features but typically larger than cities, in countries that use such an additional layer in postal addressing (for example, prefectures in China). - district, + district('district'), ///Typically these are cities, villages, municipalities, etc. They’re usually features used in postal addressing, and are suitable for display in ambient end-user applications where current-location context is needed (for example, in weather displays). - place, + place('place'), ///Official sub-city features present in countries where such an additional administrative layer is used in postal addressing, or where such features are commonly referred to in local parlance. Examples include city districts in Brazil and Chile and arrondissements in France. - locality, + locality('locality'), ///Colloquial sub-city features often referred to in local parlance. Unlike locality features, these typically lack official status and may lack universally agreed-upon boundaries. - neighborhood, + neighborhood('neighborhood'), ///Individual residential or business addresses. - address, + address('address'), ///Points of interest. These include restaurants, stores, concert venues, parks, museums, etc. - poi, + poi('poi'); + + const PlaceType(this.value); + + final String value; } -extension PlaceTypeX on PlaceType { - String get value => this.toString().split('.').last; +extension on String { + PlaceType? get placeType { + switch (this) { + case 'country': + return PlaceType.country; + case 'region': + return PlaceType.region; + case 'postcode': + return PlaceType.postcode; + case 'district': + return PlaceType.district; + case 'place': + return PlaceType.place; + case 'locality': + return PlaceType.locality; + case 'neighborhood': + return PlaceType.neighborhood; + case 'address': + return PlaceType.address; + case 'poi': + return PlaceType.poi; + default: + return null; + } + } } diff --git a/lib/src/reverse_geocoding.dart b/lib/src/reverse_geocoding.dart deleted file mode 100644 index bb6b03e..0000000 --- a/lib/src/reverse_geocoding.dart +++ /dev/null @@ -1,76 +0,0 @@ -part of mapbox_search; - -class ReverseGeoCoding { - /// API Key of the MapBox. - final String apiKey; - - /// Specify the user’s language. This parameter controls the language of the text supplied in responses. - /// - /// Check the full list of [supported languages](https://docs.mapbox.com/api/search/#language-coverage) for the MapBox API - final String? language; - - /// The point around which you wish to retrieve place information. - final Location? location; - - /// Specify the maximum number of results to return. Maximum supported is 10. - /// - /// If limit is not specified, the default is 1(MapBox Api default behaviour). - /// - /// If you wan to use limit then please just pass only one [PlaceType], this is a known limitiation of the MapBox API - final int? limit; - - ///Limit results to one or more countries. Permitted values are ISO 3166 alpha 2 country codes separated by commas. - /// - /// Check the full list of [supported countries](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) for the MapBox API - final String? country; - - /// Filter results to include only a subset (one or more) of the available feature types. - /// Options are country, region, postcode, district, place, locality, neighborhood, address, and poi. - /// Multiple options can be comma-separated. - /// - /// For more information on the available types, see the [data types section](https://docs.mapbox.com/api/search/geocoding/#data-types). - final List types; - - final Uri _baseUri = - Uri.parse('https://api.mapbox.com/geocoding/v5/mapbox.places/'); - - ReverseGeoCoding({ - required this.apiKey, - this.language, - this.location, - this.limit, - this.country, - this.types = const [PlaceType.address], - }); - - Uri _createUrl(Location location) { - final finalUri = Uri( - scheme: _baseUri.scheme, - host: _baseUri.host, - path: _baseUri.path + location.asString + '.json', - queryParameters: { - 'access_token': apiKey, - if (country != null) 'country': country, - if (limit != null) 'limit': limit.toString(), - if (language != null) 'language': language, - 'types': types.map((e) => e.value).join(','), - }, - ); - - return finalUri; - } - - Future?> getAddress(Location location) async { - // Assert that if limit is not null then only one type is passed - assert(limit != null && (types.length == 1) || limit == null, - 'Limit is not null so you can only pass one type'); - Uri uri = _createUrl(location); - final response = await http.get(uri); - - if (response.body.contains('message')) { - throw Exception(json.decode(response.body)['message']); - } - - return Predictions.fromRawJson(response.body).features; - } -} diff --git a/lib/src/search_box_api.dart b/lib/src/search_box_api.dart new file mode 100644 index 0000000..13f5abe --- /dev/null +++ b/lib/src/search_box_api.dart @@ -0,0 +1,114 @@ +part of mapbox_search; + +/// Search for places by name, point, bbox, proximity, and more. +/// +/// +/// https://docs.mapbox.com/api/search/search-box/ +/// +/// The Search Box API includes two different endpoints: `/suggest` and `/retrieve`. As the user types, text is sent to the `/suggest` endpoint to get suggested results. When the user selects a suggestion, its `mapbox_id` is sent to `/retrieve` to get the full data. +class SearchBoxAPI { + /// API Key of the MapBox. + final String apiKey; + + /// Specify the user’s language. This parameter controls the language of the text supplied in responses. + /// + /// Check the full list of [supported languages](https://docs.mapbox.com/api/search/#language-coverage) for the MapBox API + final String? language; + + ///Limit results to one or more countries. Permitted values are ISO 3166 alpha 2 country codes separated by commas. + /// + /// Check the full list of [supported countries](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) for the MapBox API + final String? country; + + /// Specify the maximum number of results to return. The default is 5 and the maximum supported is 10. + final int? limit; + + /// Limit results to only those contained within the supplied bounding box. + final BBox? bbox; + + /// Filter results to include only a subset (one or more) of the available feature types. + /// Options are country, region, postcode, district, place, locality, neighborhood, address, and poi. + /// Multiple options can be comma-separated. + /// + /// For more information on the available types, see the [data types section](https://docs.mapbox.com/api/search/geocoding/#data-types). + final List types; + + final Uri _baseUri = Uri.parse('https://api.mapbox.com/search/searchbox/v1/'); + + SearchBoxAPI({ + required this.apiKey, + this.country, + this.limit, + this.language, + this.types = const [], + this.bbox, + }); + + static String? _sessionToken; + + Uri _createUrl( + String queryOrId, [ + Proximity proximity = const LocationNone(), + bool isSuggestions = false, + List poi = const [], + ]) { + _sessionToken ??= Uuid().v1(); + final finalUri = Uri( + scheme: _baseUri.scheme, + host: _baseUri.host, + path: _baseUri.path + (isSuggestions ? 'suggest' : 'retrieve/$queryOrId'), + queryParameters: { + 'access_token': apiKey, + 'session_token': _sessionToken, + if (isSuggestions) ...{ + 'q': queryOrId, + if (proximity is Location) 'proximity': proximity.asString, + if (proximity is LocationIp) 'proximity': 'ip', + if (country != null) 'country': country, + if (limit != null) 'limit': limit.toString(), + if (language != null) 'language': language, + if (types.isNotEmpty) 'types': types.map((e) => e.value).join(','), + if (bbox != null) 'bbox': bbox?.asString, + if (poi.isNotEmpty) 'poi_category': poi.map((e) => e.value).join(','), + }, + }, + ); + return finalUri; + } + + /// Get a list of places that match the query. + Future getSuggestions( + String queryText, { + Proximity proximity = const LocationNone(), + List poi = const [], + }) async { + final uri = _createUrl(queryText, proximity, true, poi); + print(uri); + final response = await http.get(uri); + + if (response.body.contains('message')) { + throw Exception(json.decode(response.body)['message']); + } + + return SuggestionResponse.fromRawJson(response.body); + } + + /// Retrive a place by its `mapbox_id`. + Future getPlace(String mapboxId) async { + final uri = _createUrl(mapboxId); + final response = await http.get(uri); + + if (response.body.contains('message') || response.statusCode != 200) { + final decoded = json.decode(response.body) as Map; + if (decoded.containsKey('message')) { + throw Exception(decoded['message']); + } + if (decoded.containsKey('error')) { + throw Exception(decoded['error']); + } + throw Exception(json.decode(response.body)); + } + + return RetrieveResonse.fromRawJson(response.body); + } +} diff --git a/pubspec.lock b/pubspec.lock index c40427f..94e78c0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: be7703e270e48c2c5d654ef6fa013249b798d546074437d61c7c30af79c7d2b4 + sha256: "4d2a2c7f5e6db6acd2f4a7f713b308b45668c9573a11d0eda10936fb21fc5467" url: "https://pub.dev" source: hosted - version: "9.0.0" + version: "14.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: eb5945754e00d91b9dc842ce8c185b5f545819b187dd3aaf22f370716fb1b154 + sha256: "9fe5033adc3e8b19884e5ba296400be3794483acb53c2b68f8683744c9a7a9c7" url: "https://pub.dev" source: hosted - version: "0.40.1" + version: "0.41.2" args: dependency: transitive description: @@ -85,10 +85,10 @@ packages: dependency: transitive description: name: crypto - sha256: ebdb34c9171ea8e566dbed1800349c4135c33d2994de39d74206a8ad242f34a9 + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "3.0.2" glob: dependency: transitive description: @@ -353,6 +353,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + uuid: + dependency: "direct main" + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" vm_service: dependency: transitive description: @@ -373,10 +381,10 @@ packages: dependency: transitive description: name: web_socket_channel - sha256: "7712c6d1d3f1ad9b7f6da95c3898fd39c60592307475bef76f10ab388ec258de" + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "2.4.0" webkit_inspection_protocol: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f3a0d35..e91f781 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: mapbox_search description: A Flutter package for place search using MapBox Api and for Static map image -version: 3.2.0 +version: 4.0.0-beta.1 homepage: https://github.com/ketanchoyal/mapbox_search @@ -9,6 +9,7 @@ environment: dependencies: http: ^0.13.0 + uuid: ^3.0.7 dev_dependencies: pedantic: ^1.11.0 diff --git a/scripts/enum_generate_script.dart b/scripts/enum_generate_script.dart new file mode 100644 index 0000000..d3f895c --- /dev/null +++ b/scripts/enum_generate_script.dart @@ -0,0 +1,65 @@ +import 'dart:io'; + +import 'enum_values.dart'; + +void main() { + _logic('POICategory', poi_values, 'poi_category.dart'); +} + +// codegen function + +void _logic(String enumName, List values, String fileName) { + final StringBuffer enumStringBuffer = StringBuffer( + '/// This file is auto-generated. Do not modify it manually.\n\n'); + + enumStringBuffer.write('enum $enumName {\n'); + for (final value in values) { + final isLast = value == values.last; + String camelCaseValue = _toCamelCase(value); + if (isLast) { + enumStringBuffer.write(' ${camelCaseValue}(\'${value}\');\n'); + } else { + enumStringBuffer.write(' ${camelCaseValue}(\'${value}\'),\n'); + } + } + enumStringBuffer.write('\n'); + enumStringBuffer.write(' const $enumName(this.value);\n'); + enumStringBuffer.write(' final String value;\n'); + enumStringBuffer.write('}\n'); + + enumStringBuffer.write('\n'); + + // Extension Method + enumStringBuffer.write('extension ${enumName}Extension on $enumName {\n'); + enumStringBuffer.write(" $enumName? fromString(String? value) {\n"); + enumStringBuffer.write(" if (value == null) return null;\n"); + enumStringBuffer.write(" try {\n"); + enumStringBuffer.write( + " return $enumName.values.firstWhere((e) => e.value == value);\n"); + enumStringBuffer.write(" } catch (e) {\n"); + enumStringBuffer.write(" return null;\n"); + enumStringBuffer.write(" }\n"); + enumStringBuffer.write(" }\n"); + enumStringBuffer.write("}\n"); + + final File file = File('lib/generated_enums/$fileName'); + if (file.existsSync()) { + file.deleteSync(); + } + file.writeAsStringSync(enumStringBuffer.toString()); + + print('Enum written to file.'); +} + +String _toCamelCase(String value) { + final List parts = + value.contains(' ') ? value.split(' ') : value.split('_'); + final StringBuffer camelCaseStringBuffer = StringBuffer(parts[0]); + + for (int i = 1; i < parts.length; i++) { + camelCaseStringBuffer + .write(parts[i][0].toUpperCase() + parts[i].substring(1)); + } + + return camelCaseStringBuffer.toString(); +} diff --git a/scripts/enum_values.dart b/scripts/enum_values.dart new file mode 100644 index 0000000..af0bbe7 --- /dev/null +++ b/scripts/enum_values.dart @@ -0,0 +1,429 @@ +final poi_values = [ + "advertising_agency", + "african_restaurant", + "airport", + "airport_gate", + "airport_terminal", + "alternative_healthcare", + "american_restaurant", + "animal_shelter", + "antique_shop", + "aquarium", + "arcade", + "art", + "art_gallery", + "arts_and_craft_store", + "arts_center", + "asian_restaurant", + "assisted_living_facility", + "atm", + "auto_repair", + "baby_goods_shop", + "bagel_shop", + "baggage_claim", + "bakery", + "bank", + "bar", + "barbeque_restaurant", + "baseball_field", + "baseball_stadium", + "basketball_court", + "basketball_stadium", + "beach", + "beach_bar", + "beauty_store", + "bed_and_breakfast", + "beer_bar", + "bicycle_shop", + "biergarten", + "bike_rental", + "billiards", + "boat_rental", + "book_store", + "bookmaker", + "boutique", + "bowling_alley", + "boxing_gym", + "brazilian_restaurant", + "breakfast_restaurant", + "brewery", + "bridal_shop", + "bridge", + "brunch_restaurant", + "bubble_tea", + "buffet_restaurant", + "burger_restaurant", + "bus_station", + "bus_stop", + "butcher_shop", + "cafe", + "camera_shop", + "campground", + "canal", + "cannabis_dispensary", + "car_dealership", + "car_rental", + "car_wash", + "care_services", + "carpet_cleaner", + "carpet_store", + "carribean_restaurant", + "casino", + "cave", + "cemetery", + "chairlift", + "champagne_bar", + "charging_station", + "charity", + "check_cashing", + "cheese_shop", + "childcare", + "chinese_restaurant", + "chiropractor", + "chocolate_shop", + "church", + "cinema", + "climbing", + "climbing_gym", + "clothing", + "clothing_store", + "cobbler", + "cocktail_bar", + "coffee", + "coffee_roaster", + "coffee_shop", + "college", + "community_center", + "community_college", + "concert_hall", + "conference_center", + "convenience_store", + "copyshop", + "counselling", + "courthouse", + "coworking_space", + "creole_restaurant", + "cricket_club", + "cruise", + "cuban_restaurant", + "currency_exchange", + "dance_studio", + "deli", + "dentist", + "department_store", + "design_studio", + "dessert_shop", + "dialysis_center", + "diner_restaurant", + "disc_golf_course", + "discount_store", + "distillery", + "dive_bar", + "doctors_office", + "dog_park", + "donut_shop", + "dormitory", + "driving_range", + "driving_school", + "dry_cleaners", + "duty_free_shop", + "education", + "electronics_shop", + "elementary_school", + "embassy", + "emergency_room", + "employment_agency", + "english_restaurant", + "entertainment", + "equipment_rental", + "event_planner", + "event_space", + "exhibit", + "fabric_store", + "factory", + "fair_grounds", + "farm", + "fashion_accessory_shop", + "fast_food", + "field", + "filipino_restaurant", + "financial_services", + "fire_station", + "fireworks_store", + "fish_and_chips_restaurant", + "fishing", + "fishing_store", + "fishmonger", + "fitness_center", + "florist", + "food", + "food_and_drink", + "food_court", + "food_truck", + "football_stadium", + "forest", + "fountain", + "frame_store", + "french_restaurant", + "frozen_yogurt_shop", + "funeral_home", + "furniture_maker", + "furniture_store", + "garden", + "garden_store", + "gas_station", + "gastropub", + "gay_bar", + "german_restaurant", + "gift_shop", + "go_kart_racing", + "golf_course", + "government", + "government_offices", + "greek_restaurant", + "grocery", + "gun_store", + "gymnastics", + "hairdresser", + "hardware_store", + "hawaiian_restaurant", + "health_food_store", + "health_services", + "herbalist", + "high_school", + "historic_site", + "hobby_shop", + "hockey_stadium", + "home_repair", + "hookah_lounge", + "hospital", + "hostel", + "hot_dog_stand", + "hotel", + "hotel_bar", + "hunting_store", + "ice_cream", + "ice_rink", + "indian_restaurant", + "indonesian_restaurant", + "indoor_cycling", + "information_technology_company", + "insurance_broker", + "internet_cafe", + "island", + "italian_restaurant", + "japanese_restaurant", + "jewelry_store", + "juice_bar", + "karaoke_bar", + "kindergarten", + "kitchen_store", + "korean_barbeque_restaurant", + "korean_restaurant", + "laboratory", + "lake", + "landscaping", + "language_school", + "laser_tag", + "latin_american_restaurant", + "laundry", + "lawyer", + "leather_goods", + "library", + "lighthouse", + "lighting_store", + "liquor_store", + "locksmith", + "lodging", + "lounge", + "luggage_store", + "marina", + "market", + "martial_arts_studio", + "massage_shop", + "mattress_store", + "medical_clinic", + "medical_laboratory", + "medical_practice", + "medical_supply_store", + "mediterranean_restaurant", + "mexican_restaurant", + "middle_eastern_restaurant", + "military_base", + "miniature_golf", + "monument", + "mosque", + "motel", + "motorcycle_dealer", + "motorsports_store", + "mountain", + "museum", + "music_school", + "music_shop", + "music_venue", + "nail_salon", + "nature_reserve", + "news_kiosk", + "nightclub", + "nightlife", + "nongovernmental_organization", + "noodle_restaurant", + "notary", + "observatory", + "office", + "optician", + "optometrist", + "outdoors", + "outdoors_store", + "outlet_store", + "paper_goods_store", + "park", + "parking_lot", + "party_store", + "pawnshop", + "peruvian_restaurant", + "pet_store", + "pharmacy", + "phone_store", + "photo_lab", + "photo_store", + "photographer", + "physiotherapist", + "pier", + "pilates_studio", + "pizza_restaurant", + "place_of_worship", + "planetarium", + "playground", + "plaza", + "police_station", + "political_party_office", + "pop_up_shop", + "portuguese_restaurant", + "post_office", + "prison", + "psychic", + "psychological_services", + "psychotherapist", + "pub", + "public_artwork", + "public_transportation_station", + "racetrack", + "radio_studio", + "railway_platform", + "railway_station", + "ramen_restaurant", + "real_estate_agent", + "recording_studio", + "recreation_center", + "recycling_center", + "rehabilitation_center", + "repair_shop", + "resort", + "rest_area", + "restaurant", + "river", + "sake_bar", + "salad_bar", + "salon", + "sandwich_shop", + "school", + "scuba_diving_shop", + "seafood_restaurant", + "services", + "sewing_shop", + "shipping_store", + "shoe_repair", + "shoe_store", + "shopping", + "shopping_mall", + "skatepark", + "ski_area", + "ski_shop", + "snack_bar", + "soccer_field", + "social_club", + "spa", + "spanish_restaurant", + "speakeasy", + "sports", + "sports_bar", + "sports_center", + "sports_club", + "sports_shop", + "stable", + "stadium", + "steakhouse", + "storage", + "stripclub", + "studio", + "summer_camp", + "supermarket", + "surf_spot", + "surfboard_store", + "sushi_restaurant", + "swimming_pool", + "synagogue", + "taco_shop", + "tailor", + "tanning_salon", + "tapas_restaurant", + "tattoo_parlour", + "tax_advisor", + "taxi", + "teahouse", + "television_studio", + "temple", + "tennis_courts", + "thai_restaurant", + "theatre", + "theme_park", + "theme_park_attraction", + "thrift_shop", + "tiki_bar", + "tobacco_shop", + "tourist_attraction", + "tourist_information", + "tours", + "townhall", + "toy_store", + "track", + "trade_school", + "trailhead", + "transportation", + "travel agency", + "treecare", + "tunnel", + "turkish_coffeehouse", + "turkish_restaurant", + "tutor", + "university", + "university_book_store", + "university_building", + "university_laboratory", + "vacation_rental", + "vape_shop", + "variety_store", + "veterinarian", + "video_game_store", + "video_store", + "vietnamese_restaurant", + "viewpoint", + "vineyard", + "warehouse", + "waste_disposal", + "waste_transfer_station", + "watch_store", + "water_park", + "waterfall", + "whiskey_bar", + "wholesale_store", + "windmill", + "wine_bar", + "winery", + "wings_joint", + "womens_clothing_store", + "yoga_studio", + "zoo", + "zoo_exhibit" +]; diff --git a/test/mapbox_search_test.dart b/test/forward_geocoding_test.dart similarity index 84% rename from test/mapbox_search_test.dart rename to test/forward_geocoding_test.dart index 9177836..3d285a7 100644 --- a/test/mapbox_search_test.dart +++ b/test/forward_geocoding_test.dart @@ -10,15 +10,15 @@ void main() async { expect(MAPBOX_KEY, isNotEmpty); }); - test("Places search test", () async { - PlacesSearch search = PlacesSearch( + test("Forward GeoCoding Test", () async { + GeoCoding geocoding = GeoCoding( apiKey: MAPBOX_KEY, country: "BR", limit: 5, types: [PlaceType.address, PlaceType.place], ); - var searchPlace = search.getPlaces( + var searchPlace = geocoding.getPlaces( "central park", proximity: Location( lat: -19.984634, diff --git a/test/reverse_geocoding_test.dart b/test/reverse_geocoding_test.dart index e9232ef..5caee1d 100644 --- a/test/reverse_geocoding_test.dart +++ b/test/reverse_geocoding_test.dart @@ -11,7 +11,7 @@ void main() async { }); test("ReverseGeoCoding address search with limit test", () async { - ReverseGeoCoding reverseGeoCoding = ReverseGeoCoding( + GeoCoding reverseGeoCoding = GeoCoding( apiKey: MAPBOX_KEY, country: "BR", limit: 2, @@ -29,7 +29,7 @@ void main() async { expect(addresses, completion(hasLength(2))); }); test("ReverseGeoCoding address search without limit test", () async { - ReverseGeoCoding reverseGeoCoding = ReverseGeoCoding( + GeoCoding reverseGeoCoding = GeoCoding( apiKey: MAPBOX_KEY, country: "BR", types: [PlaceType.address, PlaceType.place], diff --git a/test/search_box_api_test.dart b/test/search_box_api_test.dart new file mode 100644 index 0000000..2abc8f8 --- /dev/null +++ b/test/search_box_api_test.dart @@ -0,0 +1,42 @@ +import 'package:mapbox_search/mapbox_search.dart'; +import 'package:test/test.dart'; +import 'credentials.dart' as c; + +void main() async { + final MAPBOX_KEY = c.MAPBOX_KEY; + + test("Has api key", () { + expect(MAPBOX_KEY, isNotNull); + expect(MAPBOX_KEY, isNotEmpty); + }); + + test("Places search test", () async { + SearchBoxAPI search = SearchBoxAPI( + apiKey: MAPBOX_KEY, + limit: 6, + ); + + SuggestionResponse searchPlace = await search.getSuggestions( + "central", + ); + + expect(searchPlace, isA()); + expect(searchPlace.suggestions, isNotEmpty); + expect(searchPlace.suggestions, hasLength(6)); + }); + + test("Retrive Place by mapbox_id test", () async { + SearchBoxAPI search = SearchBoxAPI( + apiKey: MAPBOX_KEY, + limit: 6, + ); + + RetrieveResonse searchPlace = await search.getPlace( + "dXJuOm1ieHJldDowcE1SX2QteDlESmVPTm5lRlRMU3h0UjllWlFya1JVb2huLWhuOVJ3Z1RTUjdQQ0QyMUkta3hOTkNVRGp2Y1FxMDBoUzM3dk9oVzRCclBNWHg0SXl4Mm1RS250UE1HTmxKV2NBOW1mdE9lbGtBdGpzYVZDcVZwQ3hneUxQWl9UbkZkdS05WkRnbktQeTRLM2FwS2xNOVlpUVNyS2ZUak5wWGZIc3g0SHUtM3pnYUVDMWJKQVpEcDl3cktyMHlhUXAxUHY3MlVyeWd1a0l2Tk0zRVlVWG1ESW9DX09qM0VGajRFLVJkeGlSZEhRdDl3bzN3VkNmQm1ZZ2ExcExBaWY3UlI1RElwMDQzdnpMMTNVWlBxRWQ4NGE2X2RpenZvWjhWR2RsNF9VSHNReDlSUzdNb0RCZ0xTemt1VF9xREg0cEE1M2xVc182a3BsUERQZnRMM2U4N0d4a2tvWG84Q0g3UnEwUVJ6TTdYT296SUNRSTItb1JYX3VzZ2k2aHh1aC1tMjhUc0xQY1NOazBlclZJQURxdFZSWFdkem44YzdKZnBCcFFmcGR3WTJadkRHZ2s4bzMwZWlwTDdyek1WSGpqZjFWaDJhUzJmOGpLZFBubzFWXzBRRktBN3BHQnJneUlhX2JsT1ZwUjlYbk1aS3RDRDBXTldFU1FJMVNJU0EtRnY3T1lUS2ZYTGxqT3laYWNGMmJrU3hIMVBFdHhfUEhFUzR2TnlydHZkWncwdG5IT3d1OEZGczZSam9IaUt6czcxcTlZbG1RV0ZqTjh5TWVKRlJBZUJiR2VmZG5zV2hPVk9Ec3BzM3BZTkl2c1MwNjVJMUNxN0xwV0tVRUpNcnhkd01fUmplZWZmTjc2T1h1aGFCcU9hcGpUek9WUDBvcnZYUUpqVHdQQzNSdDVWUEMxQzBZUEJON1lBeFhVMGJxdnphSTBuNVJ5b25rdVlYU0ZTaWVnRGZVRE1CVldMeVhqUlpMcWNabzhCcms0RzFSRkZrVzJDSERkNFlXV2gxSXllWm9aSTJKZkliSzNSUU9MRDZScGhZd0JBTjJWc2hSdTlSVzZLcTM0WVNVVEZ1T3l2cGhkb2VUemhaRURadGMzLXJtSERUR3ZWS29ic3YzbjUxQmdJUncwYzVuLUcwZTk3Sm1TSGtZdlNycWJKbTdfMzJUZXhXdDlSUHI3ckNIdk03WjlZZmxMVDRqbWtjU182TkI4TFYxb1QxSFp1bFhkMmRwRHV5ZlJhTGVWWWFIVjJhY0NERWNaQjNGSHZ5WG5naVhlQWxQTWdfY2JjanVuSzkwOVhNMVpFS1BENGhWclBSdVBTQkFjTFBHNzdpSktTV0FmdzZqaUFkaU5CT05aSWhiSXlKbmdZakZSU3FucFRPSlI2RjhBM1FtaGh2empxT2lZZHk4VFdxV3NxaUpCMUFUNVQ5VVM2WEJncU0yQjJ2TWF2bF9uZUFwU3ltcXBGTTdEa1hZZ3lTU3BnTFFpQjJ5RHdJVDY1OWwyR3ZReDZrRnJ2V29LdDc2UkhlOWc0ZFlrZ0N4VkcxWnZlcWlyTHo0RWFuelBaR3gzTk1wdk1qMVZ6bjVzeUlFdVBEUXE5Ym5DcEF5LVA0UTdmdVlQV29GU2pqWmloYWtMbm1IOXYxRkFNNTdNMGJEZk5QQTdjR2tZRmxnSW5lUGZZU0dwVlpfUzZkeV8zZDdsTlkwTXNqaW0td2w5cTJhb1E3UzZSUEI5X1BDR3dFbjhHOUR4dHREcm9TN3VWQ25mTmNjSjhwZmVPMm9hd3N1aUNYZlhiRExnQ0IwNHplZ2ZoUk5vTDJMc3BxVjJHRkdpLVBZNmZjOTB6VTNJdkNwYVNDeG4yaF94QmpjWDBNdXRZNXpiVEs2Tmp1dnQtZkwxWXpoVkxoVGxwbkhfOFhrQVlZSTRYNmN3Q2UzRnlBcEFNemY5VzdKVFNiZEpvZmRKOUNHM1d4ZGR4bE5FWkJUM0hBTG9ieGI3MGF6bld3SUlyZHo5UFk1bHBQb3VDODN1NFM3RDdhay1TeG1FNTd3eTZRZ0pGX1ZETU0zZ0Q1WVBsZ05RV180WnUxX3hjd0ZFMXJKWmNPczdWd1NabzZDRXVXSHJtVmRtSGp4aVJSNjMwdz09", + ); + + expect(searchPlace, isA()); + expect(searchPlace.features, isNotEmpty); + expect(searchPlace.features, hasLength(1)); + }); +}